mirror of https://github.com/calzoneman/sync.git
Update ffmpeg loader to work with newer fluent-ffmpeg; fix playlists
This commit is contained in:
parent
02771e6623
commit
ac10f05f21
|
@ -179,6 +179,6 @@ channel-blacklist: []
|
||||||
# If you have ffmpeg installed, you can query metadata from raw files, allowing
|
# If you have ffmpeg installed, you can query metadata from raw files, allowing
|
||||||
# server-synched raw file playback. This requires the following:
|
# server-synched raw file playback. This requires the following:
|
||||||
# * ffmpeg must be installed on the server
|
# * ffmpeg must be installed on the server
|
||||||
# * you must install the fluent-ffmpeg module (npm install fluent-ffmpeg)
|
# * you must install the fluent-ffmpeg module (npm install fluent-ffmpeg@~1.7.2)
|
||||||
ffmpeg:
|
ffmpeg:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
|
@ -885,7 +885,8 @@ PlaylistModule.prototype._addItem = function (media, data, user, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Warn about possibly unsupported formats */
|
/* Warn about possibly unsupported formats */
|
||||||
if (media.type === "fi" && media.meta.codec.indexOf("/") !== -1 &&
|
if (media.type === "fi" && media.meta.codec &&
|
||||||
|
media.meta.codec.indexOf("/") !== -1 &&
|
||||||
media.meta.codec !== "mov/h264" &&
|
media.meta.codec !== "mov/h264" &&
|
||||||
media.meta.codec !== "flv/h264") {
|
media.meta.codec !== "flv/h264") {
|
||||||
user.socket.emit("queueWarn", {
|
user.socket.emit("queueWarn", {
|
||||||
|
@ -1280,8 +1281,21 @@ PlaylistModule.prototype.handleQueuePlaylist = function (user, data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ancient playlists don't have full data */
|
||||||
|
if (pl.length > 0 && !pl[0].hasOwnProperty("title")) {
|
||||||
pl.forEach(function (item) {
|
pl.forEach(function (item) {
|
||||||
var m = new Media(item.id, item.title, item.seconds, item.type);
|
self.handleQueue(user, {
|
||||||
|
id: item.id,
|
||||||
|
type: item.type,
|
||||||
|
pos: data.pos,
|
||||||
|
temp: temp
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl.forEach(function (item) {
|
||||||
|
var m = new Media(item.id, item.title, item.seconds, item.type, item.meta);
|
||||||
self._addItem(m, qdata, user);
|
self._addItem(m, qdata, user);
|
||||||
});
|
});
|
||||||
self.channel.activeLock.release();
|
self.channel.activeLock.release();
|
||||||
|
|
|
@ -405,7 +405,11 @@ module.exports.saveUserPlaylist = function (pl, username, plname, callback) {
|
||||||
id: pl[i].media.id,
|
id: pl[i].media.id,
|
||||||
title: pl[i].media.title,
|
title: pl[i].media.title,
|
||||||
seconds: pl[i].media.seconds,
|
seconds: pl[i].media.seconds,
|
||||||
type: pl[i].media.type
|
type: pl[i].media.type,
|
||||||
|
meta: {
|
||||||
|
codec: pl[i].media.meta.codec,
|
||||||
|
bitrate: pl[i].media.meta.bitrate
|
||||||
|
}
|
||||||
};
|
};
|
||||||
time += pl[i].media.seconds;
|
time += pl[i].media.seconds;
|
||||||
tmp.push(e);
|
tmp.push(e);
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
var Logger = require("./logger");
|
var Logger = require("./logger");
|
||||||
var Config = require("./config");
|
var Config = require("./config");
|
||||||
var Metadata;
|
var ffprobe;
|
||||||
var enabled = false;
|
var enabled = false;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
if (Config.get("ffmpeg.enabled")) {
|
if (Config.get("ffmpeg.enabled")) {
|
||||||
try {
|
try {
|
||||||
Metadata = require("fluent-ffmpeg").Metadata;
|
ffprobe = require("fluent-ffmpeg").ffprobe;
|
||||||
Logger.syslog.log("Enabling raw file support with fluent-ffmpeg");
|
Logger.syslog.log("Enabling raw file support with fluent-ffmpeg");
|
||||||
enabled = true;
|
enabled = true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -34,7 +34,7 @@ var audioOnlyContainers = {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.query = function (filename, cb) {
|
exports.query = function (filename, cb) {
|
||||||
if (!Metadata) {
|
if (!ffprobe) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,14 +47,18 @@ exports.query = function (filename, cb) {
|
||||||
"or HTTPS");
|
"or HTTPS");
|
||||||
}
|
}
|
||||||
|
|
||||||
new Metadata(filename, function (meta, err) {
|
ffprobe(filename, function (err, meta) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(err);
|
return cb("Unable to query file data with ffmpeg");
|
||||||
|
}
|
||||||
|
|
||||||
|
meta = parse(meta);
|
||||||
|
if (meta == null) {
|
||||||
|
return cb("Unknown error");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isVideo(meta)) {
|
if (isVideo(meta)) {
|
||||||
var video = meta.video;
|
var codec = meta.container + "/" + meta.vcodec;
|
||||||
var codec = video.container + "/" + video.codec;
|
|
||||||
|
|
||||||
if (!(codec in acceptedCodecs)) {
|
if (!(codec in acceptedCodecs)) {
|
||||||
return cb("Unsupported video codec " + codec);
|
return cb("Unsupported video codec " + codec);
|
||||||
|
@ -62,15 +66,14 @@ exports.query = function (filename, cb) {
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
title: meta.title || "Raw Video",
|
title: meta.title || "Raw Video",
|
||||||
duration: Math.ceil(meta.durationsec),
|
duration: Math.ceil(meta.seconds),
|
||||||
bitrate: video.bitrate,
|
bitrate: meta.bitrate,
|
||||||
codec: codec
|
codec: codec
|
||||||
};
|
};
|
||||||
|
|
||||||
cb(null, data);
|
cb(null, data);
|
||||||
} else if (isAudio(meta)) {
|
} else if (isAudio(meta)) {
|
||||||
var audio = meta.audio;
|
var codec = meta.acodec;
|
||||||
var codec = audio.codec;
|
|
||||||
|
|
||||||
if (!(codec in acceptedAudioCodecs)) {
|
if (!(codec in acceptedAudioCodecs)) {
|
||||||
return cb("Unsupported audio codec " + codec);
|
return cb("Unsupported audio codec " + codec);
|
||||||
|
@ -78,8 +81,8 @@ exports.query = function (filename, cb) {
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
title: meta.title || "Raw Audio",
|
title: meta.title || "Raw Audio",
|
||||||
duration: Math.ceil(meta.durationsec),
|
duration: Math.ceil(meta.seconds),
|
||||||
bitrate: audio.bitrate,
|
bitrate: meta.bitrate,
|
||||||
codec: codec
|
codec: codec
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,13 +99,36 @@ exports.query = function (filename, cb) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function isVideo(meta) {
|
function isVideo(meta) {
|
||||||
return meta.video &&
|
return meta.vcodec && !(meta.container in audioOnlyContainers);
|
||||||
meta.video.bitrate > 0 &&
|
|
||||||
meta.video.container &&
|
|
||||||
meta.video.codec &&
|
|
||||||
!(meta.video.container in audioOnlyContainers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAudio(meta) {
|
function isAudio(meta) {
|
||||||
return meta.audio && meta.audio.bitrate > 0 && meta.audio.codec;
|
return meta.acodec;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(meta) {
|
||||||
|
if (meta == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!meta.format) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = {};
|
||||||
|
meta.streams.forEach(function (s) {
|
||||||
|
if (s.codec_type === "video") {
|
||||||
|
data.vcodec = s.codec_name;
|
||||||
|
} else if (s.codec_type === "audio") {
|
||||||
|
data.acodec = s.codec_name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
data.container = meta.format.format_name.split(",")[0];
|
||||||
|
data.bitrate = parseInt(meta.format.bit_rate) / 1000;
|
||||||
|
if (meta.format.tags) {
|
||||||
|
data.title = meta.format.tags.title;
|
||||||
|
}
|
||||||
|
data.seconds = Math.ceil(parseFloat(meta.format.duration));
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ The above copyright notice and this permission notice shall be included in all c
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const VERSION = "3.2.0";
|
const VERSION = "3.2.1";
|
||||||
var singleton = null;
|
var singleton = null;
|
||||||
var Config = require("./config");
|
var Config = require("./config");
|
||||||
|
|
||||||
|
|
|
@ -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.2.0",
|
"version": "3.2.1",
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "http://github.com/calzoneman/sync"
|
"url": "http://github.com/calzoneman/sync"
|
||||||
},
|
},
|
||||||
|
|
|
@ -398,7 +398,7 @@ $("#mediaurl").keyup(function(ev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = $("#mediaurl").val().split("?")[0];
|
var url = $("#mediaurl").val().split("?")[0];
|
||||||
if (url.match(/^https?:\/\/(.*)?\.(flv|mp4|og[gv]|webm|mp3)$/)) {
|
if (url.match(/^https?:\/\/(.*)?\.(flv|mp4|og[gv]|webm|mp3|mov)$/)) {
|
||||||
var title = $("#addfromurl-title");
|
var title = $("#addfromurl-title");
|
||||||
if (title.length === 0) {
|
if (title.length === 0) {
|
||||||
title = $("<div/>")
|
title = $("<div/>")
|
||||||
|
|
|
@ -1289,7 +1289,7 @@ function parseMediaLink(url) {
|
||||||
/* Raw file */
|
/* Raw file */
|
||||||
var tmp = url.split("?")[0];
|
var tmp = url.split("?")[0];
|
||||||
if (tmp.match(/^https?:\/\//)) {
|
if (tmp.match(/^https?:\/\//)) {
|
||||||
if (tmp.match(/\.(mp4|flv|webm|og[gv]|mp3)$/)) {
|
if (tmp.match(/\.(mp4|flv|webm|og[gv]|mp3|mov)$/)) {
|
||||||
return {
|
return {
|
||||||
id: url,
|
id: url,
|
||||||
type: "fi"
|
type: "fi"
|
||||||
|
@ -1298,7 +1298,7 @@ function parseMediaLink(url) {
|
||||||
Callbacks.queueFail({
|
Callbacks.queueFail({
|
||||||
link: url,
|
link: url,
|
||||||
msg: "The file you are attempting to queue does not match the supported " +
|
msg: "The file you are attempting to queue does not match the supported " +
|
||||||
"file extensions mp4, flv, webm, ogg, ogv, mp3."
|
"file extensions mp4, flv, webm, ogg, ogv, mp3, mov."
|
||||||
});
|
});
|
||||||
throw new Error("ERROR_QUEUE_UNSUPPORTED_EXTENSION");
|
throw new Error("ERROR_QUEUE_UNSUPPORTED_EXTENSION");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue