const utils = require('.');
const log = require('./log').create_logger("ffmpeg")
const ffmpeg = require('fluent-ffmpeg');
// Optional path overrides in case ffmpeg is not part of the system path
process.env.FFMPEG_PATH && ffmpeg.setFfmpegPath(process.env.FFMPEG_PATH);
process.env.FFPROBE_PATH && ffmpeg.setFfprobePath(process.env.FFPROBE_PATH);
const FileType = require('file-type');
const path = require('path');
const ws_utils = require('../websocket/utils');
const broadcast = require('../websocket/broadcast');
const valid_video_formats = ['mp4', 'm4a', 'webm'];
module.exports = {
/**
* Converts video located at temp_file_path to a valid format if necessary.
* Returns a Promise that resolves after conversion is complete.
*
* Note: ffmpeg.format is a very long running process, so nothing with any sort
* of timeout should depend on this promise (such as the response to a request)
* @param {temp_file_path, name, video_id, user_id} data
*/
convert: function(data, options) {
options = options || {};
const video_dir = path.join(VIDEO_ROOT, data.video_id);
return utils.fs.mkdir_if_not_exists(video_dir).then(function() {
return FileType.fromFile(data.temp_file_path);
}).then(function(file_info) {
log.general.info("file_info:", file_info);
const output_file_path = path.join(video_dir, 'video');
if (valid_video_formats.includes(file_info.ext)) {
log.v("We don't need to convert the file");
return utils.fs.rename(data.temp_file_path, output_file_path);
}
log.general.info("convert", data);
return new Promise(function(resolve, reject) {
let percent_finished_x10 = 0;
let conversion_format = valid_video_formats[0];
ffmpeg(data.temp_file_path)
.format(conversion_format)
.on('end', resolve)
.on('error', reject)
.save(output_file_path)
.on('progress', function(progress) {
log.v(`Processing: ${data.name} - ${progress.percent}% done`);
// We update the user every tenth of a percent
let rounded_percent = Math.floor(progress.percent * 10);
if (rounded_percent > percent_finished_x10) {
percent_finished_x10 = rounded_percent;
broadcast({
command: "video-status",
data: {
video_id: data.video_id,
status: utils.status.video.converting,
progress: percent_finished_x10 / 10
}
}, {
[data.user_id]: true
});
ws_utils.broadcast_storage();
}
});
}).then(function() {
if (options.delete_source) {
return utils.fs.unlink(data.temp_file_path);
}
});
}).catch(function(error) {
broadcast({
command: "upload-error",
data: {
video_id: data.video_id,
status: utils.status.video.converting,
message: "Error converting " + data.name
}
}, {
[data.user_id]: true
});
return utils.reject(error);
});
}
};