diff --git a/lib/ffmpeg.js b/lib/ffmpeg.js index 5d65e457..2ea429f9 100644 --- a/lib/ffmpeg.js +++ b/lib/ffmpeg.js @@ -4,9 +4,11 @@ var spawn = require("child_process").spawn; var https = require("https"); var http = require("http"); var urlparse = require("url"); +var path = require("path"); require("status-message-polyfill"); var USE_JSON = true; +var TIMEOUT = 30000; var acceptedCodecs = { "mov/h264": true, @@ -25,6 +27,15 @@ var audioOnlyContainers = { "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) { if (!redirCount) redirCount = 0; var data = urlparse.parse(url); @@ -137,12 +148,19 @@ function reformatData(data) { } exports.ffprobe = function ffprobe(filename, cb) { + fflog("Spawning ffprobe for " + filename); var childErr; var args = ["-show_streams", "-show_format", filename]; if (USE_JSON) args = ["-of", "json"].concat(args); var child = spawn(Config.get("ffmpeg.ffprobe-exec"), args); var stdout = ""; 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) { childErr = err; @@ -157,6 +175,8 @@ exports.ffprobe = function ffprobe(filename, cb) { }); child.on("close", function (code) { + clearTimeout(timer); + fflog("ffprobe exited with code " + code + " for file " + filename); if (code !== 0) { if (stderr.match(/unrecognized option|json/i) && USE_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) { + if (Config.get("ffmpeg.log")) { + initFFLog(); + } + if (!Config.get("ffmpeg.enabled")) { 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 " + "version of ffmpeg"); + if (err.message.match(/exceeded time limit/)) { + return cb(err.message); + } + // Ignore ffprobe error messages, they are common and most often // indicate a problem with the remote file, not with this code. if (!/(av|ff)probe/.test(String(err)))