Die Mediatheken der Öffentlich-Rechtlichen haben ja immer wieder Perlen zu bieten. Leider aber häufig nur für sehr kurze Zeit, und nicht umbedingt dann, wenn ich als Nutzer auch Zeit habe diese zu konsumieren. Und auch so manches Endgerät, wie die PlayStation, harmonieren nicht so wunderbar mit den Mediatheken. Mit MediathekView und yt-dlp gibt es aber ja zum Glück hervorragende Möglichkeiten Medien zur zeit- und gerätesouveränen Nutzung auf einen lokalen DLNA-Server oder ein Plex zu sichern.
Das Problem
Ärgerlich ist hierbei, wenn Original- und synchronisierte Version in den Mediatheken als separate Videos angeboten werden. Denn das Video ist ja in allen Versionen dasselbe. Wird es für alle Sprachversionen separat gesichert, sorgt es für doppelte Downloadgröße und doppelten Speicherbedarf. Dabei würde eine zusätzliche Tonspur nur minimalen Platz verbrauchen.
Mehrsprachige Videos herunterladen
In der Mediathek des ZDF finden sich inzwischen auch Videos bei denen allen Sprachversionen parallel ausgeliefert werden.
Leider lassen sich diese nicht direkt über MediathekView herunterladen.
Aber mit yt-dlp ist dies möglich.
Der Magie besteht hierdrin in der Nutzung des Parameters --audio-multistream
und der korrekten Auswahl der Tonspuren.
Letzere lässt sich durch die Auswahl bestaudio
auch automatisieren, allerdings müssen alle Sprachen explizit angegeben werden, also beispielsweise bestaudio[language=de]+bestaudio[langauge=en]
.
Die Arbeit an ein Skript delegieren
Um die Sprachen nicht jedes mal von Hand auswählen zu müssen hilft ein kleine Shellscript welches zuerst per yt-dlp --dump-json
die Metadaten des Videos abfragt, aus diesen die Sprachen per jq extrahiert und daraus den passenden Parameter für yt-dlp baut.
#!/bin/bash
set -eu -o pipefail
echo "Lade ${1} als ${2}"
AUDIO=$(yt-dlp --dump-json "${1}" | jq -r '[[.formats[] | select(.vcodec == "none") | .language] | sort | unique[] | "+bestaudio[language=\(.)]"] | join("")')
yt-dlp --write-subs --sub-langs 'deu,eng,fra' --audio-multistreams --format "bestvideo${AUDIO}" --embed-metadata --merge-output-format 'mp4' --write-thumbnail --output "${2}.%(ext)s" "${1}"
Das Skript übernimmt die URL eines Videos als erster Parameter, und schreibt mehrsprachiges Video, Untertitel, und ein Titelbild in Dateien welche den zweiten Parameter als Namen nutzen.
Das erlaubt die Dateien direkt mit den passenden Namen für die Metadatenerkennung von Plex anzulegen.
Um also beispielsweise Sugar aus der ZDF-Mediathek für eine Wiedergabe an der PS5 per Plex herzunterzuladen würde das, als zdf_mt_dl.sh
abgelegte, Skript wie folgt aufgerufen:
zdf_mt_dl.sh 'https://www.zdf.de/filme/spielfilm-highlights/sugar-108.html' 'Sugar (2022)'
Das Skript erklärt
Das anfängliche set -eu -o pipefail
stellt sicher, dass das Skript abbricht wenn:
- ein Aufruf im Skript einen Fehler zurückgibt (
-e
), - und zwar auch, wenn wir das Ergebnis per Pipe weitergeben (
-o pipefail
). - Auch beim Zugriff auf eine undefinierte Variable bricht das Skript ab (
-u
).
yt-dlp --dump-json
holt die Metadaten von der übergebenen URL und gibt diese als JSON aus.
Diese verarbeiter der Aufruf von jq weiter.
Aus allen Formaten werden nur diese ausgewählt, bei welchen das Attribut vcoded
den Wert none
hat, also die reinen Audio-Stream.
Von diesen lesen wir das Attribut language
aus, sortieren diese, sortieren Duplicate aus, und setzen diese per \(.)
jeweils in die Zeichenkette "+bestaudio[language=\(.)]"
ein.
Wichtig ist hier, dass wir das ganze nochmal ein eckigen Klammern haben, damit bekommen wir nicht eine Zeichenkette pro Zeile im Output von jq, sondern bekommen das ganze immer noch als JSON-Array.
Damit können wir diese am Schluss noch per join("")
zusammenfassen und bekommen dann so etwas wie +bestaudio[language=de]+bestaudio[langauge=en]
welches wir dann anschließend über die Variable ${AUDIO}
in unseren Aufruf von yt-dlp setzen können.
Beim Aufruf von yt-dlp nutzt das Skript noch ein paar weitere Parameter:
--write-subs
holt, falls verfügbar, auch die Untertitel mit aus der Mediathek.--sublangs 'deu,eng,fra'
wählt die Sprachen aus die--write-subs
versuchen soll.--audio-multistreams
sorgt dafür, dass mehrere Tonspuren in der geschriebenen Datei landen dürfen. Sonst gäbe die Auswahl mehrerer Spuren einen Fehler.--format "bestvideo${AUDIO}"
wählt die Spuren aus. Wir wollen die beste Videospur, und zu jeder Sprache das beste Audio.${AUDIO}
wird hier mit der Spezifikation der Tonspuren ersetzt die wir zuvor zusammegebastelt haben.--embed-metadata
sorgt dafür, dass die Tonspuren auch schöne Namen haben.--merge-output-format
sorgt dafür, dass einemp4
statt einermkv
geschrieben wird. Das hat bei der Weitergabe an eine PlayStation den Vorteil, dass die PlayStation MP4-Dateien, anders als Matroska-Dateien direkt abspielen kann. So wird im Zweifel der Medienserver ein klein wenig entlastet.--write-thumbnail
sorgt dafür, dass das Titelbild zur Datei mitgesichert wird.--output "${2}.%(ext)s"
schließlich lässt yt-dlp unseren vorgegebenen Dateinamen übernehmen, aber für die einzelnen Dateien selbst die passende Endung auswählen. Ein deutscher Untertitel lautet beim oben genannten Beispiel also unterSugar (2022).deu.vtt
, das Video selbst unterSugar (2022).mp4
.