Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

Hinzufügen von Untertiteln und Beschriftungen zu HTML-Videos

In anderen Artikeln haben wir uns angesehen, wie man einen plattformübergreifenden Videoplayer entwickelt unter Verwendung der HTMLMediaElement und Window.fullScreen APIs, und wie man den Player stilisiert. In diesem Artikel verwenden wir denselben Player und zeigen, wie man Beschriftungen und Untertitel hinzufügt, unter Verwendung des WebVTT-Formats und des <track> Elements.

In diesem Artikel wird ein Ausschnitt aus dem Sintel Open Movie verwendet, erstellt von der Blender Foundation.

HTML und Videobeschriftungen

Bevor wir damit beginnen, wie man dem Videoplayer Beschriftungen hinzufügt, gibt es einige Dinge, die wir zuerst erwähnen werden und die Sie wissen sollten, bevor wir anfangen.

Beschriftungen versus Untertitel

Beschriftungen und Untertitel sind nicht dasselbe: Sie richten sich an verschiedene Zielgruppen und vermitteln unterschiedliche Informationen. Es wird empfohlen, sich über die Unterschiede zu informieren, wenn Sie sich nicht sicher sind, was diese sind. Sie werden jedoch technisch auf die gleiche Weise implementiert, daher gelten die Inhalte dieses Artikels für beide.

In diesem Artikel beziehen wir uns auf die angezeigten Textspuren als Untertitel, da ihr Inhalt für hörende Menschen gedacht ist, die Schwierigkeiten haben, die Sprache des Films zu verstehen, und nicht für gehörlose oder schwerhörige Menschen.

Das <track>-Element

HTML erlaubt es uns, Untertitel für ein Video mit dem <track> Element anzugeben. Die verschiedenen Attribute dieses Elements erlauben uns, Dinge wie den Typ des hinzugefügten Inhalts, die Sprache, in der er vorliegt, und natürlich eine Referenz zur Textdatei mit den tatsächlichen Untertiteldaten anzugeben.

WebVTT

Die Dateien, die die tatsächlichen Untertiteldaten enthalten, sind Textdateien, die einem vorgegebenen Format folgen, in diesem Fall das Web Video Text Tracks (WebVTT)-Format.

Videoanbieter (wie die Blender Foundation) liefern Beschriftungen und Untertitel in einem Textformat mit ihren Videos, meistens im SubRip Text (SRT)-Format. Diese können leicht mit einem Online-Konverter in WebVTT konvertiert werden.

Änderungen an HTML und CSS

Dieser Abschnitt fasst die Änderungen am Code des vorherigen Artikels zusammen, um die Hinzufügung von Untertiteln zum Video zu erleichtern. Wenn Sie daran nicht interessiert sind und direkt zu JavaScript und wichtigen CSS-Elementen gehen möchten, springen Sie zum Abschnitt Untertitel-Implementierung.

In diesem Beispiel verwenden wir ein anderes Video, Sintel, da es tatsächlich einige Sprache enthält und daher besser zur Veranschaulichung der Funktionsweise von Untertiteln geeignet ist!

HTML-Markup

Wie oben erwähnt, müssen wir das neue HTML <track>-Element verwenden, um unsere Untertiteldateien zum HTML-Video hinzuzufügen. Wir haben unsere Untertitel tatsächlich in drei verschiedenen Sprachen - Englisch, Deutsch und Spanisch - daher werden wir alle drei relevanten VTT-Dateien referenzieren, indem wir <track>-Elemente innerhalb unseres HTML <video>-Elements hinzufügen:

html
<video id="video" controls preload="metadata">
  <source src="/shared-assets/videos/sintel-short.mp4" type="video/mp4" />
  <source src="/shared-assets/videos/sintel-short.webm" type="video/webm" />
  <track
    label="English"
    kind="subtitles"
    srclang="en"
    src="/shared-assets/misc/sintel-en.vtt"
    default />
  <track
    label="Deutsch"
    kind="subtitles"
    srclang="de"
    src="/shared-assets/misc/sintel-de.vtt" />
  <track
    label="Español"
    kind="subtitles"
    srclang="es"
    src="/shared-assets/misc/sintel-es.vtt" />
</video>

Wie Sie sehen können, hat jedes <track>-Element die folgenden Attribute gesetzt:

  • kind ist auf subtitles gesetzt, was den Typ des Inhalts beschreibt, den die Dateien enthalten.
  • label hat einen Wert, der angibt, für welche Sprache dieses Untertitelset gedacht ist - zum Beispiel English oder Deutsch - diese Beschriftungen erscheinen in der Benutzeroberfläche, um dem Benutzer die einfache Auswahl der gewünschten Untertitelsprache zu ermöglichen.
  • src ist mit einer gültigen URL versehen, die auf die jeweilige WebVTT-Untertiteldatei verweist.
  • srclang gibt an, in welcher Sprache der Inhalt jeder Untertiteldatei geschrieben ist.
  • Das default-Attribut ist auf dem englischen <track>-Element gesetzt, was dem Browser anzeigt, dass dies die Standarddefinition für Untertitel ist, die verwendet werden soll, wenn Untertitel aktiviert sind und der Benutzer keine spezifische Auswahl getroffen hat.

Zusätzlich zum Hinzufügen der <track>-Elemente haben wir auch einen neuen Button hinzugefügt, um das Untertitelmenü zu steuern, das wir erstellen werden. Infolgedessen sehen die Videosteuerungen jetzt wie folgt aus:

html
<div id="video-controls" class="controls" data-state="hidden">
  <button id="play-pause" type="button" data-state="play">Play/Pause</button>
  <button id="stop" type="button" data-state="stop">Stop</button>
  <div class="progress">
    <progress id="progress" value="0">
      <span id="progress-bar"></span>
    </progress>
  </div>
  <button id="mute" type="button" data-state="mute">Mute/Unmute</button>
  <button id="vol-inc" type="button" data-state="vol-up">Vol+</button>
  <button id="vol-dec" type="button" data-state="vol-down">Vol-</button>
  <button id="fs" type="button" data-state="go-fullscreen">Fullscreen</button>
  <button id="subtitles" type="button" data-state="subtitles">
    <span>CC</span>
  </button>
</div>

CSS-Änderungen

Es gibt fast keine Änderung am CSS im Vergleich zur vorherigen Version, außer an einer Stelle, an der wir width: calc(100% / 6) durch width: calc(100% / 7) ersetzen, um Platz für den neuen Button zu schaffen. Wir setzen auch position: relative auf die Figur, damit das Untertitelmenü relativ dazu positioniert werden kann.

Für die Beschriftungsschaltfläche wird kein Bild verwendet, daher wird sie so gestylt:

css
.controls button[data-state="subtitles"] {
  padding: 2px;
}
.controls button[data-state="subtitles"] span {
  max-width: 100%;
  width: 2rem;
  height: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  font-weight: bold;
  color: #666666;
  background-color: black;
  border-radius: 4px;
}

Es gibt auch andere CSS-Änderungen, die spezifisch für einige zusätzliche JavaScript-Implementierungen sind, aber diese werden an der entsprechenden Stelle unten erwähnt.

Untertitel-Implementierung

Vieles, was wir tun, um auf die Videountertitel zuzugreifen, dreht sich um JavaScript. Ähnlich wie bei den Videosteuerungen gibt es, wenn ein Browser HTML-Videountertitel unterstützt, einen Button innerhalb des nativen Steuerungssatzes, um darauf zuzugreifen. Da wir jedoch unsere eigenen Videosteuerungen definiert haben, ist dieser Button versteckt, und wir müssen unsere eigenen definieren.

Browser unterscheiden sich darin, was sie unterstützen, daher werden wir versuchen, eine einheitlichere Benutzeroberfläche für jeden Browser zu schaffen, wo immer möglich. Mehr zu Problemen mit der Browser-Kompatibilität weiter unten.

Initiales Setup

Wie bei allen anderen Schaltflächen müssen wir eine der ersten Dinge tun, und zwar einen Zugriff auf die Untertitel-Schaltfläche speichern:

js
const subtitles = document.getElementById("subtitles");

Wir schalten auch zunächst alle Untertitel aus, falls der Browser einige davon standardmäßig einschaltet:

js
for (const track of video.textTracks) {
  track.mode = "hidden";
}

Die Eigenschaft video.textTracks enthält ein Array aller Textspuren, die dem Video angehängt sind. Wir durchlaufen jede von ihnen und setzen ihren mode auf hidden.

Hinweis: Die WebVTT API gibt uns Zugriff auf alle Textspuren, die für ein HTML-Video mit dem <track>-Element definiert sind.

Erstellen eines Beschriftungsmenüs

Unser Ziel ist es, die zuvor hinzugefügte subtitles-Schaltfläche zu nutzen, um ein Menü anzuzeigen, das es den Benutzern ermöglicht, auszuwählen, in welcher Sprache die Untertitel angezeigt werden sollen, oder sie vollständig auszuschalten.

Wir haben die Schaltfläche hinzugefügt, aber bevor wir sie funktionsfähig machen, müssen wir das damit verbundene Menü erstellen. Dieses Menü wird dynamisch erstellt, sodass Sprachen später hinzugefügt oder entfernt werden können, indem die <track>-Elemente im Markup des Videos bearbeitet werden.

Alles, was wir tun müssen, ist, die textTracks des Videos durchzugehen, ihre Eigenschaften auszulesen und das Menü entsprechend aufzubauen:

js
const subtitleMenuButtons = [];
let subtitlesMenu;
if (video.textTracks) {
  const df = document.createDocumentFragment();
  subtitlesMenu = df.appendChild(document.createElement("ul"));
  subtitlesMenu.className = "subtitles-menu";
  subtitlesMenu.appendChild(createMenuItem("subtitles-off", "", "Off"));
  for (const track of video.textTracks) {
    subtitlesMenu.appendChild(
      createMenuItem(
        `subtitles-${track.language}`,
        track.language,
        track.label,
      ),
    );
  }
  videoContainer.appendChild(subtitlesMenu);
}

Dieser Code erstellt ein documentFragment, das verwendet wird, um eine ungeordnete Liste zu halten, die unser Untertitelmenü enthält. Zunächst wird eine Option hinzugefügt, um alle Untertitel auszuschalten, und dann werden Schaltflächen für jede Textspur hinzugefügt, wobei die Sprache und das Label von jedem ausgelesen werden.

Das Erstellen jedes Listenpunkts und der Schaltfläche erfolgt durch die createMenuItem() Funktion, die wie folgt definiert ist:

js
function createMenuItem(id, lang, label) {
  const listItem = document.createElement("li");
  const button = listItem.appendChild(document.createElement("button"));
  button.setAttribute("id", id);
  button.className = "subtitles-button";
  if (lang.length > 0) button.setAttribute("lang", lang);
  button.value = label;
  button.setAttribute("data-state", "inactive");
  button.appendChild(document.createTextNode(label));
  button.addEventListener("click", (e) => {
    // Set all buttons to inactive
    subtitleMenuButtons.forEach((button) => {
      button.setAttribute("data-state", "inactive");
    });

    // Find the language to activate
    const lang = button.getAttribute("lang");
    for (const track of video.textTracks) {
      // For the 'subtitles-off' button, the first condition will never match so all will subtitles be turned off
      if (track.language === lang) {
        track.mode = "showing";
        button.setAttribute("data-state", "active");
      } else {
        track.mode = "hidden";
      }
    }
    subtitlesMenu.style.display = "none";
  });
  subtitleMenuButtons.push(button);
  return listItem;
}

Diese Funktion erstellt die erforderlichen <li> und <button> Elemente und gibt sie zurück, damit sie zur Untertitelliste hinzugefügt werden können. Sie richtet auch die erforderlichen Event-Listener auf der Schaltfläche ein, um die betreffende Untertitelgruppe ein- oder auszuschalten. Dies geschieht durch Setzen des mode-Attributs der erforderlichen Untertitel auf showing und der anderen auf hidden.

Sobald das Menü erstellt ist, wird es dann am unteren Ende des videoContainer in den DOM eingefügt.

Anfänglich ist das Menü standardmäßig verborgen, daher muss ein Event-Listener auf unsere Untertitelschaltfläche hinzugefügt werden, um es umzuschalten:

js
subtitles.addEventListener("click", (e) => {
  if (subtitlesMenu) {
    subtitlesMenu.style.display =
      subtitlesMenu.style.display === "block" ? "none" : "block";
  }
});

CSS des Untertitelmenüs

Wir haben auch einige grundlegende Stile für das neu erstellte Untertitelmenü hinzugefügt:

css
.subtitles-menu {
  display: none;
  position: absolute;
  bottom: 3rem;
  right: 0;
  background: #666666;
  list-style-type: none;
  margin: 0;
  width: 100px;
  padding: 10px;
}

.subtitles-menu li {
  padding: 0;
  text-align: center;
}

.subtitles-menu li button {
  border: none;
  background: black;
  color: white;
  cursor: pointer;
  width: 90%;
  padding: 2px 5px;
  border-radius: 2px;
}

Styling der angezeigten Untertitel

Eine der weniger bekannten und unterstützten Funktionen von WebVTT ist die Möglichkeit, die einzelnen Untertitel (sogenannte Textcues) über CSS zu gestalten.

Das ::cue Pseudo-Element ist der Schlüssel, um einzelne Text-Track-Cues für das Styling zu bestimmen, da es auf jeden definierten Cue passt. Es gibt nur eine Handvoll CSS-Eigenschaften, die auf einen Textcue angewendet werden können:

Beispielsweise können Sie die Textfarbe der Text-Track-Cues ändern, indem Sie Folgendes schreiben:

css
::cue {
  color: #cccccc;
}

Wenn die WebVTT-Datei voice spans verwendet, die es ermöglichen, Cues als eine bestimmte "Stimme" zu definieren:

0
00:00:00.000 --> 00:00:12.000
<v Test>[Test]</v>

Dann kann diese bestimmte 'Stimme' wie folgt gestylt werden:

css
::cue(v[voice="Test"]) {
  color: white;
  background: #0095dd;
}

Ergebnis