Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 46bb3ceaa2 | |||
| 5304468669 | |||
| 5c9331b3e5 | |||
| c7a71cfd91 | |||
| 49f74bf48c | |||
| cf1ae76b22 | |||
| 3d6372bb34 | |||
| 1e56ab6dc0 | |||
| b147e2054e | |||
| 721dfa41de | |||
| ea5a9c02d2 |
@@ -0,0 +1,35 @@
|
|||||||
|
# Video Encoding Samples
|
||||||
|
Video Encoding Samples (VES) is a project to determine the ideal (or even best) settings for any available encoder through comparison with [VMAF](https://github.com/Netflix/vmaf), SSIM and PSNR. It was previously used to generate the data shown on [the old website](https://ves.xaymar.com/1.0/) which will eventually be replaced by new, up to date information.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
* A CPU with 4 Cores & 8 Threads, or 6 Cores & 6 Threads.
|
||||||
|
* Any of the compatible Operating Systems:
|
||||||
|
* Windows 10 64 bit
|
||||||
|
* Windows 7 64 bit
|
||||||
|
* [Node.JS v15.0 or newer](https://nodejs.org/en/download/current/)
|
||||||
|
* [FFmpeg](https://github.com/Xaymar/video-encoding-samples/releases/download/0.1.0/ffmpeg.7z)
|
||||||
|
* [VMAF Model "4K RB v0.6.2"](https://github.com/Netflix/vmaf/tree/master/model/vmaf_4k_rb_v0.6.2)
|
||||||
|
* Any number of input Videos
|
||||||
|
* A lot of time.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
The tool currently has no special parameters and reads its entire configuration from the `config.json` file, so you can invoke it by calling node.js with the script argument:
|
||||||
|
|
||||||
|
* Default (usually fits): `node ./ves.js`
|
||||||
|
* Or for larger configuraitons: `node --max-old-space-size=8192 ./ves.js`
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
1. Grab the latest release source code (or just master source code) and extract it to any directory.
|
||||||
|
2. Install the latest FFmpeg versions for your platform that supports libvmaf (or built it yourself):
|
||||||
|
* Windows: Extract [this archive](https://github.com/Xaymar/video-encoding-samples/releases/download/0.1.0/ffmpeg.7z) into `ffmpeg/`.
|
||||||
|
* Linux (apt): `apt-get install ffmpeg`
|
||||||
|
3. Grab the recommended model (see requirements) and place it into `ffmpeg/vmaf/`.
|
||||||
|
* It is possible to use different models, however this model has so far given the most accurate results.
|
||||||
|
4. Put any source video files in `videos/`.
|
||||||
|
* Videos must be properly tagged or they will be treated as bt709/bt709/bt709/tv.
|
||||||
|
* Video files must be in .mkv format.
|
||||||
|
5. Adjust the `config.json` file to your needs.
|
||||||
|
6. Run the tool.
|
||||||
|
|
||||||
|
## Further Information
|
||||||
|
* [Configuration Information](https://github.com/Xaymar/video-encoding-samples/wiki/Configuration)
|
||||||
+15
-17
@@ -32,24 +32,23 @@
|
|||||||
"h264_nvenc": {
|
"h264_nvenc": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"pool": "nvenc",
|
"pool": "nvenc",
|
||||||
"parallel": 3,
|
"parallel": 2,
|
||||||
"gpu": -1,
|
"gpu": -1,
|
||||||
"presets": [
|
"presets": [
|
||||||
"p5",
|
|
||||||
"p6",
|
|
||||||
"p7"
|
"p7"
|
||||||
],
|
],
|
||||||
"tunes": [
|
"tunes": [
|
||||||
"hq"
|
"hq"
|
||||||
],
|
],
|
||||||
"rc-lookahead": [
|
"rc-lookahead": [
|
||||||
0,
|
32,
|
||||||
16,
|
16,
|
||||||
32
|
0
|
||||||
],
|
],
|
||||||
"bframes": [
|
"bframes": [
|
||||||
2,
|
4,
|
||||||
3
|
3,
|
||||||
|
2
|
||||||
],
|
],
|
||||||
"bframe_reference_mode": [
|
"bframe_reference_mode": [
|
||||||
"middle"
|
"middle"
|
||||||
@@ -61,7 +60,7 @@
|
|||||||
"hevc_nvenc": {
|
"hevc_nvenc": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"pool": "nvenc",
|
"pool": "nvenc",
|
||||||
"parallel": 3,
|
"parallel": 2,
|
||||||
"gpu": -1
|
"gpu": -1
|
||||||
},
|
},
|
||||||
"h264_amf": {
|
"h264_amf": {
|
||||||
@@ -108,7 +107,7 @@
|
|||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
"arma_3-002": {
|
"arma_3-002": {
|
||||||
"enabled": true
|
"enabled": false
|
||||||
},
|
},
|
||||||
"black_mesa-001": {
|
"black_mesa-001": {
|
||||||
"enabled": false
|
"enabled": false
|
||||||
@@ -198,7 +197,7 @@
|
|||||||
},
|
},
|
||||||
"vmaf": {
|
"vmaf": {
|
||||||
"model": "vmaf_4k_rb_v0.6.2.pkl",
|
"model": "vmaf_4k_rb_v0.6.2.pkl",
|
||||||
"threads": 0
|
"threads": 3
|
||||||
},
|
},
|
||||||
"resolutions": [
|
"resolutions": [
|
||||||
[
|
[
|
||||||
@@ -223,17 +222,16 @@
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
"framerate_scalings": [
|
"framerate_scalings": [
|
||||||
1.0,
|
1.0
|
||||||
0.5
|
|
||||||
],
|
],
|
||||||
"bitrates": [
|
"bitrates": [
|
||||||
3500,
|
8000,
|
||||||
6000,
|
6000,
|
||||||
8000
|
3500
|
||||||
],
|
],
|
||||||
"keyframeinterval": [
|
"keyframeinterval": [
|
||||||
1.0,
|
2.0,
|
||||||
2.0
|
1.0
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ const path = require('path');
|
|||||||
const process = require('process');
|
const process = require('process');
|
||||||
const child_process = require('child_process');
|
const child_process = require('child_process');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
function parse_duration(str) {
|
function parse_duration(str) {
|
||||||
// Duration is in the form HH:MM:SS.fraction
|
// Duration is in the form HH:MM:SS.fraction
|
||||||
@@ -14,13 +15,20 @@ function parse_duration(str) {
|
|||||||
|
|
||||||
class ffmpeg {
|
class ffmpeg {
|
||||||
constructor(ffpath) {
|
constructor(ffpath) {
|
||||||
// Figure out the location of FFmpeg
|
this.bin = {};
|
||||||
if (!ffpath)
|
this.bin.ffmpeg = "ffmpeg";
|
||||||
ffpath = process.cwd();
|
this.bin.ffprobe = "ffprobe";
|
||||||
this.bin = {
|
if (os.platform() == "win32") { // Windows has special behavior - system installed FFmpeg is rare.
|
||||||
ffmpeg: path.join(ffpath, "bin/ffmpeg.exe"),
|
let ffmpeg_local = path.join((ffpath ? ffpath : process.cwd()), "bin/ffmpeg.exe");
|
||||||
ffprobe: path.join(ffpath, "bin/ffprobe.exe")
|
if (fs.existsSync(ffmpeg_local)) {
|
||||||
};
|
this.bin.ffmpeg = ffmpeg_local;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ffprobe_local = path.join((ffpath ? ffpath : process.cwd()), "bin/ffprobe.exe");
|
||||||
|
if (fs.existsSync(ffmpeg_local)) {
|
||||||
|
this.bin.ffmpeg = ffprobe_local;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_probeParse(buffer) {
|
_probeParse(buffer) {
|
||||||
|
|||||||
@@ -382,6 +382,7 @@ async function work(config, ff, videos, encoders) {
|
|||||||
console.time(video_key);
|
console.time(video_key);
|
||||||
let video = videos.get(video_key);
|
let video = videos.get(video_key);
|
||||||
for (let cache_key of video.caches.keys()) {
|
for (let cache_key of video.caches.keys()) {
|
||||||
|
console.group(cache_key);
|
||||||
console.time(cache_key);
|
console.time(cache_key);
|
||||||
let cache = video.caches.get(cache_key);
|
let cache = video.caches.get(cache_key);
|
||||||
|
|
||||||
@@ -450,7 +451,10 @@ async function work(config, ff, videos, encoders) {
|
|||||||
|
|
||||||
if (filter != "")
|
if (filter != "")
|
||||||
filter = `${filter};` // [temp:${idx}];[temp:${idx}]
|
filter = `${filter};` // [temp:${idx}];[temp:${idx}]
|
||||||
filter = `${filter}[${idx}:v:0]scale=flags=bicubic+full_chroma_inp+full_chroma_int:w=${video.resolution.width.toFixed(0)}:h=${video.resolution.height.toFixed(0)},colorspace=ispace=${config.options.transcode.color.matrix}:itrc=${config.options.transcode.color.trc}:iprimaries=${config.options.transcode.color.primaries}:irange=${config.options.transcode.color.range}:space=${video.color.matrix}:trc=${video.color.trc}:primaries=${video.color.primaries}:range=${video.color.range},format=pix_fmts=yuv444p,fps=fps=${video.framerate.toFixed(2)},[ref:${idx}]libvmaf=model_path=${vmaf_model}:log_fmt=json:log_path=${ff.consolify(file[1])}:enable_conf_interval=1:psnr=1:ssim=1:n_threads=${config.options.vmaf.threads.toFixed(0)}[main:${idx}]`
|
filter += `[${idx+1}:v:0]scale=flags=bicubic+full_chroma_inp+full_chroma_int:w=${video.resolution.width.toFixed(0)}:h=${video.resolution.height.toFixed(0)}`
|
||||||
|
+ `,colorspace=ispace=${config.options.transcode.color.matrix}:itrc=${config.options.transcode.color.trc}:iprimaries=${config.options.transcode.color.primaries}:irange=${config.options.transcode.color.range}:space=${video.color.matrix}:trc=${video.color.trc}:primaries=${video.color.primaries}:range=${video.color.range}`
|
||||||
|
+ `,format=pix_fmts=yuv444p,fps=fps=${video.framerate.toFixed(2)}[scaled:${idx}]`
|
||||||
|
+ `;[scaled:${idx}][${references[idx]}libvmaf=model_path=${vmaf_model}:log_fmt=json:log_path=${ff.consolify(file[1])}:enable_conf_interval=1:psnr=1:ssim=1:n_threads=${(config.options.vmaf.threads / files.length).toFixed(0)}[main:${idx}]`
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.push("-filter_complex", filter);
|
opts.push("-filter_complex", filter);
|
||||||
@@ -477,6 +481,7 @@ async function work(config, ff, videos, encoders) {
|
|||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
console.timeEnd(LABEL);
|
console.timeEnd(LABEL);
|
||||||
}
|
}
|
||||||
|
console.groupEnd(cache_key);
|
||||||
console.timeEnd(cache_key);
|
console.timeEnd(cache_key);
|
||||||
}
|
}
|
||||||
console.timeEnd(video_key);
|
console.timeEnd(video_key);
|
||||||
|
|||||||
Reference in New Issue
Block a user