conversion sous-titre HDMV/PGS (ou .sup) en .srt

Partagez vos scripts, et vos applications AutoIt.
Règles du forum
.
Répondre
serpafi
Niveau 3
Niveau 3
Messages : 40
Enregistré le : ven. 25 oct. 2019 21:19
Status : Hors ligne

conversion sous-titre HDMV/PGS (ou .sup) en .srt

#1

Message par serpafi »

Bonjour à tous,
Pour l'évolution de mon projet TAO-MKV, je cherche à convertir des sous-titres HDMV/PGS (ou .sup) en .srt .

J'arrive à extraire les horodatages de l'hexadécimale (reste la mise en forme dans le fichier .srt)

Le problème c'est d'extraire les bitmap ( 1 sous-titre vers une image" png, bmp ou jpeg...) :? :roll:

Quelqu'un pourrait m'aider à comprendre la structure des PGS et le décodage des .bmp RLE?
(extraire un bloc de sous-titre qui est en hexadecimal vers une image "png jpg etc..." qui sera lu via OCR).

L'OCR est déjà opérationnel sous ça dernière version.

J'ai fait ce code pour lire l'hexa d'un sous-titre et le rendre plus compréhensif.
#include <Array.au3>
#include <file.au3>
#include <MsgBoxConstants.au3>
#include <String.au3>

;~ INFOS ==========================================================================================================

;~ ###    http://blog.thescorpius.com/index.php/2017/07/15/presentation-graphic-stream-sup-files-bluray-subtitle-format/  ###
;~ TIMES = 0x16
;~ SIZE = 0x17
;~ PALETTE = 0x14
;~ BITMAP = 0x15
;~ END = 0x80

;~================================================================================================================

Global $ligne, $retour, $nb

Local $hFile=FileOpen("CHEMIN \subtitle.sup",$FO_BINARY)

Dim $Tableau  =  StringSplit ( FileRead($hFile) ,  "5047" ,  1 )


;~ ###############  sépare les blocs / pas obligatoire  #############
For $i = 0 to UBound($Tableau) -1
If StringLen($Tableau[$i]) = 22 Then _ArrayInsert ($Tableau,$i +1,"")
Next
;~ ##################################################################


For $i = 0 to UBound($Tableau) -1


;~ ################ remplace les lignes HEXADECIMALE par le nom de la fonction ########################################
;~ If StringMid ($Tableau[$i], 17, 2) = 15 Then $Tableau[$i] = "bitmap" ;
;~ If StringMid ($Tableau[$i], 17, 2) = 17 Then $Tableau[$i] = "taille" ;
;~ If StringMid ($Tableau[$i], 17, 2) = 14 Then $Tableau[$i] = "palette" ;
;~ If StringMid ($Tableau[$i], 17, 2) = 80 Then $Tableau[$i] = StringMid ($Tableau[$i], 17, 2) & " fin" ;
;~ ############################################################################################################


;~ ############## First Segment: PCS (0x16)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 16 Then ; pour récupérer l'horodatage et le convertir en temps lisible en texte
   horodatage($Tableau[$i] , $retour)

ConsoleWrite("First Segment: PCS (0x16)" & @CRLF & _
"Presentation Time (PTS): " & $retour & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: PCS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) &" bytes" & @CRLF & _
"Width: " & Dec( StringMid ($Tableau[$i], 23, 4)) & @CRLF & _
"Height: " & Dec( StringMid ($Tableau[$i], 27, 4)) & @CRLF & _
"Frame rate: " & StringMid ($Tableau[$i], 31, 2) & @CRLF & _
"Composition Number: " & dec(StringMid ($Tableau[$i], 33, 4)) & @CRLF & _
"Composition State: Epoch Start " & StringMid ($Tableau[$i], 37, 2) & @CRLF & _
"Palette Update Flag: " & StringMid ($Tableau[$i], 39, 2) & @CRLF & _
"Palette ID: " & StringMid ($Tableau[$i], 41, 2) & @CRLF & _
"Number of Composition Objects: " & StringMid ($Tableau[$i], 43, 2) & @CRLF & _
"Object ID: " & StringMid ($Tableau[$i], 45, 2) & @CRLF & _
"Window ID: " & StringMid ($Tableau[$i], 47, 2) & @CRLF & _
"Object Cropped Flag: " & StringMid ($Tableau[$i], 49, 4) & @CRLF & _
"Object Horizontal Position: " & Dec( StringMid ($Tableau[$i], 53, 4)) & @CRLF & _
"Object Vertical Position: " & Dec( StringMid ($Tableau[$i], 57, 4)) & @CRLF & @CRLF )

$Tableau[$i] = $retour & " --> "
EndIf

;~ ############## Second Segment: WDS (0x17)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 17 Then
ConsoleWrite("Second Segment: WDS (0x17)" & @CRLF & _
"Presentation Time (PTS): " & StringMid ($Tableau[$i], 1, 8) & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: WDS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) & " bytes" & @CRLF & _
"Number of Windows: " & StringMid ($Tableau[$i], 23, 1) & @CRLF & _
"Window ID: " & StringMid ($Tableau[$i], 25, 2) & @CRLF & _
"Window Horizontal Position: " & Dec( StringMid ($Tableau[$i], 27, 4)) & @CRLF & _
"Window Vertical Position: " & Dec( StringMid ($Tableau[$i], 31, 4)) & @CRLF & _
"Window Width: " & Dec( StringMid ($Tableau[$i], 35, 4)) & @CRLF & _
"Window Height " & Dec( StringMid ($Tableau[$i], 39, 4)) & @CRLF & _
"Window ID: " & StringMid ($Tableau[$i], 43, 2) & @CRLF & _
"Window Horizontal Position: " & Dec( StringMid ($Tableau[$i], 45, 4)) & @CRLF & _
"Window Vertical Position: " & Dec( StringMid ($Tableau[$i], 49, 4)) & @CRLF & _
"Window Width: " & Dec( StringMid ($Tableau[$i], 53, 4)) & @CRLF & _
"Window Height " & Dec( StringMid ($Tableau[$i], 47, 4)) & @CRLF & @CRLF )
EndIf


;~ ############## Third Segment: PDS (0x14)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 14 Then
ConsoleWrite("Third Segment: PDS (0x14)" & @CRLF & _
"Presentation Time (PTS): " & StringMid ($Tableau[$i], 1, 8) & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: PDS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) & " bytes" & @CRLF & _
"Palette ID: " & StringMid ($Tableau[$i], 23, 2) & @CRLF & _
"Palette Version: " & StringMid ($Tableau[$i], 25, 2) & @CRLF & _
"le reste: " & StringMid ($Tableau[$i], 27) & @CRLF & @CRLF )
EndIf



;~ ############## Fourth Segment: ODS (0x15)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 15 Then ; pour récupérer les infos sur le bitmap du sous-titre
ConsoleWrite("Fourth Segment: ODS (0x15)" & @CRLF & _
"Presentation Time (PTS): "  & StringMid ($Tableau[$i], 1, 8) & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: PDS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) & @CRLF & _
"Object ID: " & StringMid ($Tableau[$i], 23, 4) & @CRLF & _
"Object Version Number: " & StringMid ($Tableau[$i], 27, 2) & @CRLF & _
"Last in sequence flag: First and last sequence " & StringMid ($Tableau[$i], 29, 2) & @CRLF & _
"Object Data Length: " & Dec( StringMid ($Tableau[$i], 31, 6)) & @CRLF & _
"Width: " & Dec( StringMid ($Tableau[$i], 37, 4)) & @CRLF & _
"Height: " & Dec( StringMid ($Tableau[$i], 41, 4)) & @CRLF & _
"Object Data encodé en RLE: " & StringMid ($Tableau[$i], 45) & @CRLF & @CRLF )
EndIf


;~ ############## Fifth Segment: END (0x80)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 80 Then ConsoleWrite("###########################  fin du bloc #####################################################################################################" & @CRLF & @CRLF)

Next


_ArrayDisplay($Tableau)

;~ #############  création de horodatage  #################
Func horodatage($ligne, ByRef $retour)
$ligne = StringLeft ($ligne, 8) ; récuperation des hexa temps
Local $dec = Dec ($ligne)
Local $sec = ($dec/90)/1000
   $heure = Int($sec / 3600)
   $minute = Int(($sec - $heure * 3600) / 60)
   $seconde = $sec - $heure * 3600 - $minute * 60
   $MS = StringRight ( ($dec/90), 3 )
ConsoleWrite( StringFormat('%02d:%02d:%02d:%03d', $heure, $minute, $seconde,$MS) & @CRLF)
$retour = StringFormat('%02d:%02d:%02d:%03d', $heure, $minute, $seconde,$MS)
EndFunc
;~ #######################################################
Je vous mets le sous-titre que j'utilise en PJ. (changer l'extension txt en sup)
Vous pouvez prendre les vôtres aussi.
Merci d'avance
Fichiers joints
subtitle.txt
changer l'extension txt en sup
(117.39 Kio) Téléchargé 380 fois
Modifié en dernier par serpafi le lun. 15 févr. 2021 12:51, modifié 3 fois.
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: conversion sous-titre HDMV/PGS (ou .sup) en .srt

#2

Message par mikell »

Ton projet utilise déjà plusieurs logiciels tiers. Pourquoi ne pas en utiliser un pour ça ?
Les pgs, dvdsub et compagnie sont des images bmp, il faut un logiciel qui intègre de l'OCR
Les infos que tu arrives à extraire sont "standard", mais pour extraire et interpréter les data c'est une autre paire de manches
Bon courage...
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
serpafi
Niveau 3
Niveau 3
Messages : 40
Enregistré le : ven. 25 oct. 2019 21:19
Status : Hors ligne

Re: conversion sous-titre HDMV/PGS (ou .sup) en .srt

#3

Message par serpafi »

TaO-MKV utiles FFmpeg mkvmerge etc... mais aucun extrait le timestamp ou les bmp des sous-titre .sup.
C'est très particulier.
Ce que je souhaite c'est de pouvoir proposer à la communauté une solution autoit pour extraire les images et le timestamps avec l'OCR.
(sous golang, c#, c, c++, rust, etc.. il y en à quelques un) .
Pour la partie OCR, j'utilise tesseract 5.0.x de google qui est déjà opérationnel dans ma V3 sur github.

Pour la paire de manche c'est bien la le problème :')
je cherche un coup de main...
Répondre