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 zu HTML-Videos

In anderen Artikeln haben wir uns angesehen, wie man einen plattformübergreifenden Videoplayer erstellt mithilfe der HTMLMediaElement und Window.fullScreen APIs, sowie wie man den Player gestaltet. Dieser Artikel nimmt denselben Player und zeigt, wie man Untertitel und Übersetzungen hinzufügt, unter Verwendung des WebVTT-Formats und des <track> Elements.

In diesem Artikel verwendet unser Beispiel einen Ausschnitt aus dem Sintel Open Movie, erstellt von der Blender Foundation.

HTML und Video-Untertitel

Bevor wir darauf eingehen, wie Sie Ihrem Videoplayer Untertitel hinzufügen, gibt es einige Dinge, die wir zunächst erwähnen müssen, die Sie wissen sollten, bevor wir beginnen.

Untertitel und Übersetzungen

Untertitel und Übersetzungen sind nicht dasselbe: Sie haben unterschiedlich signifikante Zielgruppen und vermitteln verschiedene Informationen. Es wird empfohlen, sich über die Unterschiede zu informieren, wenn Sie sich nicht sicher sind, was sie sind. Sie werden jedoch technisch auf die gleiche Weise implementiert, sodass das Material in diesem Artikel für beide gilt.

Für diesen Artikel werden wir uns auf die angezeigten Textspuren als Übersetzungen beziehen, 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 Personen.

Das <track> Element

HTML erlaubt es uns, mithilfe des <track> Elements Übersetzungen für ein Video anzugeben. Die verschiedenen Attribute dieses Elements ermöglichen es uns, Dinge wie die Art des Inhalts, den wir hinzufügen, die Sprache, in der er geschrieben ist, und natürlich einen Verweis auf die Textdatei, die die tatsächlichen Untertitel-Informationen enthält, anzugeben.

WebVTT

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

Videodienste (wie die Blender Foundation) stellen Untertitel und Übersetzungen in einem Textformat mit ihren Videos bereit, aber sie sind normalerweise 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 zusammen, die am Code des vorherigen Artikels vorgenommen wurden, um die Hinzufügung von Untertiteln zum Video zu erleichtern. Wenn Sie daran nicht interessiert sind und direkt zu JavaScript und dem relevanteren CSS übergehen möchten, springen Sie zum Abschnitt Implementierung der Untertitel.

In diesem Beispiel verwenden wir ein anderes Video, Sintel, da es tatsächlich einige Sprache enthält und daher besser veranschaulicht, wie Untertitel funktionieren!

HTML Markup

Wie oben erwähnt, müssen wir das neue HTML <track> Element nutzen, um unsere Untertiteldateien zum HTML-Video hinzuzufügen. Wir haben unsere Untertitel tatsächlich in drei verschiedenen Sprachen — Englisch, Deutsch und Spanisch — also 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 hat den Wert subtitles, was die Art des Inhalts angibt, den die Dateien enthalten.
  • label hat einen Wert, der angibt, für welche Sprache dieser Untertitelsatz ist — zum Beispiel English oder Deutsch — diese Labels erscheinen in der Benutzeroberfläche, damit der Benutzer leicht auswählen kann, welche Untertitelsprache er sehen möchte.
  • src ist eine gültige URL, die auf die jeweilige WebVTT-Untertiteldatei verweist.
  • srclang gibt an, in welcher Sprache der Inhalt jeder Untertiteldatei ist.
  • Das default Attribut ist auf dem englischen <track> Element gesetzt, wodurch dem Browser mitgeteilt wird, dass dies die Standard-Untertiteldatei ist, die verwendet werden soll, wenn die Untertitel aktiviert sind und der Benutzer keine spezielle Auswahl getroffen hat.

Neben dem Hinzufügen der <track> Elemente haben wir auch eine neue Schaltfläche 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" min="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 gegenüber der vorherigen Version, außer an einer Stelle, an der width: calc(100% / 6) durch width: calc(100% / 7) ersetzt wurde, um die neue Schaltfläche einzubeziehen. Wir setzen auch position: relative auf die Figure, damit das Untertitelmenü-Popup relativ dazu positioniert werden kann.

Es wird kein Bild für die Untertitel-Schaltfläche verwendet, daher wird es wie folgt gestaltet:

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.

Implementierung der Untertitel

Vieles von dem, was wir tun, um auf die Video-Untertitel zuzugreifen, dreht sich um JavaScript. Ähnlich wie bei den Videosteuerungen gibt es, wenn ein Browser HTML-Video-Untertitel unterstützt, eine Schaltfläche innerhalb des nativen Steuerungssatzes, um darauf zuzugreifen. Da wir jedoch unsere eigenen Videosteuerungen definiert haben, ist diese Schaltfläche versteckt, und wir müssen unsere eigene 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 dies möglich ist. Mehr zu den Fragen der Browser-Kompatibilität weiter unten.

Erste Einrichtung

Wie bei allen anderen Schaltflächen ist eine der ersten Dinge, die wir tun müssen, einen Bezug zur Untertitel-Schaltfläche zu speichern:

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

Außerdem schalten wir alle Untertitel zunächst aus, falls der Browser einige von ihnen standardmäßig einschaltet:

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

Die Eigenschaft video.textTracks enthält ein Array von allen an das Video angehängten Textspuren. Wir durchlaufen jede einzelne 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.

Aufbau eines Untertitelmenüs

Unser Ziel ist es, die zuvor hinzugefügte subtitles Schaltfläche zu verwenden, um ein Menü anzuzeigen, in dem Benutzer auswählen können, in welcher Sprache die Untertitel angezeigt werden sollen, oder sie ganz auszuschalten.

Wir haben die Schaltfläche hinzugefügt, aber bevor wir sie etwas tun lassen, müssen wir das zugehörige Menü erstellen. Dieses Menü wird dynamisch erstellt, sodass später Sprachen durch Bearbeiten der <track> Elemente im Video-Markup hinzugefügt oder entfernt werden können.

Alles, was wir tun müssen, ist durch die textTracks des Videos zu gehen, ihre Eigenschaften zu lesen und das Menü daraus zu erstellen:

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, die es dem Benutzer ermöglicht, alle Untertitel auszuschalten, und dann werden Schaltflächen für jede Textspur hinzugefügt, wobei die Sprache und das Label von jeder gelesen wird.

Die Erstellung jedes Listenelements und jeder 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 der Untertitelmenüliste hinzugefügt werden können. Sie setzt auch die erforderlichen Ereignis-Listener auf der Schaltfläche, um den betreffenden Untertitelsatz ein- oder auszuschalten. Dies geschieht, indem das erforderliche mode Attribut der Untertitel auf showing gesetzt wird, und die anderen auf hidden gesetzt werden.

Sobald das Menü erstellt ist, wird es unten im videoContainer in das DOM eingefügt.

Das Menü ist anfänglich standardmäßig verborgen, sodass ein Ereignis-Listener zu unserer Untertitel-Schaltfläche hinzugefügt werden muss, um sie umzuschalten:

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

CSS für das Untertitelmenü

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 Fähigkeit, die einzelnen Untertitel zu stylen (etwas, das als Text-Cues bezeichnet wird) über CSS.

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

Zum Beispiel, um die Textfarbe der Texttrack-Cues zu ändern, können Sie Folgendes schreiben:

css
::cue {
  color: #cccccc;
}

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

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

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

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

Ergebnis