Konwertowanie filmów na PeerTube'ie za pomocą kodeku H.265/HEVC

Jako iż H.265/HEVC ma relatywnie dobre wsparcie ze strony systemów operacyjnych jak i przeglądarek, zdecydowałem się na przekonwertowanie filmów na Kontrabandzie Play (pod której maską znajduje się właśnie PeerTube).

Do tej pory PeerTube oficjalnie wspiera jedynie kodek H.264 – i choć jest on w zasadzie powszechny, to problemem jest to, że przy 20+ materiałach, z czego kilka z nich jest powyżej 1,5h – to już przy trzech jakościach (1080p, 720p oraz 480p) sam materiał z przesłuchania Przemysława Kuny, który wtedy był kandydatem na prezesa UKE, zajmował łącznie prawie 4 GB (po konwersji na H.265/HEVC już tylko 1,9 GB – ponad 50% oszczędności), i jest to do tej pory jedyny materiał, który przekracza próg 1 GB użycia miejsca na dysku.

(Teraz wszystkie 20+ materiałów po transkodowaniu w sumie zajmuje niewiele ponad tyle, co sam materiał z ww. przesłuchania przed konwersją. Przedtem materiały miały łączny rozmiar ~11 GB po transkodowaniu.)

Zakładam, że w użyciu są tzw. zewnętrzne runnery – dzięki temu byłem w ogóle w stanie odkryć, jakie komendy wydaje PeerTube do oprogramowania ffmpeg, odpowiedzialnego za konwersję materiałów w taki sposób, żeby były one dostępne w wielu jakościach, i je odpowiednio podmienić.

Testowałem wszystko na systemie FreeBSD; na systemach typowo Linuxowych powinno to także działać, ale nie biorę odpowiedzialności za ewentualne awarie po czyjejkolwiek innej stronie.

A całość skupia się wokół stworzenia…

…prostego skryptu, który podmienia argumenty w taki sposób, żeby runner używał kodeku H.265/HEVC przy transkodowaniu filmów. Wygląda on następująco:

#!/usr/bin/env bash

args=("$@")
new_args=()

for ((i=0; i<${#args[@]}; i++)); do
  case "${args[i]}" in
    libx264)
      new_args+=("libx265") # podmieniamy libx264 na libx265
      ;;
    -bf|-b_strategy)
      ((i++)) # pozbywamy się tego
      ;;
    -x265-params)
      ((i++)) # i tego też
      ;;
    -preset)
      ((i++)) # i tego też
      ;;
    *)
      new_args+=("${args[i]}")
      ;;
  esac
done

# Jeżeli jesteś na FreeBSD – FFmpeg powinno być pod /usr/local/bin/ffmpeg
# Na Linuxie jest to z reguły pod /usr/bin/ffmpeg
exec /usr/local/bin/ffmpeg \
  "${new_args[@]}" \
  -tag:v hvc1 \
  -x265-params "bf=0"

Oczywiście skrypt ten testowałem (na FreeBSD oraz Fedorze Workstation 43) i jest on bezpieczny do uruchomienia. Najpewniej można też zamienić libx265 na zupełnie coś innego, dajmy na to VP9 czy nowsze AV1 – ale tego pod tym kątem nie testowałem i nie gwarantuję, że to zadziała. (Jeżeli się mylę, niech ktoś da znać – byłoby ciekawie.)

Zapisujemy w dowolnym miejscu, i następnie uruchamiamy runnera tą samą komendą, co zawsze (czyli peertube-runner server, ale musimy dodatkowo podać także zmienną środowiskową FFMPEG_PATH, żeby runner wiedział, do czego się odwoływać). Innymi słowy, za każdym razem, gdy uruchamiamy runnera, od tej pory komenda w terminalu powinna wyglądać tak:

$ FFMPEG_PATH=/pelna/sciezka/do/naszego/skryptu peertube-runner server

Et voila, od tej pory wystarczy wrzucić materiały (jeżeli jeszcze tego nie zrobiliśmy), lub wymusić ponowne transkodowanie już opublikowanych materiałów z poziomu panelu administracyjnego, wchodząc w zakładkę Overview → Videos → zaznaczamy filmy, które chcemy tak potraktować → Batch actions → Run HLS transcoding.

W zależności od wielkości filmów jak i ich ilości do przekonwertowania całość może potrwać od kilkunastu minut (jeżeli przechowujemy lekkie filmy) do nawet kilkunastu godzin (albo nawet kilku dni, jeżeli mamy naprawdę wiele materiałów na karku).

A, i byłbym zapomniał: w ten sposób kolejne filmy, które będą wraz z czasem publikowane, będą transkodowane z użyciem kodeku H.265/HEVC (a nie H.264) – o ile nie zapomnimy o dodaniu rzeczonego FFMPEG_PATH=/pelna/sciezka/do/naszego/skryptu przed właściwą komendą, gdy kiedykolwiek przyjdzie nam restartować runnera.