mirror of
https://github.com/alexta69/metube.git
synced 2026-09-21 13:35:01 +00:00
Add Hardware-accelerated transcoding guide (Intel VAAPI)
@@ -0,0 +1,142 @@
|
||||
yt-dlp can re-encode downloads with ffmpeg (via `postprocessor_args`), and on a
|
||||
machine with an Intel iGPU that encoding can run on the GPU instead of the CPU.
|
||||
The MeTube image already ships ffmpeg, but not the VAAPI driver, and the
|
||||
container has no access to the GPU by default. This page covers the three
|
||||
things you need to add.
|
||||
|
||||
Contributed by [@kamaeff](https://github.com/kamaeff) in
|
||||
[discussion #1045](https://github.com/alexta69/metube/discussions/1045), tested
|
||||
on Debian 13 with an Intel N150.
|
||||
|
||||
### 1. Install the VAAPI driver in the image
|
||||
|
||||
The MeTube image is based on `python:3.13-slim` (Debian), so you can layer the
|
||||
Intel media stack on top of it with a small Dockerfile of your own:
|
||||
|
||||
```dockerfile
|
||||
FROM ghcr.io/alexta69/metube:latest
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
intel-media-va-driver \
|
||||
libvpl2 \
|
||||
libmfx-gen1.2 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
```
|
||||
|
||||
Add `vainfo` to that list if you want to be able to check the driver from
|
||||
inside the container (see [Verifying](#verifying) below).
|
||||
|
||||
The host needs the Intel media drivers installed too, and `/dev/dri/card0` and
|
||||
`/dev/dri/renderD128` must exist there.
|
||||
|
||||
### 2. Give the container access to `/dev/dri`
|
||||
|
||||
Pass the devices through, and run MeTube with the host's `render` group so it's
|
||||
allowed to open them. Find the GID first:
|
||||
|
||||
```
|
||||
getent group render | cut -d: -f3
|
||||
```
|
||||
|
||||
Then, in your compose file:
|
||||
|
||||
```yaml
|
||||
metube:
|
||||
build: ./metube # the Dockerfile from step 1
|
||||
environment:
|
||||
- "PGID=993" # <- the render GID from above
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
```
|
||||
|
||||
Note that `PGID` is also the group MeTube's downloaded files end up owned by,
|
||||
since the entrypoint chowns the download directories to `PUID:PGID`. If you'd
|
||||
rather keep your own group for the files, set `user:` in compose instead — that
|
||||
makes the entrypoint skip its `gosu` step and keep whatever groups Docker gave
|
||||
the container, so a supplementary group works:
|
||||
|
||||
```yaml
|
||||
user: "1000:1000"
|
||||
group_add:
|
||||
- "993" # the render GID
|
||||
```
|
||||
|
||||
### 3. Tell ffmpeg to use the GPU
|
||||
|
||||
Encoding options go in `postprocessor_args`. The example below is a preset (via
|
||||
`YTDL_OPTIONS_PRESETS_FILE`) that decodes on the GPU, scales to 720p, and
|
||||
encodes to HEVC — all in hardware:
|
||||
|
||||
```json
|
||||
{
|
||||
"hevc-720p-vaapi": {
|
||||
"format": "bv*[height<=1440]+ba/b",
|
||||
"merge_output_format": "mp4",
|
||||
"postprocessors": [
|
||||
{ "key": "FFmpegCopyStream" }
|
||||
],
|
||||
"postprocessor_args": {
|
||||
"copystream+ffmpeg_i": [
|
||||
"-vaapi_device", "/dev/dri/renderD128",
|
||||
"-hwaccel", "vaapi",
|
||||
"-hwaccel_output_format", "vaapi"
|
||||
],
|
||||
"copystream+ffmpeg_o": [
|
||||
"-vf", "scale_vaapi=w=-2:h=720,fps=24",
|
||||
"-vcodec", "hevc_vaapi",
|
||||
"-qp", "26",
|
||||
"-tag:v", "hvc1",
|
||||
|
||||
"-acodec", "aac",
|
||||
"-ac", "1",
|
||||
"-b:a", "64k",
|
||||
|
||||
"-f", "mp4",
|
||||
"-movflags", "+faststart"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
What the pieces do:
|
||||
|
||||
* `-hwaccel vaapi` + `-hwaccel_output_format vaapi` — decode on the GPU and
|
||||
keep the decoded frames in GPU memory, so no copying back and forth.
|
||||
* `scale_vaapi` — resize on the GPU. Use this rather than `scale`; the regular
|
||||
filter can't operate on VAAPI surfaces.
|
||||
* `-vcodec hevc_vaapi` — encode with the hardware HEVC encoder (`h264_vaapi`
|
||||
for H.264).
|
||||
* The `copystream+ffmpeg_i` / `copystream+ffmpeg_o` keys attach the arguments
|
||||
to the `FFmpegCopyStream` postprocessor's ffmpeg invocation, `_i` before the
|
||||
input and `_o` before the output. Both matter here: `-hwaccel` is an input
|
||||
option and the filter/encoder settings are output options.
|
||||
|
||||
The same setup can be defined globally via `YTDL_OPTIONS` instead of as a
|
||||
preset, but a preset lets you pick hardware transcoding per download in the UI.
|
||||
|
||||
### Verifying
|
||||
|
||||
With `vainfo` installed in your image:
|
||||
|
||||
```
|
||||
docker exec metube vainfo --display drm --device /dev/dri/renderD128
|
||||
```
|
||||
|
||||
It should list the driver and a set of `VAProfile...` entries including
|
||||
`VAEntrypointEncSlice` for the codecs your GPU can encode. Also useful:
|
||||
|
||||
```
|
||||
docker exec metube ffmpeg -hide_banner -encoders | grep vaapi
|
||||
```
|
||||
|
||||
If ffmpeg fails with a permission error on `/dev/dri/renderD128`, the group in
|
||||
step 2 is wrong or wasn't applied — check with `docker exec metube id`.
|
||||
|
||||
### Other GPUs
|
||||
|
||||
The device passthrough and group setup in step 2 are the same for AMD; swap the
|
||||
driver package in step 1 for `mesa-va-drivers`. NVIDIA doesn't use VAAPI — it
|
||||
needs the NVIDIA Container Toolkit and NVENC encoder names (`hevc_nvenc`,
|
||||
`h264_nvenc`) instead.
|
||||
+1
@@ -10,6 +10,7 @@ Welcome to the MeTube wiki — the companion to the [README](https://github.com/
|
||||
|
||||
### Guides
|
||||
* [Subscriptions](Subscriptions) — auto-download new uploads from channels and playlists.
|
||||
* [Hardware-accelerated transcoding](Hardware-accelerated-transcoding) — re-encode downloads on an Intel/AMD GPU.
|
||||
* [Troubleshooting FAQ](Troubleshooting-FAQ) — common issues and how to diagnose them.
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user