109 lines
3 KiB
JavaScript
109 lines
3 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;
|
|
}
|