Vor kurzem hatte Kollege Phillip Roth diese spannende Frage für mich auf Twitter. Und zusammen mit Walter Ebert haben wir gefachsimpelt, wie das zu lösen ist. Im Prinzip ist das möglich, aber hängt von diversen Faktoren ab. Wie wird das Video im Browser abgespielt? Via MediaElementJS oder nativ? Wie setzen wir das um, wenn mehrere Untertitel existieren? Oder mehrere Video mit unterschiedlichen Sprachen? Hier eine Zusammenfassung meiner bisherigen Recherche und ein Ticket für den Block-Editor. Wie so oft … 😉
Starten wir mit der Ausgangssituation: Es geht um ein direkt in der Mediathek hochgeladenes Video (nicht über YouTube, Vimeo oder einen anderen externen Anbieter). Dann gibt es im Video-Block des Block-Editors die Möglichkeit beim Einbau eine Untertitel-Datei -aktuell nur im VTT-Format– hochzuladen und so das Video mit Untertiteln zu bestücken.
Das Problem ist nun folgendes: Beim Aufruf der Webseite mit dem Video ist der Untertitel nicht aktiv. Er muss erst manuell ausgewählt werden. Doch es gibt unzählige Gründe, warum Untertitel standardmäßig an sein sollten und Ton problematisch ist. Großraumbüros, fehlende Kopfhörer und standardmäßig stummgeschaltete Browser sind nur ein paar davon.
Im Zuge der Barrierefreiheit wollen wir nun also die Untertitel standardmäßig aktivieren. Also los!
Unsere erste Idee war die in WordPress verwendete Javascript-Lösung MediaElementJS. Sofern diese das Video abspielt, gibt es ja einen Filter, den wir benutzen können. Mit mejs_settings
können die Einstellungen über die mediaElement.js-API angepasst werden:
<?php
function my_mejs_settings( $settings ) {
$settings['startLanguage'] = 'de';
return $settings;
}
add_filter( 'mejs_settings', 'my_mejs_settings' );
Doch das führte nicht zum erwünschten Ergebnis. Ein Blick in den Quelltext offenbarte dann die Erklärung. Der Browser konnte das Video nativ abspielen, ohne MediaElement.js zu benötigen. Daher war nur das video
Element im Einsatz. Hier ein beispielhaftes Markup:
<video id="video" controls preload="metadata">
<source src="video/sintel-short.mp4" type="video/mp4">
<source src="video/sintel-short.webm" type="video/webm">
<track label="English" kind="subtitles" srclang="en" src="captions/vtt/sintel-en.vtt" default>
<track label="Deutsch" kind="subtitles" srclang="de" src="captions/vtt/sintel-de.vtt">
<track label="Español" kind="subtitles" srclang="es" src="captions/vtt/sintel-es.vtt">
</video>
Also brauchten wir einen neuen Ansatz. Das Video-Element bietet dazu eigentlich schon eine einfache Lösung. Durch ein zusätzliches default
kann eines der Tracks (also Untertitel) als Standard ausgewählt werden. Leider gibt es im User Interface keine Möglichkeit dies auszuwählen, also habe ich dazu ein Issue beim Block-Editor eröffnet.
Bleibt uns wohl nichts anderes übrig, als selbst tätig zu werden. Wenn wir an das Markup nicht so einfach herankommen, dann müssen wir mit Javascript den Status im Nachgang ändern.
Damit wir das Video ansprechen können, benötigt es eine ID, zum Beispiel videox
und dann schalten wir den ersten Track (Zählung startet bei Null) einfach an:
videox.textTracks[0].mode = 'showing';
Oder auch aus:
videox.textTracks[0].mode = 'hidden';
Da gibt es jetzt nur ein Problem. WordPress gibt uns keine Möglichkeit eine ID an dem Video zu setzen. Unter dem Punkt „HTML-Anker“ im Reiter „Erweitert“ in der Sidebar des Block-Editors können wir zwar eine ID setzen …
… aber die hängt an dem Wrapper:
<figure id="videox" class="wp-block-video">
Also müssen wir unser Javascript anpassen. Mit dem querySelector bekommen wir das erste Element zurück, welches auf den Selektor passt und die Zählung der Tracks startet, wie oben schon erwähnt bei Null. Unser Skript sieht nun also so aus:
videox.querySelector('video').textTracks[0].mode = 'showing';
Die Alternative das default-Attribut im Nachgang via Javascript zu ergänzen funktioniert zwar, hat aber nicht den gewünschten Effekt.
videox.querySelector('track').setAttribute("default", "true");
Der Code sorgt zwar dafür, dass das Attribut gesetzt wird, aber die Anzeige ändert sich nicht mehr, da das Video ja bereits geladen wurde.
Aber wir haben ja eine funktionierende Lösung, zumindest für den Fall, dass nur ein Video mit einer Untertitelspur existiert. Die können wir jetzt in den Footer laden (im Head ist das Video ja noch nicht da):
// Add subtitle enabler in footer.
function enable_subtitles() {
?>
<script>
var myVideo = document.getElementById('videox');
if ( myVideo ) {
myVideo.querySelector('video').textTracks[0].mode = 'showing';
}
</script>
<?php
}
add_action( 'wp_footer', 'enable_subtitles' );
Damit auf allen Webseiten ohne unsere ID kein Fehler auftritt, führen wir das Skript nur aus, wenn die ID auch auf der Seite vorhanden ist.
Das Skript kann natürlich auch direkt in die footer.php
eingebaut werden. In einem Child-Theme oder wenn du dein Theme selbst gebaut hast. Alternativ kann es auch in eine JS-Datei eingebaut und sauber eingereiht werden via wp_enqueue_script.
Interessant wird es dann, wenn mehrere Untertitel-Sprachen angeboten werden müssen, die ganze Website mehrsprachig ist und Redakteure nicht immer die gleiche Reihenfolge benutzen. Dann müsste der Code etwas komplexer aussehen und erst einmal alle vorhanden Sprachen durchgehen, ggf. die Sprache der aktuellen Website auswählen und diese dann aktivieren.
Falls mehrere Video auf einer Webseite existieren, dann ist die Lösung recht einfach. Dann muss querySelector einfach zu querySelectorAll geändert werden und wir müssen zum Beispiel mit einer for/each-Schleife einmal durch alle Videos gehen und den Code ausführen.
Aber für den einfachen Use Case haben wir jetzt eine Lösung. Ein Ticket beim Block Editor hilft uns in der Zukunft vielleicht etwas einfacher ans Ziel zu kommen und wer das Skript erweitern möchte, der hat auch schon mögliche Ideen skizziert bekommen.
Falls ihr die Lösung weiter baut oder Verbesserungsvorschläge (oder Kritik) habt, dann ab damit in die Kommentare!
Update:
Es scheint auch noch einen weiteren Weg über setTrack
zu geben:
https://stackoverflow.com/questions/22424980/mediaelement-js-default-video-captions-to-on