CLI-Workflow für Untertitel: erzeugen, wandeln, einbrennen
Übergeben Sie dem folgenden Skript ein Verzeichnis mit MP4-Videos mit englischer Sprache. Es erzeugt SRT-Untertitel mit Zeitstempeln, eine WebVTT-Kopie, eine MKV-Datei mit separater Untertitelspur und eine MP4-Datei mit Untertiteln, die in die Videobilder eingebrannt sind. Whisper.cpp übernimmt die Transkription auf der CPU; FFmpeg konvertiert die Untertitel und erzeugt die Videoausgaben. Betrachten Sie die Ergebnisse als Entwürfe, die Sie vor der Veröffentlichung prüfen sollten.
Wählbare oder eingebrannte Untertitel wählen
| Wählbare Untertitelspur | Eingebrannte Untertitel | |
|---|---|---|
| Abschaltbar | Ja, in einem Player, der die Spur unterstützt | Nein |
| Text ändern | Spur ersetzen, ohne das Video zu codieren | Neues Video codieren |
| Videoverarbeitung | Vorhandenen Videostream kopieren | Text rendern und neue Frames codieren |
| Wiedergabe erfordert | Unterstützung für Container und Untertitel | Unterstützung für den Video-Codec der Ausgabe |
Nutzen Sie die MKV-Datei für eine wählbare Spur und die MP4-Datei mit eingebrannten Untertiteln, wenn der Text ohne Untertitelschalter sichtbar bleiben muss. Keine der beiden Optionen garantiert, dass jeder Player das resultierende Video unterstützt. Die Dateigröße hängt von der Quelle und den Encoding-Einstellungen ab; eingebrannter Text vergrößert die Datei nicht immer.
Tools zur CPU-Transkription installieren
Verwenden Sie ein Linux-System mit Bash und der Berechtigung, Pakete zu installieren. Diese Befehle
sind für Ubuntu 24.04 vorgesehen und nutzen die Version v1.9.4 von
Whisper.cpp. Das rein englische Modell tiny.en hält dieses Beispiel klein;
es garantiert keine Genauigkeit. Für die Installation und den Modelldownload benötigen Sie
Internetzugang. Danach läuft die Transkription lokal.
Installieren Sie FFmpeg, einen C++-Compiler, CMake und eine Schriftart zum Rendern:
(
sudo apt-get update &&
sudo apt-get install -y build-essential cmake curl ca-certificates tar ffmpeg fonts-liberation
)
Erstellen Sie subtitle-tools in einem Arbeitsverzeichnis mit Schreibberechtigung.
Die Subshell lässt Ihr aktuelles Verzeichnis und Ihre Shell-Optionen unverändert. Falls das
Verzeichnis bereits existiert, bricht die Einrichtung ab, bevor darin etwas installiert oder
geschrieben wird. Wählen Sie dann ein anderes Arbeitsverzeichnis, statt bestehende Arbeit zu löschen.
(
mkdir subtitle-tools &&
cd subtitle-tools &&
curl -fsSLo whisper.tar.gz https://github.com/ggml-org/whisper.cpp/archive/refs/tags/v1.9.4.tar.gz &&
mkdir source &&
tar -xzf whisper.tar.gz -C source --strip-components=1 &&
cmake -S source -B build -DCMAKE_BUILD_TYPE=Release \
-DGGML_CUDA=OFF -DGGML_VULKAN=OFF -DGGML_NATIVE=OFF \
-DBUILD_SHARED_LIBS=OFF -DWHISPER_BUILD_TESTS=OFF &&
cmake --build build --target whisper-cli -j2 &&
curl -fsSLo ggml-tiny.en.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.en.bin &&
printf '%s %s\n' \
921e4cf8686fdd993dcd081a5da5b6c365bfde1162e72b08d75ac75289920b1f \
ggml-tiny.en.bin | sha256sum -c -
)
Dabei kommt der Workflow für CMake-Builds und Audiovorbereitung von Whisper.cpp zum Einsatz. Dessen CLI akzeptiert Mono-PCM-WAV mit 16 kHz und 16 Bit, das das Skript aus jedem Video extrahiert. Andere Whisper-Wrapper, darunter SubsAI, haben eine eigene Befehlssyntax; sie werden hier nicht benötigt.
Um den Workflow ohne eigene Aufnahme auszuprobieren, erstellen Sie ein Video aus der mitgelieferten JFK-Sprachaufnahme dieser Version. Führen Sie dies im selben Arbeitsverzeichnis wie die Einrichtung aus:
(
mkdir demo-videos &&
ffmpeg -nostdin -n -v error -f lavfi -i color=c=black:s=640x360:r=24 \
-i ./subtitle-tools/source/samples/jfk.wav \
-map 0:v:0 -map 1:a:0 -c:v libx264 -threads 2 -c:a aac -shortest \
./demo-videos/example.mp4
)
Alles mit einem Shell-Skript automatisieren
Speichern Sie Folgendes als subtitle-tools/subtitles.sh. Das Skript verarbeitet nur reguläre
Dateien auf der obersten Verzeichnisebene mit dem kleingeschriebenen Suffix
.mp4 und überspringt symbolische Links. Jede Eingabe erhält ein neues
Verzeichnis direkt daneben, etwa example.mp4.subtitles. Leerzeichen, Anführungszeichen
und führende Bindestriche in Dateinamen werden unterstützt; Pfade mit Zeilenumbruchzeichen werden
abgelehnt. Führen Sie immer nur einen Stapellauf gleichzeitig aus.
Die festen Dateinamen in jedem Ergebnisverzeichnis halten den ursprünglichen Pfad aus der separaten Filtersyntax von FFmpeg heraus. Das Skript bewahrt eine Kopie der Quelle und eine PCM-Audiodatei auf. Planen Sie dafür sowie für beide Videoausgaben genügend Speicherplatz ein.
#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
fail() { printf '%s\n' "$*" >&2; exit 1; }
[[ $# -eq 1 ]] || fail 'Usage: bash subtitles.sh VIDEO_DIRECTORY'
[[ $PWD != *$'\n'* && $1 != *$'\n'* && ${BASH_SOURCE[0]} != *$'\n'* ]] ||
fail 'Newline characters in paths are not supported'
input_directory=$1
[[ $input_directory == /* ]] || input_directory=$PWD/$input_directory
case ${BASH_SOURCE[0]} in
*/*) tool_directory=${BASH_SOURCE[0]%/*} ;;
*) tool_directory=. ;;
esac
cd -P -- "$tool_directory"
tool_directory=$PWD
[[ $tool_directory != *$'\n'* ]] || fail 'Newline characters in paths are not supported'
whisper=$tool_directory/build/bin/whisper-cli
model=$tool_directory/ggml-tiny.en.bin
[[ -x $whisper && -s $model ]] || fail 'Complete the subtitle-tools setup first'
cd -P -- "$input_directory"
[[ $PWD != *$'\n'* ]] || fail 'Newline characters in paths are not supported'
shopt -s nullglob
process_video() (
local video=$1
local output=$video.subtitles
mkdir -- "$output"
cp -- "$video" "$output/source.mp4"
cd -- "$output"
ffmpeg -nostdin -n -v error -xerror -i source.mp4 -map 0:a:0 \
-ar 16000 -ac 1 -c:a pcm_s16le audio.wav
"$whisper" --no-gpu -t 2 -p 1 -l en -m "$model" -f audio.wav -osrt -of captions
[[ -s captions.srt ]] || fail 'No subtitle file was produced'
grep -q -- '-->' captions.srt || fail 'No timed captions were produced; check for speech'
ffmpeg -nostdin -n -v error -i captions.srt -map 0:s:0 -c:s webvtt captions.vtt
ffmpeg -nostdin -n -v error -i source.mp4 -i captions.srt \
-map 0:v:0 -map 0:a:0 -map 1:s:0 -c copy -metadata:s:s:0 language=eng soft.mkv
ffmpeg -nostdin -n -v error -xerror -i source.mp4 \
-vf "subtitles=captions.srt:force_style='Fontname=Liberation Sans,FontSize=24'" \
-map 0:v:0 -map 0:a:0 -c:v libx264 -threads 2 -crf 20 -preset veryfast \
-c:a copy burned.mp4
)
count=0
current_video='setup'
trap 'status=$?; if [[ $status -ne 0 ]]; then printf "Failed while processing: %s\n" "$current_video" >&2; fi' EXIT
for video in "$PWD"/*.mp4; do
[[ -f $video && ! -L $video ]] || continue
[[ $video != *$'\n'* ]] || fail 'Newline characters in paths are not supported'
current_video=$video
printf 'Processing: %s\n' "$video"
process_video "$video"
count=$((count + 1))
printf 'Created: %s.subtitles\n' "$video"
done
[[ $count -gt 0 ]] || fail 'No regular .mp4 files found'
Führen Sie es im Arbeitsverzeichnis aus, in dem Sie die Tools installiert haben. Dieses unterscheidet sich vom Eingabeverzeichnis:
bash ./subtitle-tools/subtitles.sh ./demo-videos
Ersetzen Sie ./demo-videos durch Ihr Aufnahmeverzeichnis. Das Skript löst dieses
Verzeichnis auf, bevor es Dateien auswählt; es verarbeitet keine MP4-Dateien aus dem Verzeichnis,
von dem aus Sie es aufrufen. Sie können auch für das gespeicherte Skript und das Eingabeverzeichnis
absolute Pfade angeben.
Ein leeres Verzeichnis führt zu einem Fehler. Ein Video ohne Audiostream, ein Fehler beim Decodieren oder eine fehlgeschlagene spätere Konvertierung stoppt den Stapellauf und nennt die aktuelle Eingabedatei. Ein Fehler kann unvollständige Dateien im zugehörigen Ergebnisverzeichnis hinterlassen. Bestehende Ergebnisverzeichnisse führen zu einem Fehler, bevor der betreffende Clip kopiert oder transkribiert wird. So bleiben frühere Ausgaben bei wiederholten Läufen erhalten. Dieses Skript kann abgebrochene Läufe nicht fortsetzen: Um einen korrigierten Clip erneut zu verarbeiten, legen Sie ihn in ein separates Verzeichnis ohne bestehende Ergebnisse.
Stilles Audio ist nicht dasselbe wie ein fehlender Audiostream. Das Modell kann entweder keine
Untertitelsegmente zurückgeben oder Kennzeichnungen für nichtsprachliche Geräusche oder erfundenen
Text liefern. Zum Beispiel kann tiny.en ein Untertitelsegment mit
[BLANK_AUDIO] erzeugen, das über die Aufnahme hinausreicht. Das Skript prüft, ob
Untertitelsegmente mit Zeitangaben vorhanden sind; es validiert weder deren Wörter noch deren
Zeitangaben. Hören Sie sich vor der Veröffentlichung das Audio an und gleichen Sie die Endzeiten der
Segmente mit der Videodauer ab.
FFmpeg kann manche beschädigten Medien auch wiederherstellen, statt einen Fehler zu melden. Erfolgreiche Befehle bestätigen weder eine intakte Eingabedatei noch eine korrekte Transkription.
SRT- und WebVTT-Untertitel prüfen
Öffnen Sie in demo-videos/example.mp4.subtitles die Dateien captions.srt und
captions.vtt. Die SRT-Datei enthält nummerierte Untertitelsegmente mit durch Komma
abgetrennten Millisekunden; die VTT-Datei beginnt mit WEBVTT und verwendet
Dezimalpunkte in ihren Zeitstempeln. Beide sollten die Passagen „ask not what your country can do for
you“ und „ask what you can do for your country“ aus der Beispielaufnahme enthalten. Gleichen Sie die
Wörter mit dem Audio ab, insbesondere Namen, Zeichensetzung sowie Anfang und Ende jedes Segments.
Die Konvertierung im Skript nutzt den Untertitel-Encoder webvtt von FFmpeg.
Für diesen Weg von SRT zu WebVTT benötigen Sie Subtitle Edit CLI nicht. Eine separate WebVTT-Datei
ist für die Untertitelspur eines kompatiblen Webplayers bereit; allein das Erzeugen der Datei bindet
sie noch nicht in eine Website ein.
Die wählbare Untertitelspur prüfen
Öffnen Sie soft.mkv in einem Player, der Matroska und SRT-Untertitel
unterstützt, und wählen Sie die englische Untertitelspur aus. Das Skript ordnet explizit den ersten
Videostream, den ersten Audiostream und die erzeugten Untertitel zu. Der
Streamcopy-Modus -c copy von FFmpeg kopiert
diese Streams in die MKV-Datei, ohne das Video zu codieren. So erfolgt das Muxing ohne zusätzliche
Installation von MKVToolNix.
Untertitel mit FFmpeg einbrennen
Öffnen Sie burned.mp4, ohne eine externe Untertiteldatei zu aktivieren. Der Text
sollte bereits im Videobild erscheinen. Der
libass-basierte Filter subtitles von FFmpeg
rendert die SRT-Datei, und libx264 codiert die geänderten Frames. Deshalb
erfordert das Einbrennen Video-Encoding, während das Hinzufügen einer wählbaren Spur ohne auskommt.
Das Audio wird in beiden Ausgaben kopiert.
Beim Beispiel mit schwarzem Hintergrund können Sie auch einen Frame bei zwei Sekunden decodieren.
Die neue Datei preview.png sollte unten sichtbaren weißen Text enthalten; das
Quellvideo ist zu diesem Zeitpunkt vollständig schwarz:
(
cd ./demo-videos/example.mp4.subtitles || exit
[[ ! -e preview.png && ! -L preview.png ]] || { printf 'preview.png already exists\n' >&2; exit 1; }
ffmpeg -nostdin -n -v error -ss 2 -i burned.mp4 -frames:v 1 -threads 2 preview.png
)
Die Option -n verweigert das Ersetzen
einer vorhandenen Vorschau. Wenn Sie captions.srt nachträglich bearbeiten, ändern
sich weder die Videos noch die bereits erzeugte VTT-Datei. Bewahren Sie korrigierte Untertitel auf
und rendern Sie neue Ausgaben, bevor Sie diese veröffentlichen.
Tipps zu Leistung und Skalierung
Messen Sie Transkription und Einbrennen getrennt anhand Ihrer eigenen Aufnahmen. Dieses Beispiel verwendet bewusst zwei CPU-Threads und keine GPU; es lässt keine Vorhersage der Verarbeitungsgeschwindigkeit auf anderer Hardware zu. Falls im Entwurf gesprochene Passagen fehlen, vergleichen Sie ein größeres englisches Modell anhand eines repräsentativen Clips und prüfen Sie auch dessen Ausgabe. Ein größeres Modell ersetzt nicht die Kontrolle der Transkription.
Bewahren Sie die geprüfte SRT-Datei zusammen mit der Aufnahme auf, damit Sie das Auslieferungsformat ändern können, ohne erneut zu transkribieren. Das Stapelskript transkribiert für neue Ergebnisverzeichnisse immer neu; es verwendet Ihre Korrekturen nicht automatisch wieder.
Fazit
Wenn Sie bereits geprüfte Untertitel haben und das Einbrennen als verwalteten Dienst nutzen möchten,
akzeptiert unser Robot
🤖 /video/subtitle vorhandene SRT- oder WebVTT-Untertitel. Er erzeugt
keine Transkription. Laden Sie das Video im Formularfeld input_video und die
Untertiteldatei in input_srt hoch; diese
Assembly Instructions halten die Eingaben getrennt:
{
"steps": {
"subtitle_video": {
"robot": "/video/subtitle",
"use": {
"steps": [
{ "name": ":original", "fields": "input_video", "as": "video" },
{ "name": ":original", "fields": "input_srt", "as": "subtitles" }
]
},
"subtitles_type": "burned",
"font_size": 24,
"position": "bottom",
"font_color": "FFFFFF",
"border_style": "outline"
}
}
}
