Refactored the ffprobe stream-selection logic to handle rejected files
better:

  * Streams tagged as a non-default disposition are not considered
  * If a file has any video stream, the audio stream will be ignored

This should prevent videos from being misreported as invalid audio
codecs, etc.
This commit is contained in:
calzoneman 2016-03-21 23:28:21 -07:00
parent a96b85fa5b
commit 7448429341
3 changed files with 65 additions and 29 deletions

View File

@ -2,7 +2,7 @@
"author": "Calvin Montgomery", "author": "Calvin Montgomery",
"name": "CyTube", "name": "CyTube",
"description": "Online media synchronizer and chat", "description": "Online media synchronizer and chat",
"version": "3.14.3", "version": "3.14.4",
"repository": { "repository": {
"url": "http://github.com/calzoneman/sync" "url": "http://github.com/calzoneman/sync"
}, },

View File

@ -113,6 +113,20 @@ function readOldFormat(buf) {
return data; return data;
} }
function isAlternateDisposition(stream) {
if (!stream.disposition) {
return false;
}
for (var key in stream) {
if (key !== "default" && stream.disposition[key]) {
return true;
}
}
return false;
}
function reformatData(data) { function reformatData(data) {
var reformatted = {}; var reformatted = {};
@ -127,24 +141,54 @@ function reformatData(data) {
reformatted.title = data.format.tags ? data.format.tags.title : null; reformatted.title = data.format.tags ? data.format.tags.title : null;
var container = data.format.format_name.split(",")[0]; var container = data.format.format_name.split(",")[0];
data.streams.forEach(function (stream) { var isVideo = false;
var audio = null;
for (var i = 0; i < data.streams.length; i++) {
const stream = data.streams[i];
// Trash streams with alternate dispositions, e.g. `attached_pic` for
// embedded album art on MP3s (not a real video stream)
if (isAlternateDisposition(stream)) {
continue;
}
if (stream.codec_type === "video" && if (stream.codec_type === "video" &&
acceptedCodecs.hasOwnProperty(container + "/" + stream.codec_name)) { !audioOnlyContainers.hasOwnProperty(container)) {
isVideo = true;
if (acceptedCodecs.hasOwnProperty(container + "/" + stream.codec_name)) {
reformatted.vcodec = stream.codec_name; reformatted.vcodec = stream.codec_name;
if (!reformatted.title && stream.tags) { reformatted.medium = "video";
reformatted.type = [container, reformatted.vcodec].join("/");
if (stream.tags && stream.tags.title) {
reformatted.title = stream.tags.title; reformatted.title = stream.tags.title;
} }
} else if (stream.codec_type === "audio") {
reformatted.acodec = stream.codec_name;
}
});
if (reformatted.vcodec && !(audioOnlyContainers.hasOwnProperty(container))) { return reformatted;
reformatted.type = [container, reformatted.vcodec].join("/"); }
reformatted.medium = "video"; } else if (stream.codec_type === "audio" && !audio &&
} else if (reformatted.acodec) { acceptedAudioCodecs.hasOwnProperty(stream.codec_name)) {
reformatted.type = [container, reformatted.acodec].join("/"); audio = {
reformatted.medium = "audio"; acodec: stream.codec_name,
medium: "audio"
};
if (stream.tags && stream.tags.title) {
audio.title = stream.tags.title;
}
}
}
// Override to make sure video files with no valid video streams but some
// acceptable audio stream are rejected.
if (isVideo) {
return reformatted;
}
if (audio) {
for (var key in audio) {
reformatted[key] = audio[key];
}
} }
return reformatted; return reformatted;
@ -273,10 +317,6 @@ exports.query = function (filename, cb) {
} }
if (data.medium === "video") { if (data.medium === "video") {
if (!acceptedCodecs.hasOwnProperty(data.type)) {
return cb("Unsupported video codec " + data.type);
}
data = { data = {
title: data.title || "Raw Video", title: data.title || "Raw Video",
duration: data.duration, duration: data.duration,
@ -286,10 +326,6 @@ exports.query = function (filename, cb) {
cb(null, data); cb(null, data);
} else if (data.medium === "audio") { } else if (data.medium === "audio") {
if (!acceptedAudioCodecs.hasOwnProperty(data.acodec)) {
return cb("Unsupported audio codec " + data.acodec);
}
data = { data = {
title: data.title || "Raw Audio", title: data.title || "Raw Audio",
duration: data.duration, duration: data.duration,
@ -299,9 +335,8 @@ exports.query = function (filename, cb) {
cb(null, data); cb(null, data);
} else { } else {
return cb("Parsed metadata did not contain a valid video or audio " + return cb("File did not contain an acceptable codec. See " +
"stream. Either the file is invalid or it has a format " + "https://git.io/va9g9 for details.");
"unsupported by this server's version of ffmpeg.");
} }
}); });
}); });

View File

@ -2064,6 +2064,7 @@ function queueMessage(data, type) {
} }
} }
var text = data.msg; var text = data.msg;
text = text.replace(/(https?:[^ ]+)/g, "<a href='$1' target='_blank'>$1</a>");
if (typeof data.link === "string") { if (typeof data.link === "string") {
text += "<br><a href='" + data.link + "' target='_blank'>" + text += "<br><a href='" + data.link + "' target='_blank'>" +
data.link + "</a>"; data.link + "</a>";