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)
|
||||
+14
-16
@@ -32,24 +32,23 @@
|
||||
"h264_nvenc": {
|
||||
"enabled": true,
|
||||
"pool": "nvenc",
|
||||
"parallel": 3,
|
||||
"parallel": 2,
|
||||
"gpu": -1,
|
||||
"presets": [
|
||||
"p5",
|
||||
"p6",
|
||||
"p7"
|
||||
],
|
||||
"tunes": [
|
||||
"hq"
|
||||
],
|
||||
"rc-lookahead": [
|
||||
0,
|
||||
32,
|
||||
16,
|
||||
32
|
||||
0
|
||||
],
|
||||
"bframes": [
|
||||
2,
|
||||
3
|
||||
4,
|
||||
3,
|
||||
2
|
||||
],
|
||||
"bframe_reference_mode": [
|
||||
"middle"
|
||||
@@ -61,7 +60,7 @@
|
||||
"hevc_nvenc": {
|
||||
"enabled": false,
|
||||
"pool": "nvenc",
|
||||
"parallel": 3,
|
||||
"parallel": 2,
|
||||
"gpu": -1
|
||||
},
|
||||
"h264_amf": {
|
||||
@@ -108,7 +107,7 @@
|
||||
"enabled": false
|
||||
},
|
||||
"arma_3-002": {
|
||||
"enabled": true
|
||||
"enabled": false
|
||||
},
|
||||
"black_mesa-001": {
|
||||
"enabled": false
|
||||
@@ -198,7 +197,7 @@
|
||||
},
|
||||
"vmaf": {
|
||||
"model": "vmaf_4k_rb_v0.6.2.pkl",
|
||||
"threads": 0
|
||||
"threads": 3
|
||||
},
|
||||
"resolutions": [
|
||||
[
|
||||
@@ -223,17 +222,16 @@
|
||||
]
|
||||
],
|
||||
"framerate_scalings": [
|
||||
1.0,
|
||||
0.5
|
||||
1.0
|
||||
],
|
||||
"bitrates": [
|
||||
3500,
|
||||
8000,
|
||||
6000,
|
||||
8000
|
||||
3500
|
||||
],
|
||||
"keyframeinterval": [
|
||||
1.0,
|
||||
2.0
|
||||
2.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ const path = require('path');
|
||||
const process = require('process');
|
||||
const child_process = require('child_process');
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
|
||||
function parse_duration(str) {
|
||||
// Duration is in the form HH:MM:SS.fraction
|
||||
@@ -14,13 +15,20 @@ function parse_duration(str) {
|
||||
|
||||
class ffmpeg {
|
||||
constructor(ffpath) {
|
||||
// Figure out the location of FFmpeg
|
||||
if (!ffpath)
|
||||
ffpath = process.cwd();
|
||||
this.bin = {
|
||||
ffmpeg: path.join(ffpath, "bin/ffmpeg.exe"),
|
||||
ffprobe: path.join(ffpath, "bin/ffprobe.exe")
|
||||
};
|
||||
this.bin = {};
|
||||
this.bin.ffmpeg = "ffmpeg";
|
||||
this.bin.ffprobe = "ffprobe";
|
||||
if (os.platform() == "win32") { // Windows has special behavior - system installed FFmpeg is rare.
|
||||
let ffmpeg_local = path.join((ffpath ? ffpath : process.cwd()), "bin/ffmpeg.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) {
|
||||
|
||||
@@ -382,6 +382,7 @@ async function work(config, ff, videos, encoders) {
|
||||
console.time(video_key);
|
||||
let video = videos.get(video_key);
|
||||
for (let cache_key of video.caches.keys()) {
|
||||
console.group(cache_key);
|
||||
console.time(cache_key);
|
||||
let cache = video.caches.get(cache_key);
|
||||
|
||||
@@ -450,7 +451,10 @@ async function work(config, ff, videos, encoders) {
|
||||
|
||||
if (filter != "")
|
||||
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);
|
||||
@@ -477,6 +481,7 @@ async function work(config, ff, videos, encoders) {
|
||||
console.groupEnd();
|
||||
console.timeEnd(LABEL);
|
||||
}
|
||||
console.groupEnd(cache_key);
|
||||
console.timeEnd(cache_key);
|
||||
}
|
||||
console.timeEnd(video_key);
|
||||
|
||||
Reference in New Issue
Block a user