From b35b2a6e7ed4c3118de34bc42aff2fc7f60ab682 Mon Sep 17 00:00:00 2001 From: calzoneman Date: Thu, 19 May 2016 20:51:39 -0700 Subject: [PATCH] Clean up ffprobe error reporting The error messages were a bit difficult for users to understand due to a combination of including useless technical information and lacking userful user information. The error messages are more verbose now and give a better indication of what went wrong. --- src/ffmpeg.js | 77 ++++++++++++++++++++++++++++++++++++++------------ www/js/util.js | 2 +- 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/ffmpeg.js b/src/ffmpeg.js index b074546b..e16fb4ad 100644 --- a/src/ffmpeg.js +++ b/src/ffmpeg.js @@ -46,15 +46,41 @@ function fixRedirectIfNeeded(urldata, redirect) { return redirect; } +function translateStatusCode(statusCode) { + switch (statusCode) { + case 400: + return "The request for the audio/video link was rejected as invalid. " + + "Contact support for troubleshooting assistance."; + case 401: + case 403: + return "Access to the link was denied. Contact the owner of the " + + "website hosting the audio/video file to grant permission for " + + "the file to be downloaded."; + case 404: + return "The requested link could not be found (404)."; + case 500: + case 503: + return "The website hosting the audio/video link encountered an error " + + "and was unable to process the request. Try again in a few minutes, " + + "and if the issue persists, contact the owner of the website hosting " + + "the link."; + default: + return "An unknown issue occurred when requesting the audio/video link. " + + "Contact support for troubleshooting assistance."; + } +} + function testUrl(url, cb, redirCount) { if (!redirCount) redirCount = 0; var data = urlparse.parse(url); if (!/https?:/.test(data.protocol)) { - return cb("Video links must start with http:// or https://"); + return cb("Only links starting with 'http://' or 'https://' are supported " + + "for raw audio/video support"); } if (!data.hostname) { - return cb("Invalid link"); + return cb("The link to the file is missing the website address and can't " + + "be processed."); } var transport = (data.protocol === "https:") ? https : http; @@ -64,29 +90,33 @@ function testUrl(url, cb, redirCount) { if (res.statusCode === 301 || res.statusCode === 302) { if (redirCount > 2) { - return cb("Too many redirects. Please provide a direct link to the " + - "file"); + return cb("The request for the audio/video file has been redirected " + + "more than twice. This could indicate a misconfiguration " + + "on the website hosting the link. For best results, use " + + "a direct link."); } return testUrl(fixRedirectIfNeeded(data, res.headers["location"]), cb, redirCount + 1); } if (res.statusCode !== 200) { - var message = res.statusMessage; - if (!message) message = ""; - return cb("HTTP " + res.statusCode + " " + message); + return cb(translateStatusCode(res.statusCode)); } if (!/^audio|^video/.test(res.headers["content-type"])) { - return cb("Server did not return an audio or video file, or sent the " + - "wrong Content-Type"); + return cb("Expected a content-type starting with 'audio' or 'video', but " + + "got '" + res.headers["content-type"] + "'. Only direct links " + + "to video and audio files are accepted, and the website hosting " + + "the file must be configured to send the correct MIME type."); } cb(); }); req.on("error", function (err) { - cb(err); + cb("An unexpected error occurred while trying to process the link. " + + "Try again, and contact support for further troubleshooting if the " + + "problem continues." + (!!err.code ? (" Error code: " + err.code) : "")); }); req.end(); @@ -215,7 +245,9 @@ exports.ffprobe = function ffprobe(filename, cb) { 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 " + (TIMEOUT/1000) + - " seconds"); + " seconds. To avoid this issue, encode your videos " + + "using the 'faststart' option: " + + "https://trac.ffmpeg.org/wiki/Encode/H.264#faststartforwebvideo"); child.kill("SIGKILL"); }, TIMEOUT); @@ -231,7 +263,9 @@ exports.ffprobe = function ffprobe(filename, cb) { stderr += data; if (stderr.match(/the tls connection was non-properly terminated/i)) { fflog("Killing ffprobe for " + filename + " due to TLS error"); - childErr = new Error("Remote server closed connection unexpectedly"); + childErr = new Error("The connection was closed unexpectedly. " + + "If the problem continues, contact support " + + "for troubleshooting assistance."); child.kill("SIGKILL"); } }); @@ -281,7 +315,7 @@ exports.query = function (filename, cb) { if (!filename.match(/^https?:\/\//)) { return cb("Raw file playback is only supported for links accessible via HTTP " + - "or HTTPS"); + "or HTTPS. Ensure that the link begins with 'http://' or 'https://'"); } testUrl(filename, function (err) { @@ -299,10 +333,11 @@ exports.query = function (filename, cb) { } else if (err.message) { if (err.message.match(/protocol not found/i)) return cb("Link uses a protocol unsupported by this server's " + - "version of ffmpeg"); + "version of ffmpeg. Some older versions of " + + "ffprobe/avprobe do not support HTTPS."); if (err.message.match(/exceeded time limit/) || - err.message.match(/remote server closed/i)) { + err.message.match(/closed unexpectedly/i)) { return cb(err.message); } @@ -310,11 +345,15 @@ exports.query = function (filename, cb) { // indicate a problem with the remote file, not with this code. if (!/(av|ff)probe/.test(String(err))) Logger.errlog.log(err.stack || err); - return cb("Unable to query file data with ffmpeg"); + return cb("An unexpected error occurred while trying to process " + + "the link. Contact support for troubleshooting " + + "assistance."); } else { if (!/(av|ff)probe/.test(String(err))) Logger.errlog.log(err.stack || err); - return cb("Unable to query file data with ffmpeg"); + return cb("An unexpected error occurred while trying to process " + + "the link. Contact support for troubleshooting " + + "assistance."); } } @@ -322,7 +361,9 @@ exports.query = function (filename, cb) { data = reformatData(data); } catch (e) { Logger.errlog.log(e.stack || e); - return cb("Unable to query file data with ffmpeg"); + return cb("An unexpected error occurred while trying to process " + + "the link. Contact support for troubleshooting " + + "assistance."); } if (data.medium === "video") { diff --git a/www/js/util.js b/www/js/util.js index c3f641c1..dd099773 100644 --- a/www/js/util.js +++ b/www/js/util.js @@ -2070,7 +2070,7 @@ function queueMessage(data, type) { } var newAlert = makeAlert(title, text, type) .addClass("linewrap qfalert qf-" + type) - .appendTo($("#queuefail")); + .prependTo($("#queuefail")); newAlert.find(".alert").data("reason", data.msg); }