Kill ffprobe after 30 seconds; add logging

This commit is contained in:
calzoneman 2015-07-30 20:45:47 -07:00
parent 66b08f53d1
commit 92b0747c0b

View file

@ -4,9 +4,11 @@ var spawn = require("child_process").spawn;
var https = require("https"); var https = require("https");
var http = require("http"); var http = require("http");
var urlparse = require("url"); var urlparse = require("url");
var path = require("path");
require("status-message-polyfill"); require("status-message-polyfill");
var USE_JSON = true; var USE_JSON = true;
var TIMEOUT = 30000;
var acceptedCodecs = { var acceptedCodecs = {
"mov/h264": true, "mov/h264": true,
@ -25,6 +27,15 @@ var audioOnlyContainers = {
"mp3": true "mp3": true
}; };
function fflog() { }
function initFFLog() {
var logger = new Logger.Logger(path.resolve(__dirname, "..", "ffmpeg.log"));
fflog = function () {
logger.log.apply(logger, arguments);
};
}
function testUrl(url, cb, redirCount) { function testUrl(url, cb, redirCount) {
if (!redirCount) redirCount = 0; if (!redirCount) redirCount = 0;
var data = urlparse.parse(url); var data = urlparse.parse(url);
@ -137,12 +148,19 @@ function reformatData(data) {
} }
exports.ffprobe = function ffprobe(filename, cb) { exports.ffprobe = function ffprobe(filename, cb) {
fflog("Spawning ffprobe for " + filename);
var childErr; var childErr;
var args = ["-show_streams", "-show_format", filename]; var args = ["-show_streams", "-show_format", filename];
if (USE_JSON) args = ["-of", "json"].concat(args); if (USE_JSON) args = ["-of", "json"].concat(args);
var child = spawn(Config.get("ffmpeg.ffprobe-exec"), args); var child = spawn(Config.get("ffmpeg.ffprobe-exec"), args);
var stdout = ""; var stdout = "";
var stderr = ""; var stderr = "";
var timer = setTimeout(function () {
Logger.errlog.log("Possible runaway ffprobe process for file " + filename);
fflog("Killing ffprobe for " + filename + " after " + (TIMEOUT/1000) + " seconds");
childErr = new Error("File query exceeded time limit of 10 seconds");
child.kill('SIGKILL');
}, TIMEOUT);
child.on("error", function (err) { child.on("error", function (err) {
childErr = err; childErr = err;
@ -157,6 +175,8 @@ exports.ffprobe = function ffprobe(filename, cb) {
}); });
child.on("close", function (code) { child.on("close", function (code) {
clearTimeout(timer);
fflog("ffprobe exited with code " + code + " for file " + filename);
if (code !== 0) { if (code !== 0) {
if (stderr.match(/unrecognized option|json/i) && USE_JSON) { if (stderr.match(/unrecognized option|json/i) && USE_JSON) {
Logger.errlog.log("Warning: ffprobe does not support -of json. " + Logger.errlog.log("Warning: ffprobe does not support -of json. " +
@ -189,6 +209,10 @@ exports.ffprobe = function ffprobe(filename, cb) {
} }
exports.query = function (filename, cb) { exports.query = function (filename, cb) {
if (Config.get("ffmpeg.log")) {
initFFLog();
}
if (!Config.get("ffmpeg.enabled")) { if (!Config.get("ffmpeg.enabled")) {
return cb("Raw file playback is not enabled on this server"); return cb("Raw file playback is not enabled on this server");
} }
@ -215,6 +239,10 @@ exports.query = function (filename, cb) {
return cb("Link uses a protocol unsupported by this server's " + return cb("Link uses a protocol unsupported by this server's " +
"version of ffmpeg"); "version of ffmpeg");
if (err.message.match(/exceeded time limit/)) {
return cb(err.message);
}
// Ignore ffprobe error messages, they are common and most often // Ignore ffprobe error messages, they are common and most often
// indicate a problem with the remote file, not with this code. // indicate a problem with the remote file, not with this code.
if (!/(av|ff)probe/.test(String(err))) if (!/(av|ff)probe/.test(String(err)))