mirror of
https://github.com/musix-org/musix-oss
synced 2025-06-17 01:16:00 +00:00
Modules
This commit is contained in:
2
node_modules/ffmpeg/.npmignore
generated
vendored
Normal file
2
node_modules/ffmpeg/.npmignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/nbproject/private/
|
||||
/nbproject/
|
349
node_modules/ffmpeg/README.md
generated
vendored
Normal file
349
node_modules/ffmpeg/README.md
generated
vendored
Normal file
@ -0,0 +1,349 @@
|
||||
node-ffmpeg
|
||||
===========
|
||||
|
||||
[FFmpeg](http://ffmpeg.org/) module for [Node](http://nodejs.org/). This library provides a set of functions and utilities to abstract commands-line usage of ffmpeg. To use this library requires that ffmpeg is already installed (including all necessary encoding libraries like libmp3lame or libx264)
|
||||
|
||||
You can install this module using [npm](http://github.com/isaacs/npm):
|
||||
|
||||
npm install ffmpeg
|
||||
|
||||
## Usage
|
||||
|
||||
To start using this library, you must include it in your project and then you can either use the callback function or through the [promise](https://github.com/cujojs/when) library:
|
||||
|
||||
var ffmpeg = require('ffmpeg');
|
||||
|
||||
Use the callback function
|
||||
|
||||
try {
|
||||
new ffmpeg('/path/to/your_movie.avi', function (err, video) {
|
||||
if (!err) {
|
||||
console.log('The video is ready to be processed');
|
||||
} else {
|
||||
console.log('Error: ' + err);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e.code);
|
||||
console.log(e.msg);
|
||||
}
|
||||
|
||||
Use the approach with the library promise
|
||||
|
||||
try {
|
||||
var process = new ffmpeg('/path/to/your_movie.avi');
|
||||
process.then(function (video) {
|
||||
console.log('The video is ready to be processed');
|
||||
}, function (err) {
|
||||
console.log('Error: ' + err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e.code);
|
||||
console.log(e.msg);
|
||||
}
|
||||
|
||||
## The video object
|
||||
|
||||
Each time you create a new instance, this library provides a new object to retrieve the information of the video, the ffmpeg configuration and all methods to make the necessary conversions:
|
||||
|
||||
try {
|
||||
var process = new ffmpeg('/path/to/your_movie.avi');
|
||||
process.then(function (video) {
|
||||
// Video metadata
|
||||
console.log(video.metadata);
|
||||
// FFmpeg configuration
|
||||
console.log(video.info_configuration);
|
||||
}, function (err) {
|
||||
console.log('Error: ' + err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e.code);
|
||||
console.log(e.msg);
|
||||
}
|
||||
|
||||
## Preset functions
|
||||
|
||||
The video object contains a set of functions that allow you to perform specific operations independent of the settings for the conversion. In all the functions you can use the approach with the callback function or with the promise object
|
||||
|
||||
### *video.fnExtractSoundToMP3 (destionationFileName, callback)*
|
||||
|
||||
This function extracts the audio stream of a video into an mp3 file
|
||||
|
||||
Params:
|
||||
|
||||
* __destionationFileName__: Full path of the new file:
|
||||
> /path/to/your_audio_file.mp3
|
||||
|
||||
* __callback__: *(optional)* If specified at the end of the process it will return the path of the new audio file:
|
||||
> function (error, file)
|
||||
|
||||
Example:
|
||||
|
||||
try {
|
||||
var process = new ffmpeg('/path/to/your_movie.avi');
|
||||
process.then(function (video) {
|
||||
// Callback mode
|
||||
video.fnExtractSoundToMP3('/path/to/your_audio_file.mp3', function (error, file) {
|
||||
if (!error)
|
||||
console.log('Audio file: ' + file);
|
||||
});
|
||||
}, function (err) {
|
||||
console.log('Error: ' + err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e.code);
|
||||
console.log(e.msg);
|
||||
}
|
||||
|
||||
### *video.fnExtractFrameToJPG(destinationFolder, settings, callback)*
|
||||
|
||||
This function takes care of extracting one or more frames from the video that is being developed. At the end of the operation will return an array containing the list of extracted images
|
||||
|
||||
Params:
|
||||
|
||||
* __destinationFolder__: Destination folder for the frames generated:
|
||||
> /path/to/save_your_frames
|
||||
|
||||
* __settings__: *(optional)* Settings to change the default settings:
|
||||
|
||||
{
|
||||
start_time : null // Start time to recording
|
||||
, duration_time : null // Duration of recording
|
||||
, frame_rate : null // Number of the frames to capture in one second
|
||||
, size : null // Dimension each frame
|
||||
, number : null // Total frame to capture
|
||||
, every_n_frames : null // Frame to capture every N frames
|
||||
, every_n_seconds : null // Frame to capture every N seconds
|
||||
, every_n_percentage : null // Frame to capture every N percentage range
|
||||
, keep_pixel_aspect_ratio : true // Mantain the original pixel video aspect ratio
|
||||
, keep_aspect_ratio : true // Mantain the original aspect ratio
|
||||
, padding_color : 'black' // Padding color
|
||||
, file_name : null // File name
|
||||
}
|
||||
|
||||
* __callback__: *(optional)* If specified at the end of the process will be returned list of paths of frames created:
|
||||
> function (error, files)
|
||||
|
||||
Example:
|
||||
|
||||
try {
|
||||
var process = new ffmpeg('/path/to/your_movie.avi');
|
||||
process.then(function (video) {
|
||||
// Callback mode
|
||||
video.fnExtractFrameToJPG('/path/to/save_your_frames', {
|
||||
frame_rate : 1,
|
||||
number : 5,
|
||||
file_name : 'my_frame_%t_%s'
|
||||
}, function (error, files) {
|
||||
if (!error)
|
||||
console.log('Frames: ' + files);
|
||||
});
|
||||
}, function (err) {
|
||||
console.log('Error: ' + err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e.code);
|
||||
console.log(e.msg);
|
||||
}
|
||||
|
||||
### *video.fnAddWatermark(watermarkPath, newFilepath, settings, callback)*
|
||||
|
||||
This function takes care of adding a watermark to the video that is being developed. You can specify the exact position in which position the image
|
||||
|
||||
Params:
|
||||
|
||||
* __watermarkPath__: The full path where the image is stored to add as watermark:
|
||||
> /path/to/retrieve/watermark_file.png
|
||||
|
||||
* __newFilepath__: *(optional)* Name of the new video. If not specified will be created by the function:
|
||||
> /path/to/save/your_file_video.mp4
|
||||
|
||||
* __settings__: *(optional)* Settings to change the default settings:
|
||||
|
||||
{
|
||||
position : "SW" // Position: NE NC NW SE SC SW C CE CW
|
||||
, margin_nord : null // Margin nord
|
||||
, margin_sud : null // Margin sud
|
||||
, margin_east : null // Margin east
|
||||
, margin_west : null // Margin west
|
||||
};
|
||||
|
||||
* __callback__: *(optional)* If specified at the end of the process it will return the path of the new video containing the watermark:
|
||||
> function (error, files)
|
||||
|
||||
Example:
|
||||
|
||||
try {
|
||||
var process = new ffmpeg('/path/to/your_movie.avi');
|
||||
process.then(function (video) {
|
||||
// Callback mode
|
||||
video.fnAddWatermark('/path/to/retrieve/watermark_file.png', '/path/to/save/your_file_video.mp4', {
|
||||
position : 'SE'
|
||||
}, function (error, file) {
|
||||
if (!error)
|
||||
console.log('New video file: ' + file);
|
||||
});
|
||||
}, function (err) {
|
||||
console.log('Error: ' + err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e.code);
|
||||
console.log(e.msg);
|
||||
}
|
||||
|
||||
## Custom settings
|
||||
|
||||
In addition to the possibility of using the preset, this library provides a variety of settings with which you can modify to your liking settings for converting video
|
||||
|
||||
* __video.setDisableAudio()__: Disables audio encoding
|
||||
|
||||
* __video.setDisableVideo()__: Disables video encoding
|
||||
|
||||
* __video.setVideoFormat(format)__: Sets the new video format. Example:
|
||||
|
||||
video.setVideoFormat('avi')
|
||||
|
||||
* __video.setVideoCodec(codec)__: Sets the new audio codec. Example:
|
||||
|
||||
video.setVideoCodec('mpeg4')
|
||||
|
||||
* __video.setVideoBitRate(bitrate)__: Sets the video bitrate in kb. Example:
|
||||
|
||||
video.setVideoBitRate(1024)
|
||||
|
||||
* __video.setVideoFrameRate(framerate)__: Sets the framerate of the video. Example:
|
||||
|
||||
video.setVideoFrameRate(25)
|
||||
|
||||
* __video.setVideoStartTime(time)__: Sets the start time. You can specify the value in seconds or in date time format. Example:
|
||||
|
||||
// Seconds
|
||||
video.setVideoStartTime(13)
|
||||
|
||||
// Date time format
|
||||
video.setVideoStartTime('00:00:13')
|
||||
|
||||
* __video.setVideoDuration(duration)__: Sets the duration. You can specify the value in seconds or in date time format. Example:
|
||||
|
||||
// Seconds
|
||||
video.setVideoDuration(100)
|
||||
|
||||
// Date time format
|
||||
video.setVideoDuration('00:01:40')
|
||||
|
||||
* __video.setVideoAspectRatio(aspect)__: Sets the new aspetc ratio. You can specify the value with a number or with a string in the format 'xx:xx'. Example:
|
||||
|
||||
// Value
|
||||
video.setVideoAspectRatio(1.77)
|
||||
|
||||
// Format xx:xx
|
||||
video.setVideoAspectRatio('16:9')
|
||||
|
||||
* __video.setVideoSize(size, keepPixelAspectRatio, keepAspectRatio, paddingColor)__: Set the size of the video. This library can handle automatic resizing of the video. You can also apply a padding automatically keeping the original aspect ratio
|
||||
|
||||
The following size formats are allowed to be passed to _size_:
|
||||
|
||||
> 640x480 _Fixed size (plain ffmpeg way)_
|
||||
|
||||
> 50% _Percental resizing_
|
||||
|
||||
> ?x480 _Fixed height, calculate width_
|
||||
|
||||
> 640x? _Fixed width, calculate height_
|
||||
|
||||
Example:
|
||||
|
||||
// In this example, the video will be automatically resized to 640 pixels wide and will apply a padding white
|
||||
video.setVideoSize('640x?', true, true, '#fff')
|
||||
|
||||
// In this example, the video will be resized to 640x480 pixel, and if the aspect ratio is different the video will be stretched
|
||||
video.setVideoSize('640x480', true, false)
|
||||
|
||||
* __video.setAudioCodec(codec)__: Sets the new audio codec. Example:
|
||||
|
||||
video.setAudioCodec('libfaac')
|
||||
|
||||
* __video.setAudioFrequency(frequency)__: Sets the audio sample frequency for audio outputs in kb. Example:
|
||||
|
||||
video.setAudioFrequency(48)
|
||||
|
||||
* __video.setAudioChannels(channel)__: Sets the number of audio channels. Example:
|
||||
|
||||
video.setAudioChannels(2)
|
||||
|
||||
* __video.setAudioBitRate(bitrate)__: Sets the audio bitrate in kb. Example:
|
||||
|
||||
video.setAudioBitRate(128)
|
||||
|
||||
* __video.setAudioQuality(quality)__: Sets the audio quality. Example:
|
||||
|
||||
video.setAudioQuality(128)
|
||||
|
||||
* __video.setWatermark(watermarkPath, settings)__: Sets the watermark. You must specify the path where the image is stored to be inserted as watermark
|
||||
|
||||
The possible settings (the values shown are the default):
|
||||
|
||||
* **position : "SW"**
|
||||
|
||||
Position: NE NC NW SE SC SW C CE CW
|
||||
|
||||
* **margin_nord : null**
|
||||
|
||||
Margin nord (specify in pixel)
|
||||
|
||||
* **margin_sud : null**
|
||||
|
||||
Margin sud (specify in pixel)
|
||||
|
||||
* **margin_east : null**
|
||||
|
||||
Margin east (specify in pixel)
|
||||
|
||||
* **margin_west : null**
|
||||
|
||||
Margin west (specify in pixel)
|
||||
|
||||
Example:
|
||||
|
||||
// In this example will be added the watermark at the bottom right of the video
|
||||
video.setWatermark('/path/to/retrieve/watermark_file.png')
|
||||
|
||||
## Add custom options
|
||||
|
||||
If the ffmpeg parameters are not present in the list of available function you can add it manually through the following function
|
||||
|
||||
**video.addCommand(command, argument)**
|
||||
|
||||
Example:
|
||||
|
||||
// In this example will be changed the output to avi format
|
||||
video.addCommand('-f', 'avi');
|
||||
|
||||
## Save the file
|
||||
|
||||
After setting the desired parameters have to start the conversion process. To do this you must call the function 'save'. This method takes as input the final destination of the file and optionally a callback function. If the function callback is not specified it's possible use the promise object.
|
||||
|
||||
**video.save(destionationFileName, callback)**
|
||||
|
||||
Example:
|
||||
|
||||
try {
|
||||
var process = new ffmpeg('/path/to/your_movie.avi');
|
||||
process.then(function (video) {
|
||||
|
||||
video
|
||||
.setVideoSize('640x?', true, true, '#fff')
|
||||
.setAudioCodec('libfaac')
|
||||
.setAudioChannels(2)
|
||||
.save('/path/to/save/your_movie.avi', function (error, file) {
|
||||
if (!error)
|
||||
console.log('Video file: ' + file);
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
console.log('Error: ' + err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e.code);
|
||||
console.log(e.msg);
|
||||
}
|
1
node_modules/ffmpeg/index.js
generated
vendored
Normal file
1
node_modules/ffmpeg/index.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('./lib/ffmpeg');
|
8
node_modules/ffmpeg/lib/configs.js
generated
vendored
Normal file
8
node_modules/ffmpeg/lib/configs.js
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Basic configuration
|
||||
*/
|
||||
module.exports = function () {
|
||||
this.encoding = 'utf8';
|
||||
this.timeout = 0;
|
||||
this.maxBuffer = 200 * 1024
|
||||
}
|
35
node_modules/ffmpeg/lib/errors.js
generated
vendored
Normal file
35
node_modules/ffmpeg/lib/errors.js
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
var util = require('util');
|
||||
|
||||
// Error list with code and message
|
||||
var list = {
|
||||
'empty_input_filepath' : { 'code' : 100, 'msg' : 'The input file path can not be empty' }
|
||||
, 'input_filepath_must_be_string' : { 'code' : 101, 'msg' : 'The input file path must be a string' }
|
||||
, 'invalid_option_name' : { 'code' : 102, 'msg' : 'The option "%s" is invalid. Check the list of available options' }
|
||||
, 'fileinput_not_exist' : { 'code' : 103, 'msg' : 'The input file does not exist' }
|
||||
, 'format_not_supported' : { 'code' : 104, 'msg' : 'The format "$s" is not supported by the version of ffmpeg' }
|
||||
, 'audio_channel_is_invalid' : { 'code' : 105, 'msg' : 'The audio channel "$s" is not valid' }
|
||||
, 'mkdir' : { 'code' : 106, 'msg' : 'Error occurred during creation folder: $s' }
|
||||
, 'extract_frame_invalid_everyN_options' : { 'code' : 107, 'msg' : 'You can specify only one option between everyNFrames and everyNSeconds' }
|
||||
, 'invalid_watermark' : { 'code' : 108, 'msg' : 'The watermark "%s" does not exists' }
|
||||
, 'invalid_watermark_position' : { 'code' : 109, 'msg' : 'Invalid watermark position "%s"' }
|
||||
, 'size_format' : { 'code' : 110, 'msg' : 'The format "%s" not supported by the function "setSize"' }
|
||||
, 'resolution_square_not_defined' : { 'code' : 111, 'msg' : 'The resolution for pixel aspect ratio is not defined' }
|
||||
, 'command_already_exists' : { 'code' : 112, 'msg' : 'The command "%s" already exists' }
|
||||
, 'codec_not_supported' : { 'code' : 113, 'msg' : 'The codec "$s" is not supported by the version of ffmpeg' }
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the error by the codename
|
||||
*/
|
||||
var renderError = function (codeName) {
|
||||
// Get the error object by the codename
|
||||
var params = [list[codeName].msg];
|
||||
// Get the possible arguments
|
||||
if (arguments.length > 1)
|
||||
params = params.concat(Array.prototype.slice.call(arguments, 1));
|
||||
// Call the function for replace the letter '%s' with the found arguments
|
||||
return { 'code' : list[codeName].code, 'msg' : util.format.apply(this, params) };
|
||||
}
|
||||
|
||||
module.exports.list = list;
|
||||
module.exports.renderError = renderError;
|
251
node_modules/ffmpeg/lib/ffmpeg.js
generated
vendored
Normal file
251
node_modules/ffmpeg/lib/ffmpeg.js
generated
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
var when = require('when')
|
||||
, fs = require('fs');
|
||||
|
||||
var errors = require('./errors')
|
||||
, utils = require('./utils')
|
||||
, configs = require('./configs')
|
||||
, video = require('./video');
|
||||
|
||||
var ffmpeg = function (/* inputFilepath, settings, callback */) {
|
||||
|
||||
/**
|
||||
* Retrieve the list of the codec supported by the ffmpeg software
|
||||
*/
|
||||
var _ffmpegInfoConfiguration = function (settings) {
|
||||
// New 'promise' instance
|
||||
var deferred = when.defer();
|
||||
// Instance the new arrays for the format
|
||||
var format = { modules : new Array(), encode : new Array(), decode : new Array() };
|
||||
// Make the call to retrieve information about the ffmpeg
|
||||
utils.exec(['ffmpeg','-formats','2>&1'], settings, function (error, stdout, stderr) {
|
||||
// Get the list of modules
|
||||
var configuration = /configuration:(.*)/.exec(stdout);
|
||||
// Check if exists the configuration
|
||||
if (configuration) {
|
||||
// Get the list of modules
|
||||
var modules = configuration[1].match(/--enable-([a-zA-Z0-9\-]+)/g);
|
||||
// Scan all modules
|
||||
for (var indexModule in modules) {
|
||||
// Add module to the list
|
||||
format.modules.push(/--enable-([a-zA-Z0-9\-]+)/.exec(modules[indexModule])[1]);
|
||||
}
|
||||
}
|
||||
// Get the codec list
|
||||
var codecList = stdout.match(/ (DE|D|E) (.*) {1,} (.*)/g);
|
||||
// Scan all codec
|
||||
for (var i in codecList) {
|
||||
// Get the match value
|
||||
var match = / (DE|D|E) (.*) {1,} (.*)/.exec(codecList[i]);
|
||||
// Check if match is valid
|
||||
if (match) {
|
||||
// Get the value from the match
|
||||
var scope = match[1].replace(/\s/g,'')
|
||||
, extension = match[2].replace(/\s/g,'');
|
||||
// Check which scope is best suited
|
||||
if (scope == 'D' || scope == 'DE')
|
||||
format.decode.push(extension);
|
||||
if (scope == 'E' || scope == 'DE')
|
||||
format.encode.push(extension);
|
||||
}
|
||||
}
|
||||
// Returns the list of supported formats
|
||||
deferred.resolve(format);
|
||||
});
|
||||
// Return 'promise' instance
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the video info
|
||||
*/
|
||||
var _videoInfo = function (fileInput, settings) {
|
||||
// New 'promise' instance
|
||||
var deferred = when.defer();
|
||||
// Make the call to retrieve information about the ffmpeg
|
||||
utils.exec(['ffmpeg','-i',fileInput,'2>&1'], settings, function (error, stdout, stderr) {
|
||||
// Perse output for retrieve the file info
|
||||
var filename = /from \'(.*)\'/.exec(stdout) || []
|
||||
, title = /(INAM|title)\s+:\s(.+)/.exec(stdout) || []
|
||||
, artist = /artist\s+:\s(.+)/.exec(stdout) || []
|
||||
, album = /album\s+:\s(.+)/.exec(stdout) || []
|
||||
, track = /track\s+:\s(.+)/.exec(stdout) || []
|
||||
, date = /date\s+:\s(.+)/.exec(stdout) || []
|
||||
, is_synched = (/start: 0.000000/.exec(stdout) !== null)
|
||||
, duration = /Duration: (([0-9]+):([0-9]{2}):([0-9]{2}).([0-9]+))/.exec(stdout) || []
|
||||
|
||||
, container = /Input #0, ([a-zA-Z0-9]+),/.exec(stdout) || []
|
||||
, video_bitrate = /bitrate: ([0-9]+) kb\/s/.exec(stdout) || []
|
||||
, video_stream = /Stream #([0-9\.]+)([a-z0-9\(\)\[\]]*)[:] Video/.exec(stdout) || []
|
||||
, video_codec = /Video: ([\w]+)/.exec(stdout) || []
|
||||
, resolution = /(([0-9]{2,5})x([0-9]{2,5}))/.exec(stdout) || []
|
||||
, pixel = /[SP]AR ([0-9\:]+)/.exec(stdout) || []
|
||||
, aspect = /DAR ([0-9\:]+)/.exec(stdout) || []
|
||||
, fps = /([0-9\.]+) (fps|tb\(r\))/.exec(stdout) || []
|
||||
|
||||
, audio_stream = /Stream #([0-9\.]+)([a-z0-9\(\)\[\]]*)[:] Audio/.exec(stdout) || []
|
||||
, audio_codec = /Audio: ([\w]+)/.exec(stdout) || []
|
||||
, sample_rate = /([0-9]+) Hz/i.exec(stdout) || []
|
||||
, channels = /Audio:.* (stereo|mono)/.exec(stdout) || []
|
||||
, audio_bitrate = /Audio:.* ([0-9]+) kb\/s/.exec(stdout) || []
|
||||
, rotate = /rotate[\s]+:[\s]([\d]{2,3})/.exec(stdout) || [];
|
||||
// Build return object
|
||||
var ret = {
|
||||
filename : filename[1] || ''
|
||||
, title : title[2] || ''
|
||||
, artist : artist[1] || ''
|
||||
, album : album[1] || ''
|
||||
, track : track[1] || ''
|
||||
, date : date[1] || ''
|
||||
, synched : is_synched
|
||||
, duration : {
|
||||
raw : duration[1] || ''
|
||||
, seconds : duration[1] ? utils.durationToSeconds(duration[1]) : 0
|
||||
}
|
||||
, video : {
|
||||
container : container[1] || ''
|
||||
, bitrate : (video_bitrate.length > 1) ? parseInt(video_bitrate[1], 10) : 0
|
||||
, stream : video_stream.length > 1 ? parseFloat(video_stream[1]) : 0.0
|
||||
, codec : video_codec[1] || ''
|
||||
, resolution : {
|
||||
w : resolution.length > 2 ? parseInt(resolution[2], 10) : 0
|
||||
, h : resolution.length > 3 ? parseInt(resolution[3], 10) : 0
|
||||
}
|
||||
, resolutionSquare : {}
|
||||
, aspect : {}
|
||||
, rotate : rotate.length > 1 ? parseInt(rotate[1], 10) : 0
|
||||
, fps : fps.length > 1 ? parseFloat(fps[1]) : 0.0
|
||||
}
|
||||
, audio : {
|
||||
codec : audio_codec[1] || ''
|
||||
, bitrate : audio_bitrate[1] || ''
|
||||
, sample_rate : sample_rate.length > 1 ? parseInt(sample_rate[1], 10) : 0
|
||||
, stream : audio_stream.length > 1 ? parseFloat(audio_stream[1]) : 0.0
|
||||
, channels : {
|
||||
raw : channels[1] || ''
|
||||
, value : (channels.length > 0) ? ({ stereo : 2, mono : 1 }[channels[1]] || 0) : ''
|
||||
}
|
||||
}
|
||||
};
|
||||
// Check if exist aspect ratio
|
||||
if (aspect.length > 0) {
|
||||
var aspectValue = aspect[1].split(":");
|
||||
ret.video.aspect.x = parseInt(aspectValue[0], 10);
|
||||
ret.video.aspect.y = parseInt(aspectValue[1], 10);
|
||||
ret.video.aspect.string = aspect[1];
|
||||
ret.video.aspect.value = parseFloat((ret.video.aspect.x / ret.video.aspect.y));
|
||||
} else {
|
||||
// If exists horizontal resolution then calculate aspect ratio
|
||||
if(ret.video.resolution.w > 0) {
|
||||
var gcdValue = utils.gcd(ret.video.resolution.w, ret.video.resolution.h);
|
||||
// Calculate aspect ratio
|
||||
ret.video.aspect.x = ret.video.resolution.w / gcdValue;
|
||||
ret.video.aspect.y = ret.video.resolution.h / gcdValue;
|
||||
ret.video.aspect.string = ret.video.aspect.x + ':' + ret.video.aspect.y;
|
||||
ret.video.aspect.value = parseFloat((ret.video.aspect.x / ret.video.aspect.y));
|
||||
}
|
||||
}
|
||||
// Save pixel ratio for output size calculation
|
||||
if (pixel.length > 0) {
|
||||
ret.video.pixelString = pixel[1];
|
||||
var pixelValue = pixel[1].split(":");
|
||||
ret.video.pixel = parseFloat((parseInt(pixelValue[0], 10) / parseInt(pixelValue[1], 10)));
|
||||
} else {
|
||||
if (ret.video.resolution.w !== 0) {
|
||||
ret.video.pixelString = '1:1';
|
||||
ret.video.pixel = 1;
|
||||
} else {
|
||||
ret.video.pixelString = '';
|
||||
ret.video.pixel = 0.0;
|
||||
}
|
||||
}
|
||||
// Correct video.resolution when pixel aspectratio is not 1
|
||||
if (ret.video.pixel !== 1 || ret.video.pixel !== 0) {
|
||||
if( ret.video.pixel > 1 ) {
|
||||
ret.video.resolutionSquare.w = parseInt(ret.video.resolution.w * ret.video.pixel, 10);
|
||||
ret.video.resolutionSquare.h = ret.video.resolution.h;
|
||||
} else {
|
||||
ret.video.resolutionSquare.w = ret.video.resolution.w;
|
||||
ret.video.resolutionSquare.h = parseInt(ret.video.resolution.h / ret.video.pixel, 10);
|
||||
}
|
||||
}
|
||||
// Returns the list of supported formats
|
||||
deferred.resolve(ret);
|
||||
});
|
||||
// Return 'promise' instance
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the info about ffmpeg's codec and about file
|
||||
*/
|
||||
var _getInformation = function (fileInput, settings) {
|
||||
var deferreds = [];
|
||||
// Add promise
|
||||
deferreds.push(_ffmpegInfoConfiguration(settings));
|
||||
deferreds.push(_videoInfo(fileInput, settings));
|
||||
// Return defer
|
||||
return when.all(deferreds);
|
||||
}
|
||||
|
||||
var __constructor = function (args) {
|
||||
// Check if exist at least one option
|
||||
if (args.length == 0 || args[0] == undefined)
|
||||
throw errors.renderError('empty_input_filepath');
|
||||
// Check if first argument is a string
|
||||
if (typeof args[0] != 'string')
|
||||
throw errors.renderError('input_filepath_must_be_string');
|
||||
// Get the input filepath
|
||||
var inputFilepath = args[0];
|
||||
// Check if file exist
|
||||
if (!fs.existsSync(inputFilepath))
|
||||
throw errors.renderError('fileinput_not_exist');
|
||||
|
||||
// New instance of the base configuration
|
||||
var settings = new configs();
|
||||
// Callback to call
|
||||
var callback = null;
|
||||
|
||||
// Scan all arguments
|
||||
for (var i = 1; i < args.length; i++) {
|
||||
// Check the type of variable
|
||||
switch (typeof args[i]) {
|
||||
case 'object' :
|
||||
utils.mergeObject(settings, args[i]);
|
||||
break;
|
||||
case 'function' :
|
||||
callback = args[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Building the value for return value. Check if the callback is not a function. In this case will created a new instance of the deferred class
|
||||
var deferred = typeof callback != 'function' ? when.defer() : { promise : null };
|
||||
|
||||
when(_getInformation(inputFilepath, settings), function (data) {
|
||||
// Check if the callback is a function
|
||||
if (typeof callback == 'function') {
|
||||
// Call the callback function e return the new instance of 'video' class
|
||||
callback(null, new video(inputFilepath, settings, data[0], data[1]));
|
||||
} else {
|
||||
// Positive response
|
||||
deferred.resolve(new video(inputFilepath, settings, data[0], data[1]));
|
||||
}
|
||||
}, function (error) {
|
||||
// Check if the callback is a function
|
||||
if (typeof callback == 'function') {
|
||||
// Call the callback function e return the error found
|
||||
callback(error, null);
|
||||
} else {
|
||||
// Negative response
|
||||
deferred.reject(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Return a possible promise instance
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
return __constructor.call(this, arguments);
|
||||
};
|
||||
|
||||
module.exports = ffmpeg;
|
43
node_modules/ffmpeg/lib/presets.js
generated
vendored
Normal file
43
node_modules/ffmpeg/lib/presets.js
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
module.exports.size = {
|
||||
'SQCIF' : '128x96'
|
||||
, 'QCIF' : '176x144'
|
||||
, 'CIF' : '352x288'
|
||||
, '4CIF' : '704x576'
|
||||
, 'QQVGA' : '160x120'
|
||||
, 'QVGA' : '320x240'
|
||||
, 'VGA' : '640x480'
|
||||
, 'SVGA' : '800x600'
|
||||
, 'XGA' : '1024x768'
|
||||
, 'UXGA' : '1600x1200'
|
||||
, 'QXGA' : '2048x1536'
|
||||
, 'SXGA' : '1280x1024'
|
||||
, 'QSXGA' : '2560x2048'
|
||||
, 'HSXGA' : '5120x4096'
|
||||
, 'WVGA' : '852x480'
|
||||
, 'WXGA' : '1366x768'
|
||||
, 'WSXGA' : '1600x1024'
|
||||
, 'WUXGA' : '1920x1200'
|
||||
, 'WOXGA' : '2560x1600'
|
||||
, 'WQSXGA' : '3200x2048'
|
||||
, 'WQUXGA' : '3840x2400'
|
||||
, 'WHSXGA' : '6400x4096'
|
||||
, 'WHUXGA' : '7680x4800'
|
||||
, 'CGA' : '320x200'
|
||||
, 'EGA' : '640x350'
|
||||
, 'HD480' : '852x480'
|
||||
, 'HD720' : '1280x720'
|
||||
, 'HD1080' : '1920x1080'
|
||||
}
|
||||
|
||||
module.exports.ratio = {
|
||||
'4:3' : 1.33
|
||||
, '3:2' : 1.5
|
||||
, '14:9' : 1.56
|
||||
, '16:9' : 1.78
|
||||
, '21:9' : 2.33
|
||||
}
|
||||
|
||||
module.exports.audio_channel = {
|
||||
'mono' : 1
|
||||
, 'stereo' : 2
|
||||
}
|
132
node_modules/ffmpeg/lib/utils.js
generated
vendored
Normal file
132
node_modules/ffmpeg/lib/utils.js
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
var exec = require('child_process').exec
|
||||
, fs = require('fs')
|
||||
, path = require('path');
|
||||
|
||||
var errors = require('./errors');
|
||||
|
||||
/**
|
||||
* Exec the list of commands and call the callback function at the end of the process
|
||||
*/
|
||||
module.exports.exec = function (commands, settings, callback) {
|
||||
// Create final command line
|
||||
var finalCommand = commands.join(" ");
|
||||
// Create the timeoutId for stop the timeout at the end the process
|
||||
var timeoutID = null;
|
||||
// Exec the command
|
||||
var process = exec(finalCommand, settings, function (error, stdout, stderr) {
|
||||
// Clear timeout if 'timeoutID' are setted
|
||||
if (timeoutID !== null) clearTimeout(timeoutID);
|
||||
// Call the callback function
|
||||
callback(error, stdout, stderr);
|
||||
});
|
||||
// Verify if the timeout are setting
|
||||
if (settings.timeout > 0) {
|
||||
// Set the timeout
|
||||
timeoutID = setTimeout(function () {
|
||||
process.kill();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if object is empty
|
||||
*/
|
||||
module.exports.isEmptyObj = function (obj) {
|
||||
// Scan all properties
|
||||
for(var prop in obj)
|
||||
// Check if obj has a property
|
||||
if(obj.hasOwnProperty(prop))
|
||||
// The object is not empty
|
||||
return false;
|
||||
// The object is empty
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge obj1 into obj
|
||||
*/
|
||||
module.exports.mergeObject = function (obj, obj1) {
|
||||
// Check if there are options set
|
||||
if (!module.exports.isEmptyObj(obj1)) {
|
||||
// Scan all settings
|
||||
for (var key in obj1) {
|
||||
// Check if the option is valid
|
||||
if (!obj.hasOwnProperty(key))
|
||||
throw errors.renderError('invalid_option_name', key);
|
||||
// Set new option value
|
||||
obj[key] = obj1[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the duration in seconds from the string retrieved by the ffmpeg info
|
||||
*/
|
||||
module.exports.durationToSeconds = function(duration) {
|
||||
var parts = duration.substr(0,8).split(':');
|
||||
return parseInt(parts[0], 10) * 3600 + parseInt(parts[1], 10) * 60 + parseInt(parts[2], 10);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the greatest common divisor
|
||||
*/
|
||||
module.exports.gcd = function (a, b) {
|
||||
if (b === 0) return a;
|
||||
return module.exports.gcd(b, a % b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offers functionality similar to mkdir -p
|
||||
*/
|
||||
module.exports.mkdir = function (dirpath, mode, callback, position) {
|
||||
// Split all directories
|
||||
var parts = path.normalize(dirpath).split('/');
|
||||
// If the first part is empty then remove this part
|
||||
if (parts[0] == "")
|
||||
parts = parts.slice(1);
|
||||
|
||||
// Set the initial configuration
|
||||
mode = mode || 0777;
|
||||
position = position || 0;
|
||||
|
||||
// Check se current position is greater than the list of folders
|
||||
if (position > parts.length) {
|
||||
// If isset the callback then it will be invoked
|
||||
if (callback)
|
||||
callback();
|
||||
// Exit and return a positive value
|
||||
return true;
|
||||
}
|
||||
|
||||
// Build the directory path
|
||||
var directory = (dirpath.charAt(0) == '/' ? '/' : '') + parts.slice(0, position + 1).join('/');
|
||||
|
||||
// Check if directory exists
|
||||
if (fs.existsSync(directory)) {
|
||||
module.exports.mkdir(dirpath, mode, callback, position + 1);
|
||||
} else {
|
||||
if (fs.mkdirSync(directory, mode)) {
|
||||
// If isset the callback then it will be invoked
|
||||
if (callback)
|
||||
callback(errors.renderError('mkdir', directory));
|
||||
// Send the new exception
|
||||
throw errors.renderError('mkdir', directory);
|
||||
} else {
|
||||
module.exports.mkdir(dirpath, mode, callback, position + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a value is present inside an array
|
||||
*/
|
||||
module.exports.in_array = function (value, array) {
|
||||
// Scan all element
|
||||
for (var i in array)
|
||||
// Check if value exists
|
||||
if (array[i] == value)
|
||||
// Return the position of value
|
||||
return i;
|
||||
// The value not exists
|
||||
return false;
|
||||
}
|
863
node_modules/ffmpeg/lib/video.js
generated
vendored
Normal file
863
node_modules/ffmpeg/lib/video.js
generated
vendored
Normal file
@ -0,0 +1,863 @@
|
||||
var fs = require('fs')
|
||||
, path = require('path')
|
||||
, when = require('when');
|
||||
|
||||
var errors = require('./errors')
|
||||
, presets = require('./presets')
|
||||
, utils = require('./utils');
|
||||
|
||||
module.exports = function (filePath, settings, infoConfiguration, infoFile) {
|
||||
|
||||
// Public info about file and ffmpeg configuration
|
||||
this.file_path = filePath;
|
||||
this.info_configuration = infoConfiguration;
|
||||
this.metadata = infoFile;
|
||||
|
||||
// Commands for building the ffmpeg string conversion
|
||||
var commands = new Array()
|
||||
, inputs = new Array()
|
||||
, filtersComlpex = new Array()
|
||||
, output = null;
|
||||
|
||||
// List of options generated from setting functions
|
||||
var options = new Object();
|
||||
|
||||
/*****************************************/
|
||||
/* FUNCTION FOR FILL THE COMMANDS OBJECT */
|
||||
/*****************************************/
|
||||
|
||||
/**
|
||||
* Add a command to be bundled into the ffmpeg command call
|
||||
*/
|
||||
this.addCommand = function (command, argument) {
|
||||
// Check if exists the current command
|
||||
if (utils.in_array(command, commands) === false) {
|
||||
// Add the new command
|
||||
commands.push(command);
|
||||
// Add the argument to new command
|
||||
if (argument != undefined)
|
||||
commands.push(argument);
|
||||
} else
|
||||
throw errors.renderError('command_already_exists', command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an input stream
|
||||
*/
|
||||
this.addInput = function (argument) {
|
||||
inputs.push(argument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter complex
|
||||
*/
|
||||
this.addFilterComplex = function (argument) {
|
||||
filtersComlpex.push(argument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output path
|
||||
*/
|
||||
var setOutput = function (path) {
|
||||
output = path;
|
||||
}
|
||||
|
||||
/*********************/
|
||||
/* SETTING FUNCTIONS */
|
||||
/*********************/
|
||||
|
||||
/**
|
||||
* Disables audio encoding
|
||||
*/
|
||||
this.setDisableAudio = function () {
|
||||
if (options.audio == undefined)
|
||||
options.audio = new Object();
|
||||
// Set the new option
|
||||
options.audio.disabled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables video encoding
|
||||
*/
|
||||
this.setDisableVideo = function () {
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
// Set the new option
|
||||
options.video.disabled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new video format
|
||||
*/
|
||||
this.setVideoFormat = function (format) {
|
||||
// Check if the format is supported by ffmpeg version
|
||||
if (this.info_configuration.encode.indexOf(format) != -1) {
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
// Set the new option
|
||||
options.video.format = format;
|
||||
return this;
|
||||
} else
|
||||
throw errors.renderError('format_not_supported', format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new audio codec
|
||||
*/
|
||||
this.setVideoCodec = function (codec) {
|
||||
// Check if the codec is supported by ffmpeg version
|
||||
if (this.info_configuration.encode.indexOf(codec) != -1) {
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
// Set the new option
|
||||
options.video.codec = codec;
|
||||
return this;
|
||||
} else
|
||||
throw errors.renderError('codec_not_supported', codec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the video bitrate
|
||||
*/
|
||||
this.setVideoBitRate = function (bitrate) {
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
// Set the new option
|
||||
options.video.bitrate = bitrate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the framerate of the video
|
||||
*/
|
||||
this.setVideoFrameRate = function (framerate) {
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
// Set the new option
|
||||
options.video.framerate = framerate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the start time
|
||||
*/
|
||||
this.setVideoStartTime = function (time) {
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
|
||||
// Check if time is a string that contain: hours, minutes and seconds
|
||||
if (isNaN(time) && /([0-9]+):([0-9]{2}):([0-9]{2})/.exec(time)) {
|
||||
time = utils.durationToSeconds(time);
|
||||
} else if (!isNaN(time) && parseInt(time) == time) {
|
||||
time = parseInt(time, 10);
|
||||
} else {
|
||||
time = 0;
|
||||
}
|
||||
|
||||
// Set the new option
|
||||
options.video.startTime = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the duration
|
||||
*/
|
||||
this.setVideoDuration = function (duration) {
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
|
||||
// Check if duration is a string that contain: hours, minutes and seconds
|
||||
if (isNaN(duration) && /([0-9]+):([0-9]{2}):([0-9]{2})/.exec(duration)) {
|
||||
duration = utils.durationToSeconds(duration);
|
||||
} else if (!isNaN(duration) && parseInt(duration) == duration) {
|
||||
duration = parseInt(duration, 10);
|
||||
} else {
|
||||
duration = 0;
|
||||
}
|
||||
|
||||
// Set the new option
|
||||
options.video.duration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new aspetc ratio
|
||||
*/
|
||||
this.setVideoAspectRatio = function (aspect) {
|
||||
// Check if aspect is a string
|
||||
if (isNaN(aspect)) {
|
||||
// Check if aspet is string xx:xx
|
||||
if (/([0-9]+):([0-9]+)/.exec(aspect)) {
|
||||
var check = /([0-9]+):([0-9]+)/.exec(aspect);
|
||||
aspect = parseFloat((check[1] / check[2]));
|
||||
} else {
|
||||
aspect = this.metadata.video.aspect.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
// Set the new option
|
||||
options.video.aspect = aspect;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size of the video
|
||||
*/
|
||||
this.setVideoSize = function (size, keepPixelAspectRatio, keepAspectRatio, paddingColor) {
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
// Set the new option
|
||||
options.video.size = size;
|
||||
options.video.keepPixelAspectRatio = keepPixelAspectRatio;
|
||||
options.video.keepAspectRatio = keepAspectRatio;
|
||||
options.video.paddingColor = paddingColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new audio codec
|
||||
*/
|
||||
this.setAudioCodec = function (codec) {
|
||||
// Check if the codec is supported by ffmpeg version
|
||||
if (this.info_configuration.encode.indexOf(codec) != -1) {
|
||||
// Check if codec is equal 'MP3' and check if the version of ffmpeg support the libmp3lame function
|
||||
if (codec == 'mp3' && this.info_configuration.modules.indexOf('libmp3lame') != -1)
|
||||
codec = 'libmp3lame';
|
||||
|
||||
if (options.audio == undefined)
|
||||
options.audio = new Object();
|
||||
// Set the new option
|
||||
options.audio.codec = codec;
|
||||
return this;
|
||||
} else
|
||||
throw errors.renderError('codec_not_supported', codec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the audio sample frequency for audio outputs
|
||||
*/
|
||||
this.setAudioFrequency = function (frequency) {
|
||||
if (options.audio == undefined)
|
||||
options.audio = new Object();
|
||||
// Set the new option
|
||||
options.audio.frequency = frequency;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of audio channels
|
||||
*/
|
||||
this.setAudioChannels = function (channel) {
|
||||
// Check if the channel value is valid
|
||||
if (presets.audio_channel.stereo == channel || presets.audio_channel.mono == channel) {
|
||||
if (options.audio == undefined)
|
||||
options.audio = new Object();
|
||||
// Set the new option
|
||||
options.audio.channel = channel;
|
||||
return this;
|
||||
} else
|
||||
throw errors.renderError('audio_channel_is_invalid', channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the audio bitrate
|
||||
*/
|
||||
this.setAudioBitRate = function (bitrate) {
|
||||
if (options.audio == undefined)
|
||||
options.audio = new Object();
|
||||
// Set the new option
|
||||
options.audio.bitrate = bitrate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the audio quality
|
||||
*/
|
||||
this.setAudioQuality = function (quality) {
|
||||
if (options.audio == undefined)
|
||||
options.audio = new Object();
|
||||
// Set the new option
|
||||
options.audio.quality = quality;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the watermark
|
||||
*/
|
||||
this.setWatermark = function (watermarkPath, settings) {
|
||||
// Base settings
|
||||
var baseSettings = {
|
||||
position : "SW" // Position: NE NC NW SE SC SW C CE CW
|
||||
, margin_nord : null // Margin nord
|
||||
, margin_sud : null // Margin sud
|
||||
, margin_east : null // Margin east
|
||||
, margin_west : null // Margin west
|
||||
};
|
||||
|
||||
// Check if watermark exists
|
||||
if (!fs.existsSync(watermarkPath))
|
||||
throw errors.renderError('invalid_watermark', watermarkPath);
|
||||
|
||||
// Check if the settings are specified
|
||||
if (settings != null)
|
||||
utils.mergeObject(baseSettings, settings);
|
||||
|
||||
// Check if position is valid
|
||||
if (baseSettings.position == null || utils.in_array(baseSettings.position, ['NE','NC','NW','SE','SC','SW','C','CE','CW']) === false)
|
||||
throw errors.renderError('invalid_watermark_position', baseSettings.position);
|
||||
|
||||
// Check if margins are valid
|
||||
|
||||
if (baseSettings.margin_nord == null || isNaN(baseSettings.margin_nord))
|
||||
baseSettings.margin_nord = 0;
|
||||
if (baseSettings.margin_sud == null || isNaN(baseSettings.margin_sud))
|
||||
baseSettings.margin_sud = 0;
|
||||
if (baseSettings.margin_east == null || isNaN(baseSettings.margin_east))
|
||||
baseSettings.margin_east = 0;
|
||||
if (baseSettings.margin_west == null || isNaN(baseSettings.margin_west))
|
||||
baseSettings.margin_west = 0;
|
||||
|
||||
var overlay = '';
|
||||
|
||||
var getSing = function (val, inverse) {
|
||||
return (val > 0 ? (inverse ? '-' : '+') : (inverse ? '+' : '-')).toString() + Math.abs(val).toString();
|
||||
}
|
||||
|
||||
var getHorizontalMargins = function (east, west) {
|
||||
return getSing(east, false).toString() + getSing(west, true).toString();
|
||||
}
|
||||
|
||||
var getVerticalMargins = function (nord, sud) {
|
||||
return getSing(nord, false).toString() + getSing(sud, true).toString();
|
||||
}
|
||||
|
||||
// Calculate formula
|
||||
switch (baseSettings.position) {
|
||||
case 'NE':
|
||||
overlay = '0' + getHorizontalMargins(baseSettings.margin_east, baseSettings.margin_west) + ':0' + getVerticalMargins(baseSettings.margin_nord, baseSettings.margin_sud);
|
||||
break;
|
||||
case 'NC':
|
||||
overlay = 'main_w/2-overlay_w/2' + getHorizontalMargins(baseSettings.margin_east, baseSettings.margin_west) + ':0' + getVerticalMargins(baseSettings.margin_nord, baseSettings.margin_sud);
|
||||
break;
|
||||
case 'NW':
|
||||
overlay = 'main_w-overlay_w' + getHorizontalMargins(baseSettings.margin_east, baseSettings.margin_west) + ':0' + getVerticalMargins(baseSettings.margin_nord, baseSettings.margin_sud);
|
||||
break;
|
||||
case 'SE':
|
||||
overlay = '0' + getHorizontalMargins(baseSettings.margin_east, baseSettings.margin_west) + ':main_h-overlay_h' + getVerticalMargins(baseSettings.margin_nord, baseSettings.margin_sud);
|
||||
break;
|
||||
case 'SC':
|
||||
overlay = 'main_w/2-overlay_w/2' + getHorizontalMargins(baseSettings.margin_east, baseSettings.margin_west) + ':main_h-overlay_h' + getVerticalMargins(baseSettings.margin_nord, baseSettings.margin_sud);
|
||||
break;
|
||||
case 'SW':
|
||||
overlay = 'main_w-overlay_w' + getHorizontalMargins(baseSettings.margin_east, baseSettings.margin_west) + ':main_h-overlay_h' + getVerticalMargins(baseSettings.margin_nord, baseSettings.margin_sud);
|
||||
break;
|
||||
case 'CE':
|
||||
overlay = '0' + getHorizontalMargins(baseSettings.margin_east, baseSettings.margin_west) + ':main_h/2-overlay_h/2' + getVerticalMargins(baseSettings.margin_nord, baseSettings.margin_sud);
|
||||
break;
|
||||
case 'C':
|
||||
overlay = 'main_w/2-overlay_w/2' + getHorizontalMargins(baseSettings.margin_east, baseSettings.margin_west) + ':main_h/2-overlay_h/2' + getVerticalMargins(baseSettings.margin_nord, baseSettings.margin_sud);
|
||||
break;
|
||||
case 'CW':
|
||||
overlay = 'main_w-overlay_w' + getHorizontalMargins(baseSettings.margin_east, baseSettings.margin_west) + ':main_h/2-overlay_h/2' + getVerticalMargins(baseSettings.margin_nord, baseSettings.margin_sud);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if the call comes from internal function
|
||||
if (arguments[2] == undefined || arguments[2] == null) {
|
||||
if (options.video == undefined)
|
||||
options.video = new Object();
|
||||
// Set the new option
|
||||
options.video.watermark = { path : watermarkPath, overlay : overlay };
|
||||
return this;
|
||||
} else if (arguments[2] != undefined && arguments[2] === true) {
|
||||
this.addInput(watermarkPath);
|
||||
this.addFilterComplex('overlay=' + overlay);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all set commands
|
||||
*/
|
||||
this.save = function (destionationFileName, callback) {
|
||||
// Check if the 'video' is present in the options
|
||||
if (options.hasOwnProperty('video')) {
|
||||
// Check if video is disabled
|
||||
if (options.video.hasOwnProperty('disabled')) {
|
||||
this.addCommand('-vn');
|
||||
} else {
|
||||
// Check all video property
|
||||
if (options.video.hasOwnProperty('format'))
|
||||
this.addCommand('-f', options.video.format);
|
||||
if (options.video.hasOwnProperty('codec'))
|
||||
this.addCommand('-vcodec', options.video.codec);
|
||||
if (options.video.hasOwnProperty('bitrate'))
|
||||
this.addCommand('-b', parseInt(options.video.bitrate, 10) + 'kb');
|
||||
if (options.video.hasOwnProperty('framerate'))
|
||||
this.addCommand('-r', parseInt(options.video.framerate, 10));
|
||||
if (options.video.hasOwnProperty('startTime'))
|
||||
this.addCommand('-ss', parseInt(options.video.startTime, 10));
|
||||
if (options.video.hasOwnProperty('duration'))
|
||||
this.addCommand('-t', parseInt(options.video.duration, 10));
|
||||
|
||||
if (options.video.hasOwnProperty('watermark')) {
|
||||
this.addInput(options.video.watermark.path);
|
||||
this.addFilterComplex('overlay=' + options.video.watermark.overlay);
|
||||
}
|
||||
|
||||
// Check if the video should be scaled
|
||||
if (options.video.hasOwnProperty('size')) {
|
||||
var newDimension = _calculateNewDimension.call(this);
|
||||
|
||||
if (newDimension.aspect != null) {
|
||||
this.addFilterComplex('scale=iw*sar:ih, pad=max(iw\\,ih*(' + newDimension.aspect.x + '/' + newDimension.aspect.y + ')):ow/(' + newDimension.aspect.x + '/' + newDimension.aspect.y + '):(ow-iw)/2:(oh-ih)/2' + (options.video.paddingColor != null ? ':' + options.video.paddingColor : ''));
|
||||
this.addCommand('-aspect', newDimension.aspect.string);
|
||||
}
|
||||
|
||||
this.addCommand('-s', newDimension.width + 'x' + newDimension.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if the 'audio' is present in the options
|
||||
if (options.hasOwnProperty('audio')) {
|
||||
// Check if audio is disabled
|
||||
if (options.audio.hasOwnProperty('disabled')) {
|
||||
this.addCommand('-an');
|
||||
} else {
|
||||
// Check all audio property
|
||||
if (options.audio.hasOwnProperty('codec'))
|
||||
this.addCommand('-acodec', options.audio.codec);
|
||||
if (options.audio.hasOwnProperty('frequency'))
|
||||
this.addCommand('-ar', parseInt(options.audio.frequency));
|
||||
if (options.audio.hasOwnProperty('channel'))
|
||||
this.addCommand('-ac', options.audio.channel);
|
||||
if (options.audio.hasOwnProperty('quality'))
|
||||
this.addCommand('-aq', options.audio.quality);
|
||||
if (options.audio.hasOwnProperty('bitrate'))
|
||||
this.addCommand('-ab', parseInt(options.audio.bitrate, 10) + 'k');
|
||||
}
|
||||
}
|
||||
|
||||
setOutput(destionationFileName);
|
||||
|
||||
return execCommand.call(this, callback);
|
||||
}
|
||||
|
||||
/*********************/
|
||||
/* INTERNAL FUNCTION */
|
||||
/*********************/
|
||||
|
||||
/**
|
||||
* Reset the list of commands
|
||||
*/
|
||||
var resetCommands = function (self) {
|
||||
commands = new Array()
|
||||
inputs = [self.file_path];
|
||||
filtersComlpex = new Array();
|
||||
output = null;
|
||||
options = new Object();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate width, height and aspect ratio by the new dimension data
|
||||
*/
|
||||
var _calculateNewDimension = function () {
|
||||
// Check if keepPixelAspectRatio is undefined
|
||||
var keepPixelAspectRatio = typeof options.video.keepPixelAspectRatio != 'boolean' ? false : options.video.keepPixelAspectRatio;
|
||||
// Check if keepAspectRatio is undefined
|
||||
var keepAspectRatio = typeof options.video.keepAspectRatio != 'boolean' ? false : options.video.keepAspectRatio;
|
||||
|
||||
// Resolution to be taken as a reference
|
||||
var referrerResolution = this.metadata.video.resolution;
|
||||
// Check if is need keep pixel aspect ratio
|
||||
if (keepPixelAspectRatio) {
|
||||
// Check if exists resolution for pixel aspect ratio
|
||||
if (utils.isEmptyObj(this.metadata.video.resolutionSquare))
|
||||
throw errors.renderError('resolution_square_not_defined');
|
||||
|
||||
// Apply the resolutionSquare
|
||||
referrerResolution = this.metadata.video.resolutionSquare;
|
||||
}
|
||||
|
||||
// Final data
|
||||
var width = null
|
||||
, height = null
|
||||
, aspect = null;
|
||||
|
||||
// Regex to check which type of dimension was specified
|
||||
var fixedWidth = /([0-9]+)x\?/.exec(options.video.size)
|
||||
, fixedHeight = /\?x([0-9]+)/.exec(options.video.size)
|
||||
, percentage = /([0-9]{1,2})%/.exec(options.video.size)
|
||||
, classicSize = /([0-9]+)x([0-9]+)/.exec(options.video.size);
|
||||
|
||||
if (fixedWidth) {
|
||||
// Set the width dimension
|
||||
width = parseInt(fixedWidth[1], 10);
|
||||
// Check if the video has the aspect ratio setted
|
||||
if (!utils.isEmptyObj(this.metadata.video.aspect)) {
|
||||
height = Math.round((width / this.metadata.video.aspect.x) * this.metadata.video.aspect.y);
|
||||
} else {
|
||||
// Calculte the new height
|
||||
height = Math.round(referrerResolution.h / (referrerResolution.w / parseInt(fixedWidth[1], 10)));
|
||||
}
|
||||
} else if (fixedHeight) {
|
||||
// Set the width dimension
|
||||
height = parseInt(fixedHeight[1], 10);
|
||||
// Check if the video has the aspect ratio setted
|
||||
if (!utils.isEmptyObj(this.metadata.video.aspect)) {
|
||||
width = Math.round((height / this.metadata.video.aspect.y) * this.metadata.video.aspect.x);
|
||||
} else {
|
||||
// Calculte the new width
|
||||
width = Math.round(referrerResolution.w / (referrerResolution.h / parseInt(fixedHeight[1], 10)));
|
||||
}
|
||||
} else if (percentage) {
|
||||
// Calculte the ratio from percentage
|
||||
var ratio = parseInt(percentage[1], 10) / 100;
|
||||
// Calculate the new dimensions
|
||||
width = Math.round(referrerResolution.w * ratio);
|
||||
height = Math.round(referrerResolution.h * ratio);
|
||||
} else if (classicSize) {
|
||||
width = parseInt(classicSize[1], 10);
|
||||
height = parseInt(classicSize[2], 10);
|
||||
} else
|
||||
throw errors.renderError('size_format', options.video.size);
|
||||
|
||||
// If the width or height are not multiples of 2 will be decremented by one unit
|
||||
if (width % 2 != 0) width -= 1;
|
||||
if (height % 2 != 0) height -= 1;
|
||||
|
||||
if (keepAspectRatio) {
|
||||
// Calculate the new aspect ratio
|
||||
var gcdValue = utils.gcd(width, height);
|
||||
|
||||
aspect = new Object();
|
||||
aspect.x = width / gcdValue;
|
||||
aspect.y = height / gcdValue;
|
||||
aspect.string = aspect.x + ':' + aspect.y;
|
||||
}
|
||||
|
||||
return { width : width, height : height, aspect : aspect };
|
||||
}
|
||||
|
||||
/**
|
||||
* Executing the commands list
|
||||
*/
|
||||
var execCommand = function (callback, folder) {
|
||||
// Checking if folder is defined
|
||||
var onlyDestinationFile = folder != undefined ? false : true;
|
||||
// Building the value for return value. Check if the callback is not a function. In this case will created a new instance of the deferred class
|
||||
var deferred = typeof callback != 'function' ? when.defer() : { promise : null };
|
||||
// Create a copy of the commands list
|
||||
var finalCommands = ['ffmpeg -i']
|
||||
.concat(inputs.join(' -i '))
|
||||
.concat(commands.join(' '))
|
||||
.concat(filtersComlpex.length > 0 ? ['-filter_complex "'].concat(filtersComlpex.join(', ')).join('') + '"' : [])
|
||||
.concat([output]);
|
||||
// Reset commands
|
||||
resetCommands(this);
|
||||
// Execute the commands from the list
|
||||
utils.exec(finalCommands, settings, function (error, stdout, stderr) {
|
||||
// Building the result
|
||||
var result = null;
|
||||
if (!error) {
|
||||
// Check if show only destination filename or the complete file list
|
||||
if (onlyDestinationFile) {
|
||||
result = finalCommands[finalCommands.length-1];
|
||||
} else {
|
||||
// Clean possible "/" at the end of the string
|
||||
if (folder.charAt(folder.length-1) == "/")
|
||||
folder = folder.substr(0, folder.length-1);
|
||||
// Read file list inside the folder
|
||||
result = fs.readdirSync(folder);
|
||||
// Scan all file and prepend the folder path
|
||||
for (var i in result)
|
||||
result[i] = [folder, result[i]].join('/')
|
||||
}
|
||||
}
|
||||
// Check if the callback is a function
|
||||
if (typeof callback == 'function') {
|
||||
// Call the callback to return the info
|
||||
callback(error, result);
|
||||
} else {
|
||||
if (error) {
|
||||
// Negative response
|
||||
deferred.reject(error);
|
||||
} else {
|
||||
// Positive response
|
||||
deferred.resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
// Return a possible promise instance
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/*******************/
|
||||
/* PRESET FUNCTION */
|
||||
/*******************/
|
||||
|
||||
/**
|
||||
* Extracting sound from a video, and save it as Mp3
|
||||
*/
|
||||
this.fnExtractSoundToMP3 = function (destionationFileName, callback) {
|
||||
// Check if file already exists. In this case will remove it
|
||||
if (fs.existsSync(destionationFileName))
|
||||
fs.unlinkSync(destionationFileName);
|
||||
|
||||
// Building the final path
|
||||
var destinationDirName = path.dirname(destionationFileName)
|
||||
, destinationFileNameWE = path.basename(destionationFileName, path.extname(destionationFileName)) + '.mp3'
|
||||
, finalPath = path.join(destinationDirName, destinationFileNameWE);
|
||||
|
||||
resetCommands(this);
|
||||
|
||||
// Adding commands to the list
|
||||
this.addCommand('-vn');
|
||||
this.addCommand('-ar', 44100);
|
||||
this.addCommand('-ac', 2);
|
||||
this.addCommand('-ab', 192);
|
||||
this.addCommand('-f', 'mp3');
|
||||
|
||||
// Add destination file path to the command list
|
||||
setOutput(finalPath);
|
||||
|
||||
// Executing the commands list
|
||||
return execCommand.call(this, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract frame from video file
|
||||
*/
|
||||
this.fnExtractFrameToJPG = function (/* destinationFolder, settings, callback */) {
|
||||
|
||||
var destinationFolder = null
|
||||
, newSettings = null
|
||||
, callback = null;
|
||||
|
||||
var settings = {
|
||||
start_time : null // Start time to recording
|
||||
, duration_time : null // Duration of recording
|
||||
, frame_rate : null // Number of the frames to capture in one second
|
||||
, size : null // Dimension each frame
|
||||
, number : null // Total frame to capture
|
||||
, every_n_frames : null // Frame to capture every N frames
|
||||
, every_n_seconds : null // Frame to capture every N seconds
|
||||
, every_n_percentage : null // Frame to capture every N percentage range
|
||||
, keep_pixel_aspect_ratio : true // Mantain the original pixel video aspect ratio
|
||||
, keep_aspect_ratio : true // Mantain the original aspect ratio
|
||||
, padding_color : 'black' // Padding color
|
||||
, file_name : null // File name
|
||||
};
|
||||
|
||||
// Scan all arguments
|
||||
for (var i in arguments) {
|
||||
// Check the type of the argument
|
||||
switch (typeof arguments[i]) {
|
||||
case 'string':
|
||||
destinationFolder = arguments[i];
|
||||
break;
|
||||
case 'object':
|
||||
newSettings = arguments[i];
|
||||
break;
|
||||
case 'function':
|
||||
callback = arguments[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the settings are specified
|
||||
if (newSettings !== null)
|
||||
utils.mergeObject(settings, newSettings);
|
||||
|
||||
// Check if 'start_time' is in the format hours:minutes:seconds
|
||||
if (settings.start_time != null) {
|
||||
if (/([0-9]+):([0-9]{2}):([0-9]{2})/.exec(settings.start_time))
|
||||
settings.start_time = utils.durationToSeconds(settings.start_time);
|
||||
else if (!isNaN(settings.start_time))
|
||||
settings.start_time = parseInt(settings.start_time, 10);
|
||||
else
|
||||
settings.start_time = null;
|
||||
}
|
||||
|
||||
// Check if 'duration_time' is in the format hours:minutes:seconds
|
||||
if (settings.duration_time != null) {
|
||||
if (/([0-9]+):([0-9]{2}):([0-9]{2})/.exec(settings.duration_time))
|
||||
settings.duration_time = utils.durationToSeconds(settings.duration_time);
|
||||
else if (!isNaN(settings.duration_time))
|
||||
settings.duration_time = parseInt(settings.duration_time, 10);
|
||||
else
|
||||
settings.duration_time = null;
|
||||
}
|
||||
|
||||
// Check if the value of the framerate is number type
|
||||
if (settings.frame_rate != null && isNaN(settings.frame_rate))
|
||||
settings.frame_rate = null;
|
||||
|
||||
// If the size is not settings then the size of the screenshots is equal to video size
|
||||
if (settings.size == null)
|
||||
settings.size = this.metadata.video.resolution.w + 'x' + this.metadata.video.resolution.h;
|
||||
|
||||
// Check if the value of the 'number frame to capture' is number type
|
||||
if (settings.number != null && isNaN(settings.number))
|
||||
settings.number = null;
|
||||
|
||||
var every_n_check = 0;
|
||||
|
||||
// Check if the value of the 'every_n_frames' is number type
|
||||
if (settings.every_n_frames != null && isNaN(settings.every_n_frames)) {
|
||||
settings.every_n_frames = null;
|
||||
every_n_check++;
|
||||
}
|
||||
|
||||
// Check if the value of the 'every_n_seconds' is number type
|
||||
if (settings.every_n_seconds != null && isNaN(settings.every_n_seconds)) {
|
||||
settings.every_n_seconds = null;
|
||||
every_n_check++;
|
||||
}
|
||||
|
||||
// Check if the value of the 'every_n_percentage' is number type
|
||||
if (settings.every_n_percentage != null && (isNaN(settings.every_n_percentage) || settings.every_n_percentage > 100)) {
|
||||
settings.every_n_percentage = null;
|
||||
every_n_check++;
|
||||
}
|
||||
|
||||
if (every_n_check >= 2) {
|
||||
if (callback) {
|
||||
callback(errors.renderError('extract_frame_invalid_everyN_options'));
|
||||
} else {
|
||||
throw errors.renderError('extract_frame_invalid_everyN_options');
|
||||
}
|
||||
}
|
||||
|
||||
// If filename is null then his value is equal to original filename
|
||||
if (settings.file_name == null) {
|
||||
settings.file_name = path.basename(this.file_path, path.extname(this.file_path));
|
||||
} else {
|
||||
// Retrieve all possible replacements
|
||||
var replacements = settings.file_name.match(/(\%[a-zA-Z]{1})/g);
|
||||
// Check if exists replacements. The scan all replacements and build the final filename
|
||||
if (replacements) {
|
||||
for (var i in replacements) {
|
||||
switch (replacements[i]) {
|
||||
case '%t':
|
||||
settings.file_name = settings.file_name.replace('%t', new Date().getTime());
|
||||
break;
|
||||
case '%s':
|
||||
settings.file_name = settings.file_name.replace('%s', settings.size);
|
||||
break;
|
||||
case '%x':
|
||||
settings.file_name = settings.file_name.replace('%x', settings.size.split(':')[0]);
|
||||
break;
|
||||
case '%y':
|
||||
settings.file_name = settings.file_name.replace('%y', settings.size.split(':')[1]);
|
||||
break;
|
||||
default:
|
||||
settings.file_name = settings.file_name.replace(replacements[i], '');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// At the filename will added the number of the frame
|
||||
settings.file_name = path.basename(settings.file_name, path.extname(settings.file_name)) + '_%d.jpg';
|
||||
|
||||
// Create the directory to save the extracted frames
|
||||
utils.mkdir(destinationFolder, 0777);
|
||||
|
||||
resetCommands(this);
|
||||
|
||||
// Adding commands to the list
|
||||
if (settings.startTime)
|
||||
this.addCommand('-ss', settings.startTime);
|
||||
if (settings.duration_time)
|
||||
this.addCommand('-t', settings.duration_time);
|
||||
if (settings.frame_rate)
|
||||
this.addCommand('-r', settings.frame_rate);
|
||||
|
||||
// Setting the size and padding settings
|
||||
this.setVideoSize(settings.size, settings.keep_pixel_aspect_ratio, settings.keep_aspect_ratio, settings.padding_color);
|
||||
// Get the dimensions
|
||||
var newDimension = _calculateNewDimension.call(this);
|
||||
// Apply the size and padding commands
|
||||
this.addCommand('-s', newDimension.width + 'x' + newDimension.height);
|
||||
// CHeck if isset aspect ratio options
|
||||
if (newDimension.aspect != null) {
|
||||
this.addFilterComplex('scale=iw*sar:ih, pad=max(iw\\,ih*(' + newDimension.aspect.x + '/' + newDimension.aspect.y + ')):ow/(' + newDimension.aspect.x + '/' + newDimension.aspect.y + '):(ow-iw)/2:(oh-ih)/2' + (settings.padding_color != null ? ':' + settings.padding_color : ''));
|
||||
this.addCommand('-aspect', newDimension.aspect.string);
|
||||
}
|
||||
|
||||
if (settings.number)
|
||||
this.addCommand('-vframes', settings.number);
|
||||
if (settings.every_n_frames) {
|
||||
this.addCommand('-vsync', 0);
|
||||
this.addFilterComplex('select=not(mod(n\\,' + settings.every_n_frames + '))');
|
||||
}
|
||||
if (settings.every_n_seconds) {
|
||||
this.addCommand('-vsync', 0);
|
||||
this.addFilterComplex('select=not(mod(t\\,' + settings.every_n_seconds + '))');
|
||||
}
|
||||
if (settings.every_n_percentage) {
|
||||
this.addCommand('-vsync', 0);
|
||||
this.addFilterComplex('select=not(mod(t\\,' + parseInt((this.metadata.duration.seconds / 100) * settings.every_n_percentage) + '))');
|
||||
}
|
||||
|
||||
// Add destination file path to the command list
|
||||
setOutput([destinationFolder,settings.file_name].join('/'));
|
||||
|
||||
// Executing the commands list
|
||||
return execCommand.call(this, callback, destinationFolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a watermark to the video and save it
|
||||
*/
|
||||
this.fnAddWatermark = function (watermarkPath /* newFilepath , settings, callback */) {
|
||||
|
||||
var newFilepath = null
|
||||
, newSettings = null
|
||||
, callback = null;
|
||||
|
||||
// Scan all arguments
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
// Check the type of the argument
|
||||
switch (typeof arguments[i]) {
|
||||
case 'string':
|
||||
newFilepath = arguments[i];
|
||||
break;
|
||||
case 'object':
|
||||
newSettings = arguments[i];
|
||||
break;
|
||||
case 'function':
|
||||
callback = arguments[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
resetCommands(this);
|
||||
|
||||
// Call the function to add the watermark options
|
||||
this.setWatermark(watermarkPath, newSettings, true);
|
||||
|
||||
if (newFilepath == null)
|
||||
newFilepath = path.dirname(this.file_path) + '/' +
|
||||
path.basename(this.file_path, path.extname(this.file_path)) + '_watermark_' +
|
||||
path.basename(watermarkPath, path.extname(watermarkPath)) +
|
||||
path.extname(this.file_path);
|
||||
|
||||
// Add destination file path to the command list
|
||||
setOutput(newFilepath);
|
||||
|
||||
// Executing the commands list
|
||||
return execCommand.call(this, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
var __constructor = function (self) {
|
||||
resetCommands(self);
|
||||
}(this);
|
||||
}
|
47
node_modules/ffmpeg/package.json
generated
vendored
Normal file
47
node_modules/ffmpeg/package.json
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"_from": "ffmpeg",
|
||||
"_id": "ffmpeg@0.0.4",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-HEYN+OfaUSf2LO70v6BsWciWMMs=",
|
||||
"_location": "/ffmpeg",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "ffmpeg",
|
||||
"name": "ffmpeg",
|
||||
"escapedName": "ffmpeg",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/ffmpeg/-/ffmpeg-0.0.4.tgz",
|
||||
"_shasum": "1c460df8e7da5127f62ceef4bfa06c59c89630cb",
|
||||
"_spec": "ffmpeg",
|
||||
"_where": "C:\\Users\\matia\\Documents\\GitHub\\Musix-V3",
|
||||
"author": {
|
||||
"name": "Damiano Ciarla",
|
||||
"email": "damiano.ciarl@gmail.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/damianociarla/node-ffmpeg/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"when": ">= 0.0.1"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Utility for managing video streams using ffmpeg",
|
||||
"homepage": "https://github.com/damianociarla/node-ffmpeg#readme",
|
||||
"main": "./index.js",
|
||||
"name": "ffmpeg",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/damianociarla/node-ffmpeg.git"
|
||||
},
|
||||
"version": "0.0.4"
|
||||
}
|
Reference in New Issue
Block a user