Motivations
Le projet INCLUDE a soulevé un certain nombre de questions sur l'accessibilité numérique des documents produits par les enseignants.
L'utilisation des e-pub3.2+accessibility1.0 a été proposé comme l'une des solutions possibles, toutefois le respect de ces normes qui introduit un balisage avec un vocabulaire issu de schema.org
ne fournit ni transcription des audio, ni sous-titrage.
Le but de ce travail est de décrire une méthode utilisée pour enrichir les vidéos incluses dans les livres numériques au format e-pub et plus généralement toute vidéo dont on souhaiterait améliorer l'accessibilité pour les malentendants.
Avertissement
Lorsque j'ai réalisé ce travail je n'avais absolument pas perçu que je mettais en oeuvre un outil d'IA. J'avais simplement vérifié que le code était ouvert (licence MIT et communauté ouverte sur GitHub) sans aller plus loin dans l'investigation. L'outil whisper est partagé avec la communauté par la société OpenAI qui porte aussi chatGPT
à propos duquel les discussions occupent le devant de la scène en ce moment. Whisper
n'est pas un dérivé de chatGPT mais partage avec lui le même modèle.
GPT signifie "Generative Pre-trained Transformer" et fait partie de la famille des LLM "Large Language Model"; le pré-entrainement consiste à exposer l'algorithme à un gigantesque corpus de ressources à partir duquel par essais/évaluation successifs est affinée une échelle de probabilités d'enchainement de mots (ou de "tokens" selon le langage openAI qui correspondent plus ou mois à une partie de mot liée à une de ses racines).
On conçoit aisément que si en plus d'un outils de génération de texte on dispose d'un moteur capable de transcrire même rudimentairement les phonèmes en représentation textuelle, cela fournit à l'algorithme de génération des indications décisives pour choisir à tout moment de la lecture, avec une probabilité extrêmement forte, le mot suivant de la chaîne constituant la phrase enregistrée. Cela se traduit par la performance élevée de cet outil de transcription qui m'avait séduit.
je ne souhaite pas ici entrer dans le débat sur IA et enseignement, il me semble que le fait que chacun puisse contrôler les résultats de l'exécution avant de les diffuser, intervenir facilement sur quelques paramètres simples du modèle, contribuer à l'évolution ou modifier librement le code source du logiciel suffit à garantir durablement un usage sain et neutre. Un autre argument est fourni par les angagements éthiques d'openAI.
Remerciements
Éric le Jan et Charles-Henri Eyraud, Carole Larose, Benkouar Benyoucef.
Sommaire
Ajouter des sous-titres à une vidéo
- Installation des logiciels
- Extraction de la piste audio d'une vidéo
- Transcription du fichier audio
- Correction du fichier texte issu de l'audio
- Ajout du canal de sous-titres à la vidéo
- Conclusion
Téléchargements
Ajouter des sous-titres à une vidéo
Les sous-titres dérivent forcément d'un fichier audio la procédure de sous-titrage requiert une étape préliminaire de traitement de la vidéo afin d'extraire le son sous forme d'un fichier audio. On utilise trois logiciels pour réaliser complètement la procédure :
- whisper
- jubler
- ffmpeg
Déroulé
La procédure de transcription se déroule en trois étapes utilisant chacune l'un des logiciels installés avec les commandes ci-dessus :
- on extrait l'audio de la vidéo -> ffmpeg
- on réalise la transcription de l'audio (avec correction si besoin) -> whisper (+ jubler )
- on intègre les sous-titres à la vidéo -> ffmpeg
Si vous êtes pressés...
Les résultats du travail sont consultables sur cette page. les données quantitatives de comparaison sont proposées ici
1. Installation des logiciels
1.1 Linux
L'installation détaillée ci-dessous concerne l'OS linux, pour les autres OS se reporter aux instructions détaillées depuis les pages de garde des 3 logiciels
Pour whisper
il est nécessaire de créer un environnement virtuel python qui est la façon préconnisée pour gérer un logiciel avec des dépendances sans perturber le fonctionnement du système (nous utilisons ici pipenv
mais les autres solutions de Virt.Envs python sont tout aussi valides). De plus au moment de l'installation (04-12-23) openai-whisper
imposait l'usage de python < 3.11 à cause de la version de numba
qui n'est pas encore adaptée à python3.11
, cette limitation étant susceptible d'évoluer avec les mises à disposition de nouvelles versions de python3. Deux solutions sont possibles, soit on utilise python3.9
ou python3.10
soit on installe indépendamment numba avant d'installer whisper avec la commande pipenv install "numba==0.57.0rc1"
dans l'environnement virtuel.
mkdir -p Whisper/VenvWhisper
cd Whisper/VenvWhisper
pipenv --python 3.10 install openai-whisper pycuda torchaudio torchvision openai
Nous proposons d'installer la version deb-multimedia qui propose par défaut l'utilisation de fragments non libres mais qui en contrepartie fournit une grande souplesse d'utilisation en éliminant quelques incompatibilités. Pour les distributions Linux Debian et dérivées, ajouter dans /etc/apt/sources.list.d
un fichier ffmpegMarillat.list
contenant deb https://www.deb-multimedia.org bookworm main non-free
puis effectuer les commandes suivantes.
sudo apt update -oAcquire::AllowInsecureRepositories=true
sudo apt install deb-multimedia-keyring
sudo apt install ffmpeg
Jubler propose un appimage
directement exécutable, j'ai pris l'habitude de les copier dans mon /usr/local/bin
.
wget https://github.com/teras/Jubler/releases/download/v7.0.3/Jubler-7.0.3.x86_64.appimage
chmod a+x Jubler-7.0.3.x86_64.appimage
sudo cp Jubler-7.0.3.x86_64.appimage /usr/local/bin/jubler
1.2 Windows
La méthode la plus simple (la seule que j'ai pu mener à bien) reste d'installer un linux à l'intérieur de windows puis de suivre ensuite la procédure proposée pour linux hormis pour jubler
qui peut être directement installé depuis le site. Windows limite les ressources et les affichages de linux mais le logiciel est fonctionnel.
2. Extraction de la piste audio d'une vidéo
Il est utile de déterminer la structure de la vidéo utilisée afin de reconnaître les différentes pistes présentes. La commande ffprobe nomVidéo
fournie par ffmpeg fait parfaitement ce travail :
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video1.mp4':
Metadata:
major_brand : mp42
minor_version : 1
compatible_brands: mp41mp42isom
creation_time : 2023-02-27T22:26:28.000000Z
Duration: 00:09:07.10, start: 0.000000, bitrate: 482 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), [SAR 1:1 DAR 706:415], 346 kb/s, 60 fps, 60 tbr, 15360 tbn (default)
Metadata:
creation_time : 2023-02-27T22:26:28.000000Z
handler_name : Core Media Video
vendor_id : [0][0][0][0]
encoder : Lavc59.37.100 libx264
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)
Metadata:
creation_time : 2023-02-27T22:26:28.000000Z
handler_name : Core Media Audio
vendor_id : [0][0][0][0]
Sur les données ci-dessus on peut lire que la vidéo utilisée dure 00:09:07.10
soit 9 minutes 7 secondes, elle fait 1412x830
pixels
Elle contient 2 flux :
- Un flux vidéo
#0:0[0x1](und): Video: h264
le codec est H264- rapport de forme des pixels stockés
SAR 1:1
- rapport d'aspect de l'affichage de la vidéo attendu
DAR 706:415
ce rapport bizarre est issu de la taille de la fenêtre de l'ordinateur qui a été enregistrée.
- rapport de forme des pixels stockés
- Un flux audio
#0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D)
le codec est du acc, la désignation mp4a (parfois m4a) signifie qu'il s'agit d'un audio intégrée dans un conteneur mp4
Pour extraire l'audio la commande suivante permet de récupérer le fichier audio pour les traitements ultérieurs.
ffmpeg -i video1.mp4 -vn -acodec copy video1.aac
Les paramètres indiquent -vn
pas de vidéo et -acodec copy
copie du codec audio. On obtient un fichier audio au format aac
qui est immediatement accessible par whisper
.
3. Transcription du fichier audio
Pour la transcription on utilise le logiciel ai-whisper
qui dispose d'un grand nombre de paramètres permettant de moduler le modèle utilisé et les fonctions choisies pour les opérations. On utilise l'environnement virtuel créé dans le premier paragraphe. Si vous êtes équipés d'une carte vidéo puissante avec les logiciels d'exploitation de sa puissance de calcul installés, whisper
tentera de l'utiliser afin de minimiser le tamps de calcul, attention à la taille mémoire du modèle utilisé ! Si vous n'avez pas trop de mémoire sur la carte vidéo pensez à utiliser les petits modèles sinon le manque de mémoire indut des fautes aléatoires dont les messages sont peu explicites et ne renvoient pas forcément et explicitement l'avertissement d'un manque de mémoire. Il est toujours possible de contraindre l'exécution sur le CPU central avec l'option --device
(Pour les cartes vidéo, j'ai testé seulement l'exécution sur une nvidia avec CUDA qui a parfaitement fonctionné, j'essaierai une AMD si j'en trouve une que je parvienne à configurer). La commande ci-dessous liste les principales options de whisper
.
cd Whisper/VenvWhisper/
pipenv run whisper --help
usage: whisper [-h] [--model {tiny.en,tiny,base.en,base,small.en,small,medium.en,medium,large-v1,large-v2,large}] [--model_dir MODEL_DIR] [--device DEVICE]
[--output_dir OUTPUT_DIR] [--output_format {txt,vtt,srt,tsv,json,all}] [--verbose VERBOSE] [--task {transcribe,translate}]
[--language {af,am,ar,as,az,ba,be,bg,bn,bo,br,bs,ca,cs,cy,da,de,el,en,es,et,eu,fa,fi,fo,fr,gl,gu,ha,haw,he,hi,hr,ht,hu,hy,id,is,it,ja,jw,ka,kk,km,kn,ko,la,lb,ln,lo,lt,lv,mg,mi,mk,ml,mn,mr,ms,mt,my,ne,nl,nn,no,oc,pa,pl,ps,pt,ro,ru,sa,sd,si,sk,sl,sn,so,sq,sr,su,sv,sw,ta,te,tg,th,tk,tl,tr,tt,uk,ur,uz,vi,yi,yo,zh,Afrikaans,Albanian,Amharic,Arabic,Armenian,Assamese,Azerbaijani,Bashkir,Basque,Belarusian,Bengali,Bosnian,Breton,Bulgarian,Burmese,Castilian,Catalan,Chinese,Croatian,Czech,Danish,Dutch,English,Estonian,Faroese,Finnish,Flemish,French,Galician,Georgian,German,Greek,Gujarati,Haitian,Haitian Creole,Hausa,Hawaiian,Hebrew,Hindi,Hungarian,Icelandic,Indonesian,Italian,Japanese,Javanese,Kannada,Kazakh,Khmer,Korean,Lao,Latin,Latvian,Letzeburgesch,Lingala,Lithuanian,Luxembourgish,Macedonian,Malagasy,Malay,Malayalam,Maltese,Maori,Marathi,Moldavian,Moldovan,Mongolian,Myanmar,Nepali,Norwegian,Nynorsk,Occitan,Panjabi,Pashto,Persian,Polish,Portuguese,Punjabi,Pushto,Romanian,Russian,Sanskrit,Serbian,Shona,Sindhi,Sinhala,Sinhalese,Slovak,Slovenian,Somali,Spanish,Sundanese,Swahili,Swedish,Tagalog,Tajik,Tamil,Tatar,Telugu,Thai,Tibetan,Turkish,Turkmen,Ukrainian,Urdu,Uzbek,Valencian,Vietnamese,Welsh,Yiddish,Yoruba}]
[--temperature TEMPERATURE] [--best_of BEST_OF] [--beam_size BEAM_SIZE] [--patience PATIENCE] [--length_penalty LENGTH_PENALTY]
[--suppress_tokens SUPPRESS_TOKENS] [--initial_prompt INITIAL_PROMPT] [--condition_on_previous_text CONDITION_ON_PREVIOUS_TEXT] [--fp16 FP16]
[--temperature_increment_on_fallback TEMPERATURE_INCREMENT_ON_FALLBACK] [--compression_ratio_threshold COMPRESSION_RATIO_THRESHOLD]
[--logprob_threshold LOGPROB_THRESHOLD] [--no_speech_threshold NO_SPEECH_THRESHOLD] [--word_timestamps WORD_TIMESTAMPS]
[--prepend_punctuations PREPEND_PUNCTUATIONS] [--append_punctuations APPEND_PUNCTUATIONS] [--threads THREADS]
audio [audio ...]
positional arguments:
audio audio file(s) to transcribe
options:
-h, --help show this help message and exit
--model {tiny.en,tiny,base.en,base,small.en,small,medium.en,medium,large-v1,large-v2,large}
name of the Whisper model to use (default: small)
--model_dir MODEL_DIR
the path to save model files; uses ~/.cache/whisper by default (default: None)
--device DEVICE device to use for PyTorch inference (default: cpu)
--output_dir OUTPUT_DIR, -o OUTPUT_DIR
directory to save the outputs (default: .)
--output_format {txt,vtt,srt,tsv,json,all}, -f {txt,vtt,srt,tsv,json,all}
format of the output file; if not specified, all available formats will be produced (default: all)
--verbose VERBOSE whether to print out the progress and debug messages (default: True)
--task {transcribe,translate}
whether to perform X->X speech recognition ('transcribe') or X->English translation ('translate') (default: transcribe)
--language {af,am,ar,as,az,ba,be,bg,bn,bo,br,bs,ca,cs,cy,da,de,el,en,es,et,eu,fa,fi,fo,fr,gl,gu,ha,haw,he,hi,hr,ht,hu,hy,id,is,it,ja,jw,ka,kk,km,kn,ko,la,lb,ln,lo,lt,lv,mg,mi,mk,ml,mn,mr,ms,mt,my,ne,nl,nn,no,oc,pa,pl,ps,pt,ro,ru,sa,sd,si,sk,sl,sn,so,sq,sr,su,sv,sw,ta,te,tg,th,tk,tl,tr,tt,uk,ur,uz,vi,yi,yo,zh,Afrikaans,Albanian,Amharic,Arabic,Armenian,Assamese,Azerbaijani,Bashkir,Basque,Belarusian,Bengali,Bosnian,Breton,Bulgarian,Burmese,Castilian,Catalan,Chinese,Croatian,Czech,Danish,Dutch,English,Estonian,Faroese,Finnish,Flemish,French,Galician,Georgian,German,Greek,Gujarati,Haitian,Haitian Creole,Hausa,Hawaiian,Hebrew,Hindi,Hungarian,Icelandic,Indonesian,Italian,Japanese,Javanese,Kannada,Kazakh,Khmer,Korean,Lao,Latin,Latvian,Letzeburgesch,Lingala,Lithuanian,Luxembourgish,Macedonian,Malagasy,Malay,Malayalam,Maltese,Maori,Marathi,Moldavian,Moldovan,Mongolian,Myanmar,Nepali,Norwegian,Nynorsk,Occitan,Panjabi,Pashto,Persian,Polish,Portuguese,Punjabi,Pushto,Romanian,Russian,Sanskrit,Serbian,Shona,Sindhi,Sinhala,Sinhalese,Slovak,Slovenian,Somali,Spanish,Sundanese,Swahili,Swedish,Tagalog,Tajik,Tamil,Tatar,Telugu,Thai,Tibetan,Turkish,Turkmen,Ukrainian,Urdu,Uzbek,Valencian,Vietnamese,Welsh,Yiddish,Yoruba}
language spoken in the audio, specify None to perform language detection (default: None)
--temperature TEMPERATURE
temperature to use for sampling (default: 0)
--best_of BEST_OF number of candidates when sampling with non-zero temperature (default: 5)
--beam_size BEAM_SIZE
number of beams in beam search, only applicable when temperature is zero (default: 5)
--patience PATIENCE optional patience value to use in beam decoding, as in https://arxiv.org/abs/2204.05424, the default (1.0) is equivalent to conventional beam search
(default: None)
--length_penalty LENGTH_PENALTY
optional token length penalty coefficient (alpha) as in https://arxiv.org/abs/1609.08144, uses simple length normalization by default (default: None)
--suppress_tokens SUPPRESS_TOKENS
comma-separated list of token ids to suppress during sampling; '-1' will suppress most special characters except common punctuations (default: -1)
--initial_prompt INITIAL_PROMPT
optional text to provide as a prompt for the first window. (default: None)
--condition_on_previous_text CONDITION_ON_PREVIOUS_TEXT
if True, provide the previous output of the model as a prompt for the next window; disabling may make the text inconsistent across windows, but the
model becomes less prone to getting stuck in a failure loop (default: True)
--fp16 FP16 whether to perform inference in fp16; True by default (default: True)
--temperature_increment_on_fallback TEMPERATURE_INCREMENT_ON_FALLBACK
temperature to increase when falling back when the decoding fails to meet either of the thresholds below (default: 0.2)
--compression_ratio_threshold COMPRESSION_RATIO_THRESHOLD
if the gzip compression ratio is higher than this value, treat the decoding as failed (default: 2.4)
--logprob_threshold LOGPROB_THRESHOLD
if the average log probability is lower than this value, treat the decoding as failed (default: -1.0)
--no_speech_threshold NO_SPEECH_THRESHOLD
if the probability of the <|nospeech|> token is higher than this value AND the decoding has failed due to `logprob_threshold`, consider the segment
as silence (default: 0.6)
--word_timestamps WORD_TIMESTAMPS
(experimental) extract word-level timestamps and refine the results based on them (default: False)
--prepend_punctuations PREPEND_PUNCTUATIONS
if word_timestamps is True, merge these punctuation symbols with the next word (default: "'“¿([{-)
--append_punctuations APPEND_PUNCTUATIONS
if word_timestamps is True, merge these punctuation symbols with the previous word (default: "'.。,,!!??::”)]}、)
--threads THREADS number of threads used by torch for CPU inference; supercedes MKL_NUM_THREADS/OMP_NUM_THREADS (default: 0)
La commande utilisée avec une configuration minimaliste permet de produire un fichier au format srt
(le modèle medium ne passe pas sur ma carte NVIDIA GeForce GTX 1660 SUPER avec un bureau ouvert mais Xorg,firefox et thunderbird mobilisent un peu plus de 800M, medium passe peut-être en mode console...). Tous les centres de calcul proposent des machines équipées de grosses cartes graphiques de calcul qui peuvent au besoin sous-traiter ce calcul.
whisper --model small --task transcribe --output_format srt --language fr video1.aac
Commande pour produire les sous-titres en anglais (penser à changer le nom du fichier srt
qui sera écrasé sinon) :
whisper --model small --output_format srt --task translate --language fr video1.aac
4. Correction du fichier texte issu de l'audio
Le fichier produit par ai-whisper
malgré le support d'un modèle d'IA peut ne pas être exempt d'anomalies, il est nécessaire de relire le fichier afin de corriger les éventuelles erreurs qui auraient échappé au dispositif automatisé (À titre d'exemple sur le fichier traité ici on a relevé une seule erreur). On utilise pour cela l'interface graphique du logiciel jubler. Ouvrir le fichier srt
puis cliquer sur chaque ligne qui doit être corrigée et effectuer les corrections nécessaires puis sauvegarder le fichier.
5. Ajout du canal de sous-titres à la vidéo
La dernière opération consiste à ajouter le ou les canaux de sous-titres à la vidéo originelle. Deux méthodes sont possibles et éventuellement complémentaires :
- ajouter les sous-titres dans des canaux indépendants ("overlay" ce qui requiert, pour les voir, un lecteur capable de détecter ces canaux et d'en afficher un ou un autre ou de les masquer à la demande)
- incruster les sous-titres dans l'image sous la forme d'une surcouche (incrustation), il n'y a pas de canal supplémentaire créé et la vidéo affiche en permanence les sous-titres.
5.1. Sous-titres en "overlay"
- Exemple avec un fichier de sous-titres (mp4)
- Exemple avec un fichier de sous-titres (webm)
- Exemple avec deux fichier de sous-titres (mp4)
- Exemple avec udeux fichier de sous-titres (webm)
Cette méthode est la plus simple et la moins consommatrice de temps car les images de la vidéo ne sont pas modifiées et les sous-titres ajoutés sous la forme d'un canal supplémentaire qui doit être géré par le lecteur. L'intérêt majeur est qu'un utilisateur ne souhaitant pas lire les sous-titres pourra afficher l'image intacte et celui qui souhaite les lire les afficher en transparence. On utilise la commande ffmpeg suivante à partir de la vidéo video1.mp4
avec les sous-titres video1.srt
produits précédemment :
ffmpeg -i video1.mp4 -i video1.srt -c copy -c:s mov_text video1+sstit.mp4
On a alors une vidéo contenant 3 flux :
ffprobe video1+sstit.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video1+sstit.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf59.27.100
Duration: 00:09:07.12, start: 0.000000, bitrate: 487 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1412x830 [SAR 1:1 DAR 706:415], 346 kb/s, 60 fps, 60 tbr, 15360 tbn (default)
Metadata:
handler_name : Core Media Video
vendor_id : [0][0][0][0]
encoder : Lavc59.37.100 libx264
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)
Metadata:
handler_name : Core Media Audio
vendor_id : [0][0][0][0]
Stream #0:2[0x3](und): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s (default)
Metadata:
handler_name : SubtitleHandler
../...
Il est aussi possible de rajouter une seconde piste de sous-titres, par exemple ici en anglais avec le fichier video1-en.srt
:
ffmpeg -i video1+sstit.mp4 -i video1-en.srt -map 0 -map 1 -vcodec copy -acodec copy -c:s:0 copy -c:s:1 copy -c:s:1 mov_text -metadata:s:s:1 language=English video1+2sstit.mp4
Le fichier vidéo présentee alors 2 flux de sous-titres :
ffprobe video1+2sstit.mp4
.../...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video1+2sstit.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf59.27.100
Duration: 00:09:07.12, start: 0.000000, bitrate: 487 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1412x830 [SAR 1:1 DAR 706:415], 346 kb/s, 60 fps, 60 tbr, 15360 tbn (default)
Metadata:
handler_name : Core Media Video
vendor_id : [0][0][0][0]
encoder : Lavc59.37.100 libx264
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)
Metadata:
handler_name : Core Media Audio
vendor_id : [0][0][0][0]
Stream #0:2[0x3](und): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s (default)
Metadata:
handler_name : SubtitleHandler
Stream #0:3[0x4]: Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s
Metadata:
handler_name : SubtitleHandler
Il est aussi possible de rajouter plusieurs sous-titres directement en une seule passe ici pour le film curationIFE Le lien conduit à la vidéo avec sous-titres (à visualiser sur un player capable de les détecter VLC par exemple) :
ffmpeg -i curationIFE.mp4 -i curationIFE-fr-cor.srt -i curationIFE-en-cor.srt -map 0:v -map 0:a -map 1 -map 2 -c:v copy -c:a copy -c:s mov_text -metadata:s:s:0 language=fre -metadata:s:s:1 language=eng curationIFE+sstt.mp4
Dans un player capable de détecter les sous-titres (par exemple VLC) on a alors desux "pistes" proposées dans l'onglet sous-titres.
5.2. Sous-titres en "incrustation"
L'incrustation des sous-titres est une opération un peu plus complexe car les images de la vidéo qui contiennent des sous-titres sont recomposées en incrustant dans l'image le sous-titre ce qui impose de modifier tous les pixels correspondant à la surface des sous-titres. Une difficulté supplémentaire vient (au moins pour la méthode proposée) de ce qu'il faille utiliser le format .ass
au lieu de .srt
pour les sous-titres, une conversion de format est donc nécessaire en amont. La manipulation a été réalise avec l'enchaînement de commandes suivant :
ffmpeg -i video1.srt video1.ass # produit le fichier de sous-titres au format ass
ffmpeg -i video1.mp4 -filter_complex "subtitles=video1.ass:force_style='BackColour=&H70000000,BorderStyle=4,Outline=1,Shadow=0,MarginV=10'" video1+sstit2.mp4
La partie filter_complex "subtitles=video1.ass:force_style='BackColour=&H70000000,BorderStyle=4,Outline=1,Shadow=0,MarginV=10'"
gère le détail des options de présentation des sous-titres, comme souvent dans ffmpeg ces options sont délicates à manipuler parce qu'elles agissent au plus bas niveau et sans "garde-fou"; consultez la documentation et agissez avec précaution pour les manipuler, de nombreuses options cont possibles tant sur le texte que sur le fond.
La vidéo produite ne contient aucun flux de sous-titre, le texte est directement incrusté dans les images.
ffprobe video1+sstit2.mp4
.../...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video1+sstit2.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf59.27.100
Duration: 00:09:07.12, start: 0.000000, bitrate: 578 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1412x830 [SAR 1:1 DAR 706:415], 437 kb/s, 60 fps, 60 tbr, 15360 tbn (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
encoder : Lavc59.37.100 libx264
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
handler_name : Core Media Audio
vendor_id : [0][0][0][0]
6. Conclusion
Cet article présente une des nombreuses façons de sous-titrer une vidéo, la méthode proposée peut certainement être améliorée ou modifiée en fonction de contraintes ou de choix éditoriaux. Un des intérêts est de montrer la faisabilité de l'opération sans qu'il soit besoin de connaissances avancées en media ou en numérique. Il est toutefois parfaitement clair qu'une production qe qualité professionnelle requiert des compétences professionnelles, toutefois il est probable que des étudiants malentendants apprécieront de disposer des sous-titres, de même la possibilité de proposer les sous-titres en anglais ouvre des perspectives importantes.
Commentaires