Extraction de sous-titre d'un DVD

Published: 17-01-2015

Updated: 21-06-2017

By: Maxime de Roucy

tags: ass dvd ffmpeg video vobsub

Mes notes concernant l’extraction et la conversion des sous-titre d’un DVD en VOBSUB et ASS.

Sources :

Pour plus de simplicité je fais une copie iso du DVD sur mon disque dure. Cette étape n’est pas nécessaire, on peut trés bien travailler directement sur /dev/sr0.

Sélection de la piste

Un DVD contient plusieurs titres, nous devons choisir le bon (le film).

Pour lire le titre n°1 d’un DVD

max@laptop % mpv     dvd://1     --dvd-device DVD.iso
max@laptop % mpv     dvdread://1 --dvd-device DVD.iso

dvd (anciennement appelé dvdnav) et dvdread sont deux implémentations différentes. dvd peut passer automatiquement d’un titre à l’autre. Le support de dvd://menu a été supprimé des version récente de mpv.

Il est possible de connaitre le titre actuellement joué via dvd en observant la sortie standard. DVDNAV, switched to title: 23 indique que je suis en train de lire le titre 23.

Pour lister les titres d’un DVD on peut utiliser lsdvd :

max@laptop % lsdvd DVD.iso
libdvdread: Encrypted DVD support unavailable.
Disc Title: …
Title: 01, Length: 00:00:37.080 Chapters: 01, Cells: 01, Audio streams: 01, Subpictures: 00
Title: 02, Length: 00:24:34.760 Chapters: 06, Cells: 06, Audio streams: 05, Subpictures: 02
…
Longest track: 09
max@laptop % lsdvd -t 02 -x DVD.iso
libdvdread: Encrypted DVD support unavailable.
Disc Title: …
Title: 02, Length: 00:24:34.760 Chapters: 06, Cells: 06, Audio streams: 05, Subpictures: 02
        VTS: 02, TTN: 01, FPS: 25.00, Format: PAL, Aspect ratio: 16/9, Width: 720, Height: 576, DF: Letterbox
        Palette: 108080 2b8080 eb8080 51ef5a 7d8080 b48080 a910a5 6addca d29210 1c76b8 50505a 30b86d 5d4792 3dafa5 718947 eb8080
        Number of Angles: 1
        Audio: 1, Language: fr - Francais, Format: ac3, Frequency: 48000, Quantization: drc, Channels: 6,AP: 0, Content: Undefined, Stream id: 0x80
	…
        Audio: 5, Language: en - English, Format: ac3, Frequency: 48000, Quantization: drc, Channels: 2, AP: 0, Content: Undefined, Stream id: 0x84
        Chapter: 01, Length: 00:01:40.320, Start Cell: 01
	…
        Chapter: 06, Length: 00:00:00.480, Start Cell: 06
        Cell: 01, Length: 00:01:40.320
	…
        Cell: 06, Length: 00:00:00.480
        Subtitle: 01, Language: fr - Francais, Content: Undefined, Stream id: 0x20,
        Subtitle: 02, Language: xx - Unknown, Content: Undefined, Stream id: 0x21,

Attention : j’ai eu des surprise avec certains DVD, j’indiquais à mpv de lire un certain titre et il en prenait un autre. Dans ce cas j’y vais à taton, je testes les titres jusqu’à trouver le bon.

ISO → VOB

Une fois qu’on déterminé le bon titre (ici 02) on l’extrait sous forme de VOB.

max@laptop % mpv dvdread://02 --dvd-device DVD.iso --stream-dump=titre01.vob
Playing: dvdread://02
libdvdread: Encrypted DVD support unavailable.
[dvd] There are 20 titles on this DVD.
[dvd] There are 1 angles in this DVD title.
[dvd] audio stream: 0 format: ac3 (5.1) language: fr aid: 128.
[dvd] audio stream: 1 format: ac3 (5.1) language: ja aid: 129.
[dvd] audio stream: 2 format: ac3 (stereo) language: fr aid: 130.
[dvd] audio stream: 3 format: ac3 (stereo) language: ja aid: 131.
[dvd] audio stream: 4 format: ac3 (stereo) language: en aid: 132.
[dvd] number of audio channels on disk: 5.
[dvd] subtitle ( sid ): 0 language: fr
[dvd] subtitle ( sid ): 1 language: unknown
[dvd] number of subtitles on disk: 2
[dvd] CHAPTERS: 00:00:00.000,00:01:40.320,00:09:55.040,00:22:17.360,00:23:44.120,
…

Les méta données seront perdues c’est pourquoi je les affiches ici (il faut les conserver).

On peut aussi utiliser dvd mais je le déconseille car plusieurs titres peuvent s’enchainer.

max@laptop % mpv dvd://02 --dvd-device DVD.iso --stream-dump titre01.vob
…
libdvdnav: DVD disk reports itself with Region mask 0x00000000. Regions: 1 2 3 4 5 6 7 8
[dvdnav] DVDNAV, switched to title: 23
Dumping 1409284096/0...
[dvdnav] DVDNAV, switched to title: 1
Dumping 1465001984/0...
…

IFO

Il peut être interessant de sauvegarder le fichier ifo correspondant à votre titre/piste. Celui-ci contient notamment la couleur des sous-titres.

Pour déterminer le bon VTS j’utilise lsdvd :

max@laptop % lsdvd -t 02 -v DVD.iso
libdvdread: Encrypted DVD support unavailable.
Disc Title: …
Title: 02, Length: 00:24:34.760 Chapters: 06, Cells: 06, Audio streams: 05, Subpictures: 02
        VTS: 02, TTN: 01, FPS: 25.00, Format: PAL, Aspect ratio: 16/9, Width: 720, Height: 576, DF: Letterbox

Ici « VTS: 02 » donc le fichier IFO est VIDEO_TS/VTS_02_0.IFO.

max@laptop % mkdir /tmp/dvd
max@laptop % sudo mount -o loop DVD.iso /tmp/dvd
mount: /dev/loop0 est protégé en écriture, sera monté en lecture seule
max@laptop % cp /tmp/dvd/VIDEO_TS/VTS_02_0.IFO titre01.ifo

Sources :

VOB → PS1

Je veux extraire les sous-titres français, je sais qu’il s’agit du premier flux de sous-titre du VOB.

[dvd] number of audio channels on disk: 6.
[dvd] subtitle ( sid ): 0 language: fr
[dvd] subtitle ( sid ): 1 language: unknown
[dvd] number of subtitles on disk: 2

J’utilise ffmpeg pour déterminer sa référence.

max@laptop % ffprobe titre01.vob
…
Input #0, mpeg, from 'titre01.vob':
  Duration: 00:26:00.52, start: 0.280000, bitrate: 7229 kb/s
    Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p(tv), 720x576 [SAR 16:15 DAR 4:3], max. 8199 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x80]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 384 kb/s
    Stream #0:2[0x82]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 384 kb/s
    Stream #0:3[0x84]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 384 kb/s
    Stream #0:4[0x81]: Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s
    Stream #0:5[0x83]: Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s
    Stream #0:6[0x85]: Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s
    Stream #0:7[0x20]: Subtitle: dvd_subtitle
    Stream #0:8[0x21]: Subtitle: dvd_subtitle
At least one output file must be specified

Ici sa référence est « 0x20 » (premier flux de sous-titre).

Je l’extrais via tcextract (paquet « transcode » sous Archlinux).

max@laptop % tcextract -i titre01.vob -t vob -x ps1 -a 0x20 > titre01_subtitle_fr.ps1

PS1 → VOBSUB

Dans le format VOBSUB les sous-titre sont stoqué sous forme d’image. Cette technique est donc beaucoup plus simple est rapide que la création de fichier ASS.

Avec le fichier ifo :

max@laptop % subtitle2vobsub -p titre01_subtitle_fr.ps1 -i titre01.ifo -o titre01_subtitle_fr

Sans fichier ifo, subtitle2vobsub utilise des paramètre par défaut (qu’il est possible de surcharger, je n’ai pas réussi à faire fonctionner -c correctement) :

max@laptop % subtitle2vobsub -p titre01_subtitle_fr.ps1 -o titre01_subtitle_fr -s 720x576 -a 0,fr

Je change la palette par défaut (immonde) par celle donnée en exemple par matroska :

max@laptop % sed -i 's/^palette: .*/palette: 000000, 7e7e7e, fbff8b, cb86f1, 7f74b8, e23f06, 0a48ea, b3d65a, 6b92f1, 87f087, c02081, f8d0f4, e3c411, 382201, e8840b, fdfdfd/' titre01_subtitle_fr.idx

PS1 → ASS

Les sous-titre sont stoqué en temps qu’image dans le fichier PS1. Pour créé notre fichier ASS nous allons devoir passer toutes ces images dans un OCR.

PS1 → PGM

J’extrais ensuite les sous-titres sous forme d’images.

max@laptop % subtitle2pgm -i titre01_subtitle_fr.ps1 -C 0 -c 255,0,255,255

subtitle2pgm créé aussi un fichier d’index movie_subtitle.srtx qui servira de base à la création du srt.

Si les images vous paraisse moches (difficilement exploitable par un OCR) vous pouvez faire plusieurs tests en faisant varier les niveaux de gris :

max@laptop % subtitle2pgm -e 00:00:00,5 -i titre01_subtitle_fr.ps1 -C 0 -c 255,0,0,0

PGM → TXT

Nous transformons ensuite chaque images en texte via l’OCR tesseract.

max@laptop % for i in *.pgm
do
tesseract $i $i -l fra -psm 6
done

Il est aussi possible d’utiliser pgm2txt qui utilise gocr mais je trouve que les résultats sont beaucoup moins bon.

TXT → SRT

On fusionne tous le fichier srtx et txt pour créer un srt.

max@laptop % srttool -s -w -i movie_subtitle.srtx -o titre01_subtitle_fr.srt

Corrections

On corrige les fautes les plus importante avec vim. Voici les commande vim que je lance habituellement :

:%s/\.7/?/gc
:%s/\/\//Il/gc
:%s/\//l/gc
:%s/\//I/gc
:%s/||/Il/gc
:%s/|/l/gc
:%s/|/I/gc
:%s/a‘/à/gc
:%s/— /-/gc
:%s/—/-/g
:%s/\(.\)- /\1-/gc
:%s/’/'/g
:%s/”/"/g
:%s/0\([a-zA-Z]\)/O\1/gc
:%s/ 7/ ?/gc

En touche final on passe un correcteur orthographique.

max@laptop % aspell check -l fr --home-dir=. titre01_subtitle_fr.srt

Les différentes commande lors de la correction :

SRT → ASS

On converti ensuite le srt en ASS.

max@laptop % ffmpeg -i titre01_subtitle_fr.{srt,ass}

Personnellement je remplace le style utilisé par ffmpeg par mon propre style.

max@laptop % sed -i 's/Style: Default.*/Style: Default,DejaVu Sans,24,\&H0000FFFF,\&H00FFFFFF,\&H00000000,\&H00FFFFFF,0,0,0,0,100,100,0,0,1,2,0,2,20,20,20,0/' titre01_subtitle_fr.ass

Le format de style utilisé dans les fichiers ASS est, dans l’ordre d’apparition :

  1. nom du style (Default)
  2. police de caractère à utiliser (DejaVu Sans)
  3. taille de la police (24)
  4. couleur du texte (&H0000FFFF → jaune)
  5. je ne sais pas (&H00FFFFFF → blanc)
  6. couleur du contour des caractères ou de la boite de fond (&H00000000 → noir)
  7. couleur de l’ombre des caractères (&H00FFFFFF → blanc)
  8. caractères gras (0 → non)
  9. caractères italic (0 → non)
  10. texte souligné (0 → non)
  11. texte barré (0 → non)
  12. modifie la taille horizontal de la police en % (100 → taille normal)
  13. modifie la taille vertical de la police en % (100 → taille normal)
  14. ajout de pixels supplémentaires entre les caractères (0 pixels)
  15. angle de rotation du texte par rapport à l’horizontal (0 degrés d’angle)
  16. « BorderStyle » (1)
    • 1 = contour + ombre
    • 3 = boite
  17. taille du contour entre 0 et 4 pixels (2 pixels)
  18. taille de l’ombre entre 0 et 4 pixels (0 pixels)
  19. placement du texte (2)
    • 1 = gauche
    • 2 = centré
    • 3 = droite
    • +4 = haut (par exemple, 5 = 1 + 4 = en haut à gauche)
    • +8 = centre vertical
  20. marge de gauche en pixels (20)
  21. marge de droite en pixels (20)
  22. marge horizontale, haut ou bas, en pixels (20)
  23. encodage du texte (0 pour de l’ASCII)… je met de l’UTF8 et ça passe très bien.

On peut rendre plus ou moin transparente une couleur en modifiant son premier octet, c’est à dire les deux premier caractères qui suivent le « &H ». Ici aucune des couleurs n’a de transparence, elles sont complètement opaques ; leur premier octet est « 00 » (e.g. &H00FFFFFF, &H0000FFFF…). Pour rendre une couleur complètement transparente (je vois pas trop l’intérêt… mais bon) indiquez « FF » (e.g. &HFFFFFFFF, &HFF00FFFF…). Personnellement je me sers parfois de cette fonctionnalité pour mettre mes sous-titres dans des boites (paramètre n°16 à 3) noire légèrement transparentes (paramètre n°6 à &H50000000).

max@laptop % sed -i 's/Style: Default.*/Style: Default,DejaVu Sans,24,\&H0000FFFF,\&H00FFFFFF,\&H50000000,\&H00FFFFFF,0,0,0,0,100,100,0,0,3,2,0,2,20,20,20,0/' titre01_subtitle_fr.ass

Les paramètres ASS « PlayResX  » et « PlayResY » sont important pour le rendu des sous-titre, ils définissent la taille/résolution de la fenêtre d’affichage de la vidéo de celui qui à écrit le sous-titre. La taille des caractères affichés et tous les autres paramètre de style correspondant à des pixels, sont calculer en fonction de la taille de la fenêtre d’affichage de la vidéo et de ces paramètres, pas de la résolution de la vidéo ou de l’écran. Par exemple, si on fixe PlaxResY à 100 et une taille de police de 50, un caractère recouvrira en hauteur la moitié de la vidéo. Par défaut lors de la conversion d’un SRT en ASS, ffmpeg fixe PlayRedX et PlayResY à 384x288.

Lors de la conversion de sous-titre SRT en ASS vous pourrez tomber sur l’erreur suivante :

Invalid UTF-8 in decoded subtitles text; maybe missing -sub_charenc option

Pour résoudre se problème il suffit d’indiqué à ffmpeg l’encodage du fichier SRT, pour le français il s’agit généralement de CP1252.

max@laptop % ffmpeg -sub_charenc cp1252 -i French.srt French.ass

HS sub_charenc

Une petite note hors sujet concernant -sub_charenc. mpv peut aussi indiquer l’erreur suivante :

[ffmpeg] mov_text: Invalid UTF-8 in decoded subtitles text; maybe missing -sub_charenc option
[sub/ass] Error decoding subtitle

-sub_charenc n’est pas une option reconnue par mpv. À la place vous pouvez essayer --sub-codepage (eg. --sub-codepage=+cp1252), mais personnellement ça n’a pas fonctionné.

Décallage sous-titre ↔ son

Si le sous-titre ne colle pas parfaitement à l’image vous pouvez les décaller facilement avec ffmpeg. Dans la commande suivante j’opère un décalage de 500 millisecondes (les sous-titres étaient en retard).

max@laptop % ffmpeg -itsoffset '-0.5' -y -i titre01_subtitle_fr.ass titre01_subtitle_fr.ass