9 Commits

Author SHA1 Message Date
dependabot[bot] 61eee9f92a Bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-11 01:15:07 +00:00
dependabot[bot] c0d30550a6 Bump word-wrap from 1.2.3 to 1.2.4
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-21 13:08:35 +02:00
Michael Fabian 'Xaymar' Dirks 2735d7b0c6 1.1.2: Fix some bugs regarding frame rate
- r_framerate doesn't exist, but r_frame_rate does.
- FFmpeg may misidentify CFR streams as pseudo-VFR, need to force it into the correct mode.
2023-01-09 11:22:57 +01:00
Michael Fabian 'Xaymar' Dirks 41989579f2 Fix framerate override and force CFR on pseudo-VFR content
Can't exactly support VFR :/
2023-01-09 11:21:45 +01:00
Michael Fabian 'Xaymar' Dirks 3f57e8b399 Add missing VSCode workspace file 2023-01-09 11:19:24 +01:00
Michael Fabian 'Xaymar' Dirks 67c85f5df8 Improve README 2022-12-27 16:34:07 +01:00
Michael Fabian 'Xaymar' Dirks dee9eed566 1.1.1: Fix filter chain and libvmaf input order
- The order of inputs to libvmaf is distorted, then reference. Earlier versions had this inverted accidentally.
- Format conversion now happens after color conversion and scaling, and now supports the optional argument.
2022-12-27 16:11:49 +01:00
Michael Fabian 'Xaymar' Dirks 9431689ac8 1.1.0: Percentiles for JSON logs
- Adds 50th, 75th, 90th, 95th, 99th and 99.9th percentile to the calculations in the JSON log output.
- Fixes being forced to calculate the vmaf_v0.6.1 model.
- Flips the order for scaling reference files.
2022-12-27 16:09:48 +01:00
Michael Fabian 'Xaymar' Dirks 611157ec67 Don't always print arguments to output 2022-12-27 16:08:30 +01:00
5 changed files with 189 additions and 46 deletions
+76
View File
@@ -0,0 +1,76 @@
# js-vmaf: Simple, but effective VMAF comparison tool
This is a simple wrapper around FFmpeg and VMAF to handle comparison of files.
```
$node . --help
usage: js-vmaf [--help] [--hide_banner] [-q] [-v] --ffmpeg FFMPEG --ffprobe FFPROBE [--vmaf VMAF] -r
REFERENCE [-o OUTPUT] [--flip] [-cs COLOR_SPACE] [-cp COLOR_PRIMARIES] [-ct COLOR_TRC]
[-cr COLOR_RANGE] [-p FORMAT] [-w WIDTH] [-h HEIGHT] [--fps FPS] [-f FEATURE] [-m MODEL]
[-t THREADS]
Path [Path ...]
A simple, yet effective tool to quickly compare one or more videos using VMAF.
positional arguments:
Path One or more paths to a distorted file or a directory containing distorted files.
optional arguments:
--help show this help message and exit
--hide_banner Hide license banner.
-q, --quiet Be quiet.
-v, --verbose Be verbose.
--ffmpeg FFMPEG Path to the FFmpeg binary to use.
--ffprobe FFPROBE Path to the FFprobe binary to use.
--vmaf VMAF Path to the VMAF binary to use. Will fall back to FFmpeg if not provided
-r REFERENCE, --reference REFERENCE
Reference file
-o OUTPUT, --output OUTPUT
The file name, including formatters, for the output log file.
--flip Scale, convert and resample to distorted file instead of reference file.
-cs COLOR_SPACE, --color_space COLOR_SPACE
Define the color space of the reference file.
-cp COLOR_PRIMARIES, --color_primaries COLOR_PRIMARIES
Define the color primaries of the reference file.
-ct COLOR_TRC, --color_trc COLOR_TRC
Define the color transfer characteristics of the reference file.
-cr COLOR_RANGE, --color_range COLOR_RANGE
Define the color range of the reference file.
-p FORMAT, --format FORMAT
Define the format for comparison.
-w WIDTH, --width WIDTH
Define the width for the comparision.
-h HEIGHT, --height HEIGHT
Define the height for the comparision.
--fps FPS Define the FPS for comparison.
-f FEATURE, --feature FEATURE
Enable (and configure) a feature
-m MODEL, --model MODEL
Enable (and configure) a model
-t THREADS, --threads THREADS
Number of threads to use.
```
## Installing
```
npm install
npm run build
```
## Examples
##### Compare all files in a directory
```
$(prog) --ffmpeg ffmpeg --ffprobe ffprobe -r /mnt/usb0/ref.mp4 /mnt/usb1/
```
##### Use the distorted files as the target size
The following command converts the reference to the same format, resolution, framerate and color as the distorted files. Ideal for bitrate optimization.
```
$(prog) --ffmpeg ffmpeg --ffprobe ffprobe --flip -r /mnt/usb0/ref.mp4 /mnt/usb1/
```
##### Resize everything to 1080p and convert to yuv420p
```
$(prog) --ffmpeg ffmpeg --ffprobe ffprobe -h 1080 -p yuv420p -r /mnt/usb0/ref.mp4 /mnt/usb1/
```
+8
View File
@@ -0,0 +1,8 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}
+34 -23
View File
@@ -1,15 +1,16 @@
{ {
"name": "js-vmaf", "name": "js-vmaf",
"version": "0.0.0", "version": "1.1.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "js-vmaf", "name": "js-vmaf",
"version": "0.0.0", "version": "1.1.2",
"license": "BSD 3-Clause \"New\" or \"Revised\" License", "license": "BSD 3-Clause \"New\" or \"Revised\" License",
"dependencies": { "dependencies": {
"argparse": "^2.0.1" "argparse": "^2.0.1",
"percentile": "^1.6.0"
}, },
"devDependencies": { "devDependencies": {
"@types/argparse": "^2.0.10", "@types/argparse": "^2.0.10",
@@ -436,12 +437,12 @@
} }
}, },
"node_modules/braces": { "node_modules/braces": {
"version": "3.0.2", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"fill-range": "^7.0.1" "fill-range": "^7.1.1"
}, },
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -801,9 +802,9 @@
} }
}, },
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.0.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
@@ -1266,6 +1267,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/percentile": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/percentile/-/percentile-1.6.0.tgz",
"integrity": "sha512-8vSyjdzwxGDHHwH+cSGch3A9Uj2On3UpgOWxWXMKwUvoAbnujx6DaqmV1duWXNiH/oEWpyVd6nSQccix6DM3Ng=="
},
"node_modules/picomatch": { "node_modules/picomatch": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
@@ -1567,9 +1573,9 @@
} }
}, },
"node_modules/word-wrap": { "node_modules/word-wrap": {
"version": "1.2.3", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@@ -1875,12 +1881,12 @@
} }
}, },
"braces": { "braces": {
"version": "3.0.2", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true, "dev": true,
"requires": { "requires": {
"fill-range": "^7.0.1" "fill-range": "^7.1.1"
} }
}, },
"callsites": { "callsites": {
@@ -2152,9 +2158,9 @@
} }
}, },
"fill-range": { "fill-range": {
"version": "7.0.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true, "dev": true,
"requires": { "requires": {
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
@@ -2499,6 +2505,11 @@
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true "dev": true
}, },
"percentile": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/percentile/-/percentile-1.6.0.tgz",
"integrity": "sha512-8vSyjdzwxGDHHwH+cSGch3A9Uj2On3UpgOWxWXMKwUvoAbnujx6DaqmV1duWXNiH/oEWpyVd6nSQccix6DM3Ng=="
},
"picomatch": { "picomatch": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
@@ -2683,9 +2694,9 @@
} }
}, },
"word-wrap": { "word-wrap": {
"version": "1.2.3", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
"dev": true "dev": true
}, },
"wrappy": { "wrappy": {
+3 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "js-vmaf", "name": "js-vmaf",
"version": "1.0.0", "version": "1.1.2",
"description": "A simple tool to quickly and correctly compare a reference file with a distorted file using VMAF.", "description": "A simple tool to quickly and correctly compare a reference file with a distorted file using VMAF.",
"main": "generated/index.js", "main": "generated/index.js",
"scripts": { "scripts": {
@@ -21,6 +21,7 @@
"typescript": "^4.9.4" "typescript": "^4.9.4"
}, },
"dependencies": { "dependencies": {
"argparse": "^2.0.1" "argparse": "^2.0.1",
"percentile": "^1.6.0"
} }
} }
+68 -21
View File
@@ -8,6 +8,7 @@ import CHILD_PROCESS from "node:child_process";
import PROCESS from "node:process"; import PROCESS from "node:process";
import PATH from "node:path"; import PATH from "node:path";
import FS from "node:fs"; import FS from "node:fs";
import PERCENTILE from "percentile";
function valueOrDefault(value : any, fallback : any) : any { function valueOrDefault(value : any, fallback : any) : any {
if (value === undefined) { if (value === undefined) {
@@ -119,7 +120,7 @@ class App {
this._argparse.add_argument("-m", "--model", { this._argparse.add_argument("-m", "--model", {
type: "str", type: "str",
action: "append", action: "append",
default: [ "version=vmaf_v0.6.1" ], default: [],
help: "Enable (and configure) a model" help: "Enable (and configure) a model"
}); });
@@ -224,9 +225,15 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
} }
async compare(path : string) { async compare(path : string) {
if (!this._args.quiet) console.log(`'${path}' Comparing...`); if (!this._args.quiet) console.log(`Comparing '${path}'...`);
const cmp = this.FFprobe([path]); let cmp;
try {
cmp = this.FFprobe([path]);
} catch {
console.error("Not a video file.");
return;
}
if (cmp.video.length == 0) { if (cmp.video.length == 0) {
console.error(`'${path}' Missing video track.`); console.error(`'${path}' Missing video track.`);
return; return;
@@ -246,16 +253,15 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
chain.push("setpts=PTS-STARTPTS"); chain.push("setpts=PTS-STARTPTS");
// Convert to the correct framerate. // Convert to the correct framerate.
if (this._args.fps || (this._ref.video[0].r_framerate !== fref.video[0].r_framerate)) { if (this._args.fps || (this._ref.video[0].r_frame_rate !== fref.video[0].r_frame_rate)) {
chain.push(`fps=${valueOrDefault(this._args.fps, fref.video[0].r_framerate)}`); chain.push(`fps=${valueOrDefault(this._args.fps, fref.video[0].r_frame_rate)}`);
} }
// Convert format and color. // Convert color.
if (this._args.color_space if (this._args.color_space
|| this._args.color_primaries || this._args.color_primaries
|| this._args.color_trc || this._args.color_trc
|| this._args.color_range || this._args.color_range
|| (this._ref.video[0].pix_fmt !== fref.video[0].pix_fmt)
|| (this._ref.video[0].color_space !== fref.video[0].color_space) || (this._ref.video[0].color_space !== fref.video[0].color_space)
|| (this._ref.video[0].color_primaries !== fref.video[0].color_primaries) || (this._ref.video[0].color_primaries !== fref.video[0].color_primaries)
|| (this._ref.video[0].color_transfer !== fref.video[0].color_transfer) || (this._ref.video[0].color_transfer !== fref.video[0].color_transfer)
@@ -268,8 +274,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
`:space=${valueOrDefault(this._args.color_space, valueOrDefault(fref.video[0].color_space, "bt709"))}` + `:space=${valueOrDefault(this._args.color_space, valueOrDefault(fref.video[0].color_space, "bt709"))}` +
`:primaries=${valueOrDefault(this._args.color_primaries, valueOrDefault(fref.video[0].color_primaries, "bt709"))}` + `:primaries=${valueOrDefault(this._args.color_primaries, valueOrDefault(fref.video[0].color_primaries, "bt709"))}` +
`:trc=${valueOrDefault(this._args.color_trc, valueOrDefault(fref.video[0].color_transfer, "bt709"))}` + `:trc=${valueOrDefault(this._args.color_trc, valueOrDefault(fref.video[0].color_transfer, "bt709"))}` +
`:range=${valueOrDefault(this._args.color_range, valueOrDefault(fref.video[0].color_range, "tv"))}` + `:range=${valueOrDefault(this._args.color_range, valueOrDefault(fref.video[0].color_range, "tv"))}`);
`:format=${valueOrDefault(this._args.format, valueOrDefault(fref.video[0].pix_fmt, "yuv420p"))}`);
} }
// Scale // Scale
@@ -291,6 +296,11 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
); );
} }
// Convert format.
if (this._args.format || (this._ref.video[0].pix_fmt !== fref.video[0].pix_fmt)) {
chain.push(`format=pix_fmts=${valueOrDefault(this._args.format, valueOrDefault(fref.video[0].pix_fmt, "yuv420p"))}`);
}
filters.push(`[0:v:0]${chain.join(",")}[ref]`); filters.push(`[0:v:0]${chain.join(",")}[ref]`);
} }
{ // Adjust distorted to the expected format. { // Adjust distorted to the expected format.
@@ -300,8 +310,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
chain.push("setpts=PTS-STARTPTS"); chain.push("setpts=PTS-STARTPTS");
// Convert to the correct framerate. // Convert to the correct framerate.
if (this._args.fps || (cmp.video[0].r_framerate !== fref.video[0].r_framerate)) { if (this._args.fps || (cmp.video[0].r_frame_rate !== fref.video[0].r_frame_rate)) {
chain.push(`fps=${valueOrDefault(this._args.fps, fref.video[0].r_framerate)}`); chain.push(`fps=${valueOrDefault(this._args.fps, fref.video[0].r_frame_rate)}`);
} }
// Convert format and color. // Convert format and color.
@@ -309,7 +319,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
|| this._args.color_primaries || this._args.color_primaries
|| this._args.color_trc || this._args.color_trc
|| this._args.color_range || this._args.color_range
|| (cmp.video[0].pix_fmt !== fref.video[0].pix_fmt)
|| (cmp.video[0].color_space !== fref.video[0].color_space) || (cmp.video[0].color_space !== fref.video[0].color_space)
|| (cmp.video[0].color_primaries !== fref.video[0].color_primaries) || (cmp.video[0].color_primaries !== fref.video[0].color_primaries)
|| (cmp.video[0].color_transfer !== fref.video[0].color_transfer) || (cmp.video[0].color_transfer !== fref.video[0].color_transfer)
@@ -322,8 +331,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
`:space=${valueOrDefault(this._args.color_space, valueOrDefault(fref.video[0].color_space, "bt709"))}` + `:space=${valueOrDefault(this._args.color_space, valueOrDefault(fref.video[0].color_space, "bt709"))}` +
`:primaries=${valueOrDefault(this._args.color_primaries, valueOrDefault(fref.video[0].color_primaries, "bt709"))}` + `:primaries=${valueOrDefault(this._args.color_primaries, valueOrDefault(fref.video[0].color_primaries, "bt709"))}` +
`:trc=${valueOrDefault(this._args.color_trc, valueOrDefault(fref.video[0].color_transfer, "bt709"))}` + `:trc=${valueOrDefault(this._args.color_trc, valueOrDefault(fref.video[0].color_transfer, "bt709"))}` +
`:range=${valueOrDefault(this._args.color_range, valueOrDefault(fref.video[0].color_range, "tv"))}` + `:range=${valueOrDefault(this._args.color_range, valueOrDefault(fref.video[0].color_range, "tv"))}`);
`:format=${valueOrDefault(this._args.format, valueOrDefault(fref.video[0].pix_fmt, "yuv420p"))}`);
} }
// Scale // Scale
@@ -345,6 +353,11 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
); );
} }
// Convert format.
if (this._args.format || (cmp.video[0].pix_fmt !== fref.video[0].pix_fmt)) {
chain.push(`format=pix_fmts=${valueOrDefault(this._args.format, valueOrDefault(fref.video[0].pix_fmt, "yuv420p"))}`);
}
filters.push(`[1:v:0]${chain.join(",")}[dst]`); filters.push(`[1:v:0]${chain.join(",")}[dst]`);
} }
@@ -361,22 +374,25 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
chain.push(`feature=${this._args.feature.join("|").replace(/([\\"'`:]{1,1})/g, "\\\\$1")}`); chain.push(`feature=${this._args.feature.join("|").replace(/([\\"'`:]{1,1})/g, "\\\\$1")}`);
} }
chain.push(`n_threads=${this._args.threads}`); chain.push(`n_threads=${this._args.threads}`);
filters.push(`[ref][dst]libvmaf=${chain.join(":")}`); filters.push(`[dst][ref]libvmaf=${chain.join(":")}`);
const proc = this.FFmpeg([ const proc = this.FFmpeg([
"-hide_banner", "-hide_banner",
"-v", "info", "-v", "quiet",
"-stats", "-stats",
"-hwaccel", "auto",
"-threads", this._args.threads, "-threads", this._args.threads,
"-strict", "strict", "-strict", "strict",
"-hwaccel", "auto",
"-hwaccel_flags", "+allow_high_depth", "-hwaccel_flags", "+allow_high_depth",
"-r", this._ref.video[0].r_frame_rate,
"-i", this._args.reference, "-i", this._args.reference,
"-threads", this._args.threads, "-threads", this._args.threads,
"-strict", "strict", "-strict", "strict",
"-hwaccel", "auto",
"-hwaccel_flags", "+allow_high_depth", "-hwaccel_flags", "+allow_high_depth",
"-r", cmp.video[0].r_frame_rate,
"-i", path, "-i", path,
"-sws_flags", "bicubic+full_chroma_inp+full_chroma_int", "-sws_flags", "bicubic+full_chroma_inp+full_chroma_int",
@@ -388,7 +404,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
"-f", "null", OS.platform() === "win32" ? "NUL" : "/dev/null" "-f", "null", OS.platform() === "win32" ? "NUL" : "/dev/null"
]); ]);
await new Promise((resolve, reject) => { const result : any = await new Promise((resolve, reject) => {
const sout : Array<string> = []; const sout : Array<string> = [];
const serr : Array<string> = []; const serr : Array<string> = [];
proc.addListener("exit", (code) => { proc.addListener("exit", (code) => {
@@ -420,15 +436,46 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AN
}); });
}); });
}); });
if (result.code !== 0) {
throw new Error("Unexpected failure running FFmpeg");
}
}
if (PATH.extname(log) === ".json") {
// Post-process the JSON file so we get more useful metrics.
const data = JSON.parse(FS.readFileSync(log).toString("utf-8"));
const prc = [50, 75, 90, 99, 99.9];
const frames : any = {};
for (const metric in data.pooled_metrics) {
frames[metric] = [];
}
for (const frame of data.frames) {
for (const metric in frame.metrics) {
frames[metric].push(frame.metrics[metric]);
}
}
for (const metric in data.pooled_metrics) {
for (const p in prc) {
data.pooled_metrics[metric][`${prc[p]}th %ile`] = PERCENTILE(
100 - prc[p],
frames[metric]
);
}
}
FS.writeFileSync(log, JSON.stringify(data, undefined, "\t"));
} }
} }
public async run() : Promise<number> { public async run() : Promise<number> {
this._args = this._argparse.parse_known_args();
this.license();
this._args = this._argparse.parse_args(); this._args = this._argparse.parse_args();
this.license();
if (!this._args.quiet) console.dir(this._args); //if (!this._args.quiet) console.dir(this._args);
// Probe information (color, fps, ...) about the reference file. // Probe information (color, fps, ...) about the reference file.
try { try {