Various changes:
* Reformatted source code automatically. * Possible fix for x264 refusing to build lossless videos. * Allow encoders to add extra options to the command line, such as gpu selection.
This commit is contained in:
+13
-6
@@ -31,6 +31,7 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"pool": "nvenc",
|
"pool": "nvenc",
|
||||||
"parallel": 2,
|
"parallel": 2,
|
||||||
|
"gpu": -1,
|
||||||
"presets": [
|
"presets": [
|
||||||
"p5",
|
"p5",
|
||||||
"p6",
|
"p6",
|
||||||
@@ -55,32 +56,38 @@
|
|||||||
"hevc_nvenc": {
|
"hevc_nvenc": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"pool": "nvenc",
|
"pool": "nvenc",
|
||||||
"parallel": 3
|
"parallel": 2,
|
||||||
|
"gpu": -1
|
||||||
},
|
},
|
||||||
"h264_amf": {
|
"h264_amf": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"pool": "amf",
|
"pool": "amf",
|
||||||
"parallel": 3
|
"parallel": 2,
|
||||||
|
"gpu": -1
|
||||||
},
|
},
|
||||||
"hevc_amf": {
|
"hevc_amf": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"pool": "amf",
|
"pool": "amf",
|
||||||
"parallel": 3
|
"parallel": 2,
|
||||||
|
"gpu": -1
|
||||||
},
|
},
|
||||||
"h264_qsv": {
|
"h264_qsv": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"pool": "qsv",
|
"pool": "qsv",
|
||||||
"parallel": 3
|
"parallel": 2,
|
||||||
|
"gpu": -1
|
||||||
},
|
},
|
||||||
"hevc_qsv": {
|
"hevc_qsv": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"pool": "qsv",
|
"pool": "qsv",
|
||||||
"parallel": 3
|
"parallel": 2,
|
||||||
|
"gpu": -1
|
||||||
},
|
},
|
||||||
"vp9_qsv": {
|
"vp9_qsv": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"pool": "qsv",
|
"pool": "qsv",
|
||||||
"parallel": 3
|
"parallel": 2,
|
||||||
|
"gpu": -1
|
||||||
},
|
},
|
||||||
"libvpx-vp9": {
|
"libvpx-vp9": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ class encoder {
|
|||||||
get(index, width, height, framerate) {
|
get(index, width, height, framerate) {
|
||||||
throw new Error("Not Implemented");
|
throw new Error("Not Implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extra() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = encoder;
|
module.exports = encoder;
|
||||||
|
|||||||
@@ -139,15 +139,9 @@ class h264_nvenc extends encoder {
|
|||||||
return this.combinations[index];
|
return this.combinations[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
extra() {
|
||||||
for (let br of _config.bitrates)
|
return ["-gpu", settings.gpu];
|
||||||
"-b:v", `${br.toFixed(0)}k`,
|
}
|
||||||
"-bufsize", `${(br * 2).toFixed(0)}k`,
|
|
||||||
"-minrate", "0",
|
|
||||||
"-maxrate", `${br.toFixed(0)}k`,
|
|
||||||
for (let kfm of _config.keyframe_multiplier)
|
|
||||||
"-g", (_cache.fps * kfm).toFixed(0),
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = h264_nvenc;
|
module.exports = h264_nvenc;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function float_lt(a, b, edge) { return ((a + edge) < b); }
|
|||||||
function float_le(a, b, edge) { return float_lt(a, b, edge) || float_eq(a, b, edge); }
|
function float_le(a, b, edge) { return float_lt(a, b, edge) || float_eq(a, b, edge); }
|
||||||
function float_gt(a, b, edge) { return ((a - edge) > b); }
|
function float_gt(a, b, edge) { return ((a - edge) > b); }
|
||||||
function float_ge(a, b, edge) { return float_gt(a, b, edge) || float_eq(a, b, edge); }
|
function float_ge(a, b, edge) { return float_gt(a, b, edge) || float_eq(a, b, edge); }
|
||||||
Object.size = function(obj) { var size = 0, key; for (key in obj) { if (obj.hasOwnProperty(key)) { size++; } } return size; };
|
Object.size = function (obj) { var size = 0, key; for (key in obj) { if (obj.hasOwnProperty(key)) { size++; } } return size; };
|
||||||
|
|
||||||
// Actual Code
|
// Actual Code
|
||||||
async function load_config() { // Load Configuration
|
async function load_config() { // Load Configuration
|
||||||
@@ -103,7 +103,7 @@ async function load_videos(config, ff) { // Load Videos
|
|||||||
if (global.debug) console.debug(`${name} is disabled or invalid.`);
|
if (global.debug) console.debug(`${name} is disabled or invalid.`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the video exist?
|
// Does the video exist?
|
||||||
if (!fs.existsSync(path.join(config.paths.videos, `${name}.mkv`))) {
|
if (!fs.existsSync(path.join(config.paths.videos, `${name}.mkv`))) {
|
||||||
console.error(`${name} does not exist.`);
|
console.error(`${name} does not exist.`);
|
||||||
@@ -119,27 +119,27 @@ async function load_videos(config, ff) { // Load Videos
|
|||||||
probeprom.then((json) => {
|
probeprom.then((json) => {
|
||||||
let data = new Object();
|
let data = new Object();
|
||||||
|
|
||||||
data.name = name;
|
data.name = name;
|
||||||
data.info = json;
|
data.info = json;
|
||||||
data.caches = new Map();
|
data.caches = new Map();
|
||||||
|
|
||||||
// File Information
|
// File Information
|
||||||
data.file_name = `${name}.mkv`;
|
data.file_name = `${name}.mkv`;
|
||||||
data.file_ext = path.extname(data.file_name);
|
data.file_ext = path.extname(data.file_name);
|
||||||
data.file_base = path.basename(data.file_name, data.file_ext);
|
data.file_base = path.basename(data.file_name, data.file_ext);
|
||||||
data.file = path.join(config.paths.videos, data.file_name);
|
data.file = path.join(config.paths.videos, data.file_name);
|
||||||
|
|
||||||
// Video Information
|
// Video Information
|
||||||
data.resolution = { width: data.info.streams[0].width, height: data.info.streams[0].height };
|
data.resolution = { width: data.info.streams[0].width, height: data.info.streams[0].height };
|
||||||
data.framerate = eval(data.info.streams[0].r_frame_rate);
|
data.framerate = eval(data.info.streams[0].r_frame_rate);
|
||||||
data.duration = data.info.streams[0].duration;
|
data.duration = data.info.streams[0].duration;
|
||||||
|
|
||||||
// Color Information
|
// Color Information
|
||||||
data.color = {};
|
data.color = {};
|
||||||
data.color.range = data.info.streams[0].color_range ? data.info.streams[0].color_range : 'tv';
|
data.color.range = data.info.streams[0].color_range ? data.info.streams[0].color_range : 'tv';
|
||||||
data.color.trc = data.info.streams[0].color_transfer ? data.info.streams[0].color_transfer : 'bt709';
|
data.color.trc = data.info.streams[0].color_transfer ? data.info.streams[0].color_transfer : 'bt709';
|
||||||
data.color.primaries = data.info.streams[0].color_primaries ? data.info.streams[0].color_primaries : 'bt709';
|
data.color.primaries = data.info.streams[0].color_primaries ? data.info.streams[0].color_primaries : 'bt709';
|
||||||
data.color.matrix = data.info.streams[0].color_space ? data.info.streams[0].color_space : 'bt709';
|
data.color.matrix = data.info.streams[0].color_space ? data.info.streams[0].color_space : 'bt709';
|
||||||
|
|
||||||
videos.set(data.name, data);
|
videos.set(data.name, data);
|
||||||
console.timeEnd(name);
|
console.timeEnd(name);
|
||||||
@@ -202,11 +202,11 @@ async function create_caches(config, ff, videos, encoders) { // Create Caches
|
|||||||
if (fs.existsSync(cache.file)) {
|
if (fs.existsSync(cache.file)) {
|
||||||
let info = ff.probeSync(cache.file);
|
let info = ff.probeSync(cache.file);
|
||||||
if ((info.streams)
|
if ((info.streams)
|
||||||
&& (info.streams.length > 0)
|
&& (info.streams.length > 0)
|
||||||
&& (info.streams[0].width == cache.width)
|
&& (info.streams[0].width == cache.width)
|
||||||
&& (info.streams[0].height == cache.height)
|
&& (info.streams[0].height == cache.height)
|
||||||
&& float_eq(eval(info.streams[0].r_frame_rate), cache.framerate, 0.01)
|
&& float_eq(eval(info.streams[0].r_frame_rate), cache.framerate, 0.01)
|
||||||
&& float_eq(info.streams[0].duration, video.duration, 0.1)) {
|
&& float_eq(info.streams[0].duration, video.duration, 0.1)) {
|
||||||
if (global.debug) console.debug(`${key} already exists.`);
|
if (global.debug) console.debug(`${key} already exists.`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ async function create_caches(config, ff, videos, encoders) { // Create Caches
|
|||||||
if (encoders.has("h264_nvenc")) {
|
if (encoders.has("h264_nvenc")) {
|
||||||
command.push(
|
command.push(
|
||||||
"-c:v", "h264_nvenc",
|
"-c:v", "h264_nvenc",
|
||||||
"-profile:v", "high",
|
"-profile:v", "high",
|
||||||
"-preset", "p1",
|
"-preset", "p1",
|
||||||
"-tune", "lossless",
|
"-tune", "lossless",
|
||||||
"-rc", "constqp",
|
"-rc", "constqp",
|
||||||
@@ -244,7 +244,6 @@ async function create_caches(config, ff, videos, encoders) { // Create Caches
|
|||||||
} else {
|
} else {
|
||||||
command.push(
|
command.push(
|
||||||
"-c:v", "libx264",
|
"-c:v", "libx264",
|
||||||
"-profile:v", "high",
|
|
||||||
"-preset", "veryfast",
|
"-preset", "veryfast",
|
||||||
"-crf", "0",
|
"-crf", "0",
|
||||||
"-b:v", "0",
|
"-b:v", "0",
|
||||||
@@ -254,7 +253,7 @@ async function create_caches(config, ff, videos, encoders) { // Create Caches
|
|||||||
"-g", `15`,
|
"-g", `15`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
command.push(cache.file);
|
command.push(cache.file);
|
||||||
let res = ff.ffmpegSync(command);
|
let res = ff.ffmpegSync(command);
|
||||||
if (res.status != 0) {
|
if (res.status != 0) {
|
||||||
console.log(res.stderr.toString());
|
console.log(res.stderr.toString());
|
||||||
@@ -302,7 +301,7 @@ async function transcode(config, ff, videos, encoders) {
|
|||||||
let queue_files = new poolqueue();
|
let queue_files = new poolqueue();
|
||||||
for (let idx = 0; idx < encoder.count(); idx++) {
|
for (let idx = 0; idx < encoder.count(); idx++) {
|
||||||
let command_promises = [];
|
let command_promises = [];
|
||||||
let command = encoder.get(idx, cache.width, cache.height, cache.framerate);
|
let command = encoder.get(idx, cache.width, cache.height, cache.framerate);
|
||||||
for (let bitrate of config.options.bitrates) {
|
for (let bitrate of config.options.bitrates) {
|
||||||
for (let kfinterval of config.options.keyframeinterval) {
|
for (let kfinterval of config.options.keyframeinterval) {
|
||||||
command_promises.push(new Promise((resolve, reject) => {
|
command_promises.push(new Promise((resolve, reject) => {
|
||||||
@@ -342,7 +341,7 @@ async function transcode(config, ff, videos, encoders) {
|
|||||||
"-minrate", "0",
|
"-minrate", "0",
|
||||||
"-maxrate", "0",
|
"-maxrate", "0",
|
||||||
"-bufsize", `${2 * bitrate}k`,
|
"-bufsize", `${2 * bitrate}k`,
|
||||||
].concat(command.options).concat([file]);
|
].concat(command.options).concat(encoder.extra()).concat([file]);
|
||||||
|
|
||||||
queue_commands.push(
|
queue_commands.push(
|
||||||
encoder.pool(),
|
encoder.pool(),
|
||||||
@@ -359,7 +358,7 @@ async function transcode(config, ff, videos, encoders) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queue_promises.push(async function() {
|
queue_promises.push(async function () {
|
||||||
await Promise.allSettled(command_promises);
|
await Promise.allSettled(command_promises);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -379,8 +378,33 @@ async function transcode(config, ff, videos, encoders) {
|
|||||||
console.timeEnd("Subtotal");
|
console.timeEnd("Subtotal");
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
|
|
||||||
|
// Process from here on out.
|
||||||
|
// LOOP
|
||||||
|
// 1. Pull out front of the command and file queue.
|
||||||
|
// 2. Encode using the given command(s).
|
||||||
|
// 3. Compare resulting files with real input (libvmaf).
|
||||||
|
// 4. Delete encoded files.
|
||||||
|
// 5. Repeat until queues empty, no more caches for video, and no more videos.
|
||||||
|
|
||||||
|
/*
|
||||||
|
console.group("Queueing...")
|
||||||
|
console.time("Subtotal");
|
||||||
|
for (let video_key of videos.keys()) {
|
||||||
|
console.group(video_key);
|
||||||
|
console.time(video_key);
|
||||||
|
let video = videos.get(video_key);
|
||||||
|
for (let cache_key of video.caches.keys()) {
|
||||||
|
let cache = video.caches.get(cache_key);
|
||||||
|
console.time(cache_key);
|
||||||
|
|
||||||
|
console.timeEnd(cache_key);
|
||||||
|
}
|
||||||
|
console.timeEnd(video_key);
|
||||||
|
console.groupEnd();
|
||||||
|
}
|
||||||
|
console.timeEnd("Subtotal");
|
||||||
|
console.groupEnd();
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
for (let video_name in videos) {
|
for (let video_name in videos) {
|
||||||
console.time(video_name);
|
console.time(video_name);
|
||||||
|
|||||||
Reference in New Issue
Block a user