sync/lib/ffmpeg.js

109 lines
3.0 KiB
JavaScript

var Logger = require("./logger");
var Config = require("./config");
var Metadata;
var enabled = false;
function init() {
if (Config.get("ffmpeg.enabled")) {
try {
Metadata = require("fluent-ffmpeg").Metadata;
Logger.syslog.log("Enabling raw file support with fluent-ffmpeg");
enabled = true;
} catch (e) {
Logger.errlog.log("Failed to load fluent-ffmpeg. Did you remember to " +
"execute `npm install fluent-ffmpeg` ?");
}
}
}
var acceptedCodecs = {
"mov/h264": true,
"flv/h264": true,
"matroska/vp8": true,
"matroska/vp9": true,
"ogg/theora": true
};
var acceptedAudioCodecs = {
"mp3": true,
"vorbis": true
};
var audioOnlyContainers = {
"mp3": true
};
exports.query = function (filename, cb) {
if (!Metadata) {
init();
}
if (!enabled) {
return cb("Raw file playback is not enabled on this server");
}
if (!filename.match(/^https?:\/\//)) {
return cb("Raw file playback is only supported for links accessible via HTTP " +
"or HTTPS");
}
new Metadata(filename, function (meta, err) {
if (err) {
return cb(err);
}
if (isVideo(meta)) {
var video = meta.video;
var codec = video.container + "/" + video.codec;
if (!(codec in acceptedCodecs)) {
return cb("Unsupported video codec " + codec);
}
var data = {
title: meta.title || "Raw Video",
duration: Math.ceil(meta.durationsec),
bitrate: video.bitrate,
codec: codec
};
cb(null, data);
} else if (isAudio(meta)) {
var audio = meta.audio;
var codec = audio.codec;
if (!(codec in acceptedAudioCodecs)) {
return cb("Unsupported audio codec " + codec);
}
var data = {
title: meta.title || "Raw Audio",
duration: Math.ceil(meta.durationsec),
bitrate: audio.bitrate,
codec: codec
};
cb(null, data);
} else if (data.ffmpegErr.match(/Protocol not found/)) {
return cb("This server is unable to load videos over the " +
filename.split(":")[0] + " protocol.");
} else {
return cb("Parsed metadata did not contain a valid video or audio stream. " +
"Either the file is invalid or it has a format unsupported by " +
"this server's version of ffmpeg.");
}
});
};
function isVideo(meta) {
return meta.video &&
meta.video.bitrate > 0 &&
meta.video.container &&
meta.video.codec &&
!(meta.video.container in audioOnlyContainers);
}
function isAudio(meta) {
return meta.audio && meta.audio.bitrate > 0 && meta.audio.codec;
}