Hardware-Transcoding in Peertube (Docker)

Continuing the discussion from Ffmpeg transcoding profile - native and through plugin:

I would also be interested in Hardware-accelerated transcoding.

The first thing is to check which encoders are available. I am using a docker setup here running on a virtual server from the provider OVH.

docker compose exec -u root peertube sh -c 'ffmpeg -encoders | grep 264'


ffmpeg version 4.3.5-0+deb11u1 Copyright (c) 2000-2022 the FFmpeg developers
  built with gcc 10 (Debian 10.2.1-6)
  configuration: --prefix=/usr --extra-version=0+deb11u1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-pocketsphinx --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 51.100 / 56. 51.100
  libavcodec     58. 91.100 / 58. 91.100
  libavformat    58. 45.100 / 58. 45.100
  libavdevice    58. 10.100 / 58. 10.100
  libavfilter     7. 85.100 /  7. 85.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  7.100 /  5.  7.100
  libswresample   3.  7.100 /  3.  7.100
  libpostproc    55.  7.100 / 55.  7.100
 V..... libx264              libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (codec h264)
 V..... libx264rgb           libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 RGB (codec h264)
 V..... h264_omx             OpenMAX IL H.264 video encoder (codec h264)
 V..... h264_qsv             H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration) (codec h264)
 V..... h264_v4l2m2m         V4L2 mem2mem H.264 encoder wrapper (codec h264)
 V..... h264_vaapi           H.264/AVC (VAAPI) (codec h264)

So this ffmpeg was built with support for QSV and VAAPI. It does not mean that the server offers also the resources required to use it (namely /dev/dri).

1 Like

QSV is the Intel API for hardware-accelerated encoding and decoding.
On my development machine with an Intel chip, I had good results with QSV.


VAAPI is a multi-vendor open API.


The wiki has examples for hardware transcoding, e.g. this one with conversion from h265 to h264:

ffmpeg -hwaccel qsv -c:v hevc_qsv -i input.mp4 -vf 'vpp_qsv=framerate=60,scale_qsv=w=1920:h=1080' -c:v h264_qsv output.mp4

To create a plugin for hardware-accelarated ffmpeg profiles, the starting point would be Théo Le Calvar / peertube-plugin-hardware-transcode-vaapi · GitLab . A year ago, the author tried to generate those ffmpeg options programatically, but the development seemed to be stalled.

The thing looks quite complex, so maybe monkey patching the source in peertube is quicker for the time being. :see_no_evil:

This plugin itself is quite crude, but it works and is a very good starting point to any further development. It would be nice to have it as native feature of peertube. Last time I’ve checked it didn’t receive any updates for the last 2 years.

I’m the author of the plugin. As is it should be considered experimental but it worked OK on my hardware (which was equipped with a Intel i5-6500T cpu).

I know a few bugs that I could not fix with the plugin API at the time. It was related to source files that were not compatible with my hardware (the CPU I have cannot hardware decode h265 or av1 files) and I was not able to detect these files with the plugin API at the time (see this issue) so these tasks would fail and Peertube would not try them agin on another profile. I planned to make the feature and update my plugin accordingly but I didn’t find the time with my new job.

I think that once the issue linked above is solved it should not be too hard to update the plugin to check if the input file is compatible with the hardware and accept the transcode task.


Alternatively use the plugin transcoding-profile-debug and use hardware encoding that way.

Is there an easy way to tell if Peertube is actually using hardware accel for transcoding with this plugin?

Yes. Since you have to setup and select HW encoding, if it is not working, no video will be output.

On intel CPUs, you can use intel_gpu_top (linux command line) and check how is the transcoding going.

You can also check CPU usage during transcode, if you see little activity during transcode job then it is likely to use HW encoding.

You can also check GPU usage using intel_gpu_top or similar tool.

The instructions say > Official docker images do not ship with required libraries for hardware transcode.
You can build your own image with this docker compose:< But what immediately follows looks like a Dockerfile, not a docker compose file. A little further down it shows what looks like a docker compose file but it references the regular peertube image, not a built or to be built Docker image. Can someone clarify this a bit?

I updated the readme with newer Dockerfile & the partial docker-compose.yml that I use. The docker-compose.yml expects the Dockerfile to be present in the same directory.

1 Like

I finally think I have the docker image setup correctly. Pardon my ignorance but where do I « select HW encoding »?

You can browse to the the admin page of Peertube then Configuration > VOD Transcoding > Transcoding Profile at the end of the page. If the plugin is correctly installed you should see a « vaapi » profile.
Selecting it and updating the configuration should be enough to switch to the profile and use hardware acceleration.

You can do something similar for « Live Streaming » if you also want to use the profile for streams.

Ah yes. I didn’t see a vaapi option in that menu when I first logged in but later on it did appear. That said, I can’t get any uploaded videos to actually play, regardless of the setting. I just get the grey spinning circle. I DO see the generated thumbnail.

You should check transcode jobs status in Admin > System > Jobs. You can filter them by selecting « video-transcode » in Job Type.
If they fail you should have access to logs detailing the error.

5 video-transcoding 102 4/27/23, 3:35:28.217 AM
Job: 5 Type: video-transcoding Processed on 4/27/23, 3:35:28.251 AM Finished on 4/27/23, 3:35:32.866 AM
{ « type »: « new-resolution-to-hls », « videoUUID »: « 3377094a-81fe-402b-8c55-422e0960b64a », « resolution »: 360, « hasAudio »: true, « copyCodecs »: false, « isMaxQuality »: false, « autoDeleteWebTorrentIfNeeded »: true, « isNewVideo »: true }

It doesn’t look like a failure.

You can see the state of the job in the web page but yeah, it looks like a success.

You can search for the generated file on the server storage and download it to check if you can play it locally.

I looked at your updated instructions and my Dockerfile was far more complicated. So I decided to start over and build the image fresh. Now I’m getting a error.

"err": {
    "stack": "Error: ffmpeg exited with code 1: Device creation failed: -22.\nFailed to set value '/dev/dri/renderD128' for option 'vaapi_device': Invalid argument\nError parsing global options: Invalid argument\n\n    at ChildProcess.<anonymous> (/app/node_modules/fluent-ffmpeg/lib/processor.js:182:22)\n    at ChildProcess.emit (node:events:513:28)\n    at Process.ChildProcess._handle.onexit (node:internal/child_process:293:12)",
    "message": "ffmpeg exited with code 1: Device creation failed: -22.\nFailed to set value '/dev/dri/renderD128' for option 'vaapi_device': Invalid argument\nError parsing global options: Invalid argument\n"

I’m using a Q1-17 xeon processor that I believe corresponds with a Gen 7. Intel® HD Graphics P630