Processus CLI : générer, convertir et incruster des sous-titres
Fournissez au script ci-dessous un répertoire de vidéos MP4 contenant des paroles en anglais. Il produit des sous-titres SRT horodatés, une copie WebVTT, un MKV avec une piste de sous-titres séparée et un MP4 avec des sous-titres incrustés dans ses images. Whisper.cpp assure la transcription sur CPU ; FFmpeg se charge de la conversion des sous-titres et de la production des vidéos. Considérez les résultats comme des versions provisoires à réviser avant publication.
Choisir des sous-titres sélectionnables ou incrustés
| Piste de sous-titres sélectionnable | Sous-titres incrustés | |
|---|---|---|
| Désactivation possible | Oui, dans un lecteur prenant en charge la piste | Non |
| Modification du texte | Remplacer la piste sans encoder la vidéo | Encoder une nouvelle vidéo |
| Traitement vidéo | Copier le flux vidéo existant | Effectuer le rendu du texte et encoder de nouvelles images |
| Exigence de lecture | Prise en charge du conteneur et des sous-titres | Prise en charge du codec vidéo de sortie |
Utilisez le MKV pour une piste sélectionnable et le MP4 avec incrustation lorsque le texte doit rester visible sans commande d’activation des sous-titres. Aucun de ces choix ne garantit que tous les lecteurs prennent en charge la vidéo produite. La taille du fichier dépend de la source et des paramètres d’encodage ; l’incrustation du texte ne l’augmente pas toujours.
Installer les outils de transcription sur CPU
Utilisez un système Linux avec Bash et les droits nécessaires pour installer des paquets. Ces
commandes ciblent Ubuntu 24.04 et utilisent la version v1.9.4 de
Whisper.cpp. Le modèle tiny.en, limité à l’anglais, permet de garder cet
exemple léger ; il ne garantit pas l’exactitude des résultats. Vous avez besoin d’un accès à
Internet pour l’installation et le téléchargement du modèle, puis la transcription s’exécute
localement.
Installez FFmpeg, un compilateur C++, CMake et une police pour le rendu :
(
sudo apt-get update &&
sudo apt-get install -y build-essential cmake curl ca-certificates tar ffmpeg fonts-liberation
)
Depuis un répertoire de travail où vous avez le droit d’écriture, créez
subtitle-tools. Le sous-shell laisse votre répertoire courant et les options du
shell inchangés. Si ce répertoire existe déjà, la configuration s’arrête avant d’y installer ou
d’y écrire quoi que ce soit ; choisissez un autre répertoire de travail plutôt que de supprimer
le travail existant.
(
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 -
)
Cette procédure suit le processus de compilation avec CMake et de préparation audio de Whisper.cpp. Son interface CLI accepte le WAV PCM mono à 16 kHz sur 16 bits que le script extrait de chaque vidéo. D’autres surcouches de Whisper, dont SubsAI, ont leur propre syntaxe de commande ; elles ne sont pas nécessaires ici.
Pour essayer ce processus sans fournir d’enregistrement, créez une vidéo à partir de l’extrait du discours de JFK fourni avec cette version. Exécutez ceci depuis le même répertoire de travail que pour la configuration :
(
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
)
Automatiser le tout avec un script shell
Enregistrez le script suivant sous le nom subtitle-tools/subtitles.sh. Il traite uniquement les
fichiers ordinaires à la racine du répertoire dont le suffixe est .mp4
en minuscules, et ignore les liens symboliques. Pour chaque fichier d’entrée, un nouveau répertoire
est créé à ses côtés, par exemple example.mp4.subtitles. Les espaces, les guillemets et
les traits d’union en début de nom de fichier sont pris en charge ; les chemins contenant des
caractères de saut de ligne sont rejetés. N’exécutez qu’un lot à la fois.
Les noms de fichiers fixes dans chaque répertoire de résultats permettent de ne pas utiliser le chemin d’origine dans la syntaxe distincte des filtres de FFmpeg. Le script conserve une copie de la source et un fichier audio PCM : prévoyez donc de l’espace disque pour ces fichiers ainsi que pour les deux vidéos produites.
#!/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'
Exécutez-le depuis le répertoire de travail où vous avez installé les outils, qui est distinct du répertoire d’entrée :
bash ./subtitle-tools/subtitles.sh ./demo-videos
Remplacez ./demo-videos par votre répertoire d’enregistrements. Le script résout
le chemin de ce répertoire avant de sélectionner les fichiers ; il ne traite pas les MP4 du
répertoire de l’appelant. Vous pouvez aussi fournir des chemins absolus pour le script enregistré
et pour le répertoire d’entrée.
Un répertoire vide renvoie une erreur. Une vidéo sans flux audio, une erreur de décodage ou l’échec d’une conversion ultérieure arrête le lot et indique le fichier d’entrée en cours. Un échec peut laisser des fichiers partiels dans son répertoire de résultats. Les répertoires de résultats existants provoquent une erreur avant la copie ou la transcription du clip concerné : les exécutions répétées préservent donc les résultats précédents. Ce script ne reprend pas un traitement interrompu : pour relancer le traitement d’un seul clip corrigé, placez-le dans un répertoire séparé sans résultats existants.
Un audio silencieux n’est pas la même chose qu’un flux audio absent. Le modèle peut ne produire
aucun segment, ou produire des annotations non verbales ou du texte inventé. Par exemple,
tiny.en peut produire un segment [BLANK_AUDIO] qui se
prolonge au-delà de l’enregistrement. Le script vérifie la présence de segments horodatés ; il ne
valide ni leur texte ni leur synchronisation. Écoutez l’audio et comparez la fin des segments à la
durée de la vidéo avant publication.
FFmpeg peut aussi récupérer certains fichiers multimédias endommagés au lieu de signaler une erreur. La réussite des commandes ne garantit ni l’intégrité du fichier d’entrée ni l’exactitude de la transcription.
Vérifier les sous-titres SRT et WebVTT
Dans demo-videos/example.mp4.subtitles, ouvrez captions.srt et
captions.vtt. Le SRT contient des segments numérotés avec une virgule avant les
millisecondes ; le VTT commence par WEBVTT et utilise des points décimaux
dans ses horodatages. Les deux devraient contenir les phrases « ask not what your country can do
for you » et « ask what you can do for your country » de l’extrait. Vérifiez le texte par rapport
à l’audio, en particulier les noms, la ponctuation, ainsi que le début et la fin de chaque segment.
La conversion du script utilise l’encodeur de sous-titres webvtt de FFmpeg.
Vous n’avez pas besoin de Subtitle Edit CLI pour cette conversion de SRT en WebVTT. Un fichier
WebVTT séparé est prêt à servir de piste de sous-titres dans un lecteur web compatible ; la seule
génération du fichier ne l’intègre pas à un site web.
Vérifier la piste de sous-titres sélectionnable
Ouvrez soft.mkv dans un lecteur prenant en charge Matroska et les sous-titres
SRT, puis sélectionnez sa piste de sous-titres en anglais. Le script sélectionne explicitement le
premier flux vidéo, le premier flux audio et les sous-titres générés. Le
mode de copie des flux -c copy de FFmpeg
copie ces flux dans le MKV sans encoder la vidéo. Il effectue ainsi le multiplexage sans nécessiter
l’installation de MKVToolNix en complément.
Incruster les sous-titres dans l’image avec FFmpeg
Ouvrez burned.mp4 sans activer de fichier de sous-titres externe. Le texte
devrait déjà apparaître dans l’image vidéo. Le
filtre subtitles reposant sur libass de FFmpeg
effectue le rendu du SRT, et libx264 encode les images modifiées. C’est
pourquoi l’incrustation nécessite un encodage vidéo, contrairement à l’ajout d’une piste
sélectionnable. L’audio est copié dans les deux vidéos produites.
Pour l’extrait sur fond noir, vous pouvez aussi décoder une image à deux secondes. Le nouveau
fichier preview.png devrait contenir du texte blanc visible près du bas de
l’image ; à cet instant, la vidéo source est entièrement noire :
(
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
)
L’option -n refuse de remplacer un
aperçu existant. Modifier captions.srt par la suite ne change ni les vidéos ni
le VTT déjà générés. Conservez les sous-titres corrigés et produisez de nouveaux fichiers avant de
les publier.
Conseils de performances et de passage à l’échelle
Mesurez séparément la transcription et l’incrustation sur vos propres enregistrements. Cet exemple utilise délibérément deux threads CPU et aucun GPU ; il ne permet pas de prédire la vitesse de traitement sur un autre matériel. Si la version provisoire omet des paroles, comparez les résultats d’un modèle anglais plus grand sur un clip représentatif et révisez aussi ce qu’il produit. Un modèle plus grand ne remplace pas la vérification de la transcription.
Conservez le SRT révisé avec l’enregistrement pour pouvoir changer le format de diffusion sans recommencer la transcription. Le script de traitement par lots effectue toujours une transcription pour les nouveaux répertoires de résultats ; il ne réutilise pas automatiquement vos corrections.
Conclusion
Si vous avez déjà des sous-titres révisés et souhaitez une solution gérée d’incrustation de
sous-titres, notre Robot
🤖 /video/subtitle (English) accepte des sous-titres SRT ou WebVTT existants.
Il ne génère pas la transcription. Téléversez la vidéo dans le champ de formulaire
input_video et le fichier de sous-titres dans input_srt ;
ces Assembly Instructions gardent ces entrées
séparées :
{
"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"
}
}
}
