From 364994deccd1ffc4e0d025508636a885bab22170 Mon Sep 17 00:00:00 2001 From: knotteye Date: Sun, 8 Nov 2020 23:12:24 -0600 Subject: [PATCH 1/4] Start work on hardware acceleration. Documentation first, code later. --- docs/CONFIGURATION.md | 11 ++++---- docs/HWACCEL.md | 53 ++++++++++++++++++++++++++++++++++++++ install/config.example.yml | 4 +++ 3 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 docs/HWACCEL.md diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 839492d..4af0580 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -38,17 +38,16 @@ transcode: # satyr will generate one source quality variant, and the remaining # variants will be of incrementally lower quality and bitrate +# having more than 4-5 variants will start giving diminishing returns on stream quality for cpu load +# if you can't afford to generate at least 3 variants, it's recommended to leave adaptive streaming off + inputflags: "" # additional flags to apply to the input during transcoding outputflags: "" # additional flags to apply to the output during transcoding -# hardware acceleration is a bit difficult to configure programmatically -# this is a good place to do so for your system -# https://trac.ffmpeg.org/wiki/HWAccelIntro is a good place to start - -# having more than 4-5 variants will start giving diminishing returns on stream quality for cpu load -# if you can't afford to generate at least 3 variants, it's recommended to leave adaptive streaming off +hwaccel: +# See HWACCEL.md for information on configuring hardware acceleration. crypto: saltRounds: 12 diff --git a/docs/HWACCEL.md b/docs/HWACCEL.md new file mode 100644 index 0000000..f5595f3 --- /dev/null +++ b/docs/HWACCEL.md @@ -0,0 +1,53 @@ +## Configuration Hardware Acceleration +Satyr supports the NVENC and VA-API hardware acceleration APIs. If you've configured your system correctly (the hard part) it should be enough to set the type and use the default device setting if you only have one hardware acceleration device. + +### System +Configuring the system for any hardware acceleration API involves three main steps: selecting the right drivers, installing the API libraries, and configuring ffmpeg. + +#### NVENC +NVENC in ffmpeg can work with either open-source drivers (nouvea) or nvidia's proprietary drivers. The documentation for your distribution should have instructions for installing these. + +The only system library you should need is the CUDA toolkit, general named cudatoolkit, nvidia-cuda-toolkit, or some variation in your system repositories. +You can also try installing manually from [here](https://developer.nvidia.com/cuda-downloads). + +Most binary distributions provide a version of ffmpeg with NVENC already enabled. If not you can try compiling ffmpeg from source with the `--enable-nvenc` flag. If you use a source based distribution you should be familiar with enabling optional compile flags. + +You can verify that ffmpeg has been set up correctly by checking the output of `ffmpeg -hide_banner -hwaccels | grep cuvid` and `ffmpeg -hide_banner -encoders | grep nvenc`. If you don't see anything, something is wrong. + +#### VA-API +VA-API is an extremely generic API. Although the package names might be different in your distribution, the arch wiki page for hardware acceleration has good information on [driver selection](https://wiki.archlinux.org/index.php/Hardware_video_acceleration#Installation) and [verifying](https://wiki.archlinux.org/index.php/Hardware_video_acceleration#Verifying_VA-API) a VA-API install for a wide range of devices. + +Regardless of driver selection, you will also need libva or the equivalent from your distrubtion, and libva-utils can be helpful as well. + +Most binary distributions provide a version of ffmpeg with VA-API already enabled. If not you can try compiling ffmpeg from source with the `--enable-vaapi` flag. If you use a source based distribution you should be familiar with enabling optional compile flags. + +You can verify that ffmpeg has been set up correctly by checking the output of `ffmpeg -hide_banner -hwaccels | grep vaapi` and `ffmpeg -hide_banner -encoders | grep vaapi`. If you don't see anything, something is wrong. + +### Satyr +``` +# Decoding +hwaccel: +# Enable hardware acceleration for decoding as well as encoding. +# Probably not worth it, hardware decoding won't be any faster compared to software on a vaguely modern CPU +# Hardware decoding also may not support the input format, in which case transcoding will fail + decode: true + +# Only supported for VA-API +# Fall back to software decoding if hardware decoding fails +hwaccel: + decode: 'fallback' + + +# NVENC +hwaccel: + type: 'nvenc' +# device is optional for nvenc + device: 0 +# nvenc wants a device number instead of a path, set to null to disable + +# VA-API +hwaccel: + type: 'vaapi' +# device is mandatory for va-api + device: '/dev/dri/renderD128' +``` \ No newline at end of file diff --git a/install/config.example.yml b/install/config.example.yml index 4ea6987..2e81225 100644 --- a/install/config.example.yml +++ b/install/config.example.yml @@ -32,6 +32,10 @@ transcode: #unused right now, will always transcode to dash format: dash +hwaccel: + # see docs/HWACCEL.md for instructions on configuring hardware acceleration + type: null + chat: irc: -- 2.38.3 From 9df4b545ec7ac13919ac9013c4521016fbab8c40 Mon Sep 17 00:00:00 2001 From: knotteye Date: Sun, 10 Jan 2021 13:42:12 -0600 Subject: [PATCH 2/4] Update config.ts to include hwaccel options --- src/config.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/config.ts b/src/config.ts index 4c641a4..50669e4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -39,6 +39,11 @@ const config: Object = { connectionTimeout: '1000', insecureAuth: false, debug: false }, localconfig['database']), + hwaccel: Object.assign({ + type: null, + device: null, + decode: false + }, localconfig['hwaccel']), rtmp: Object.assign({ cluster: false, port: 1935, -- 2.38.3 From 1afd855e73655184536d44c12e396045ebadde79 Mon Sep 17 00:00:00 2001 From: knotteye Date: Sun, 10 Jan 2021 13:42:23 -0600 Subject: [PATCH 3/4] Clarify some documentation --- docs/HWACCEL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/HWACCEL.md b/docs/HWACCEL.md index f5595f3..748a7d7 100644 --- a/docs/HWACCEL.md +++ b/docs/HWACCEL.md @@ -43,7 +43,7 @@ hwaccel: type: 'nvenc' # device is optional for nvenc device: 0 -# nvenc wants a device number instead of a path, set to null to disable +# nvenc wants a device number instead of a path, set to null to use the default # VA-API hwaccel: -- 2.38.3 From 943c71d1e050a613e8af156c5e36f90162150081 Mon Sep 17 00:00:00 2001 From: knotteye Date: Sun, 10 Jan 2021 13:42:52 -0600 Subject: [PATCH 4/4] Add what I think is working hwaccel support --- src/server.ts | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/server.ts b/src/server.ts index dd60538..2406eca 100644 --- a/src/server.ts +++ b/src/server.ts @@ -42,9 +42,10 @@ function init () { if(session.audioCodec !== 0 && session.videoCodec !== 0){ transCommand(results[0].username, key).then((r) => { execFile(config['media']['ffmpeg'], r, {maxBuffer: Infinity}, (err, stdout, stderr) => { - /*console.log(err); - console.log(stdout); - console.log(stderr);*/ + //console.log(r); + //console.log(err); + //console.log(stdout); + //console.log(stderr); }); }); break; @@ -126,29 +127,49 @@ function init () { async function transCommand(user: string, key: string): Promise{ let args: string[] = ['-loglevel', 'fatal', '-y']; + let vcodec: string = 'libx264'; + if(config['hwaccel']['type'] === 'nvenc'){ + vcodec = 'h264_nvenc'; + if(config['hwaccel']['decode']){ + args = args.concat(['-hwaccel', 'cuda']); + if(config['hwaccel']['device']) + args = args.concat(['-hwaccel_device', config['hwaccel']['device']]); + args = args.concat(['-hwaccel_output_format', 'cuda']); + } + } + else if (config['hwaccel']['type'] === 'vaapi') { + vcodec = 'h264_vaapi'; + if(config['hwaccel']['decode'] === 'fallback'){ + args = args.concat('init_hw_device', 'vaapi=foo:'+config['hwaccel']['device'], '-hwaccel vaapi', '-hwaccel_output_format', 'vaapi', '-hwaccel_device', 'foo'); + } else if (config['hwaccel']['decode']) { + args = args.concat(['-hwaccel', 'vaapi', '-hwaccel_output_format', 'vaapi', '-vaapi_device', config['hwaccel']['device']]); + } + } if(config['transcode']['inputflags'] !== null && config['transcode']['inputflags'] !== "") args = args.concat(config['transcode']['inputflags'].split(" ")); args = args.concat(['-i', 'rtmp://127.0.0.1:'+config['rtmp']['port']+'/'+config['media']['privateEndpoint']+'/'+key, '-movflags', '+faststart']); if(config['transcode']['adaptive']===true && config['transcode']['variants'] > 1) { for(let i=0;i 51 ? 51 : Math.floor(18 + (i * 7)); args = args.concat(['-crf:'+i, ''+crf]); } for(let i=1;i