Un peu de contexte
Le DCP
Actuellement, presque plus aucun cinéma ne diffuse de films en argentique : comme dans un certain nombre
d’autres domaines, le numérique est arrivé, et ce sont donc maintenant des fichiers qui sont utilisés.
Ces fichiers sont dans un format particulier, spécifique au milieu du cinéma : le
Digital Cinema Package (DCP
pour les intimes).
Ce format est peu utilisé ailleurs, car il n’est pas partièrement pratique :
Un de ces intérêts est qu’il inclut une norme de chiffrement. Cela permet de transmettre le fichier d’un film aux cinémas en avance, sans craindre une fuite sur internet. |
La norme est ouverte (disponible sur Digital Cinema Initiative), et chacun peut donc écrire son propre lecteur ou éditeur de DCPs. Dans la pratique, il n’intéresse pas beaucoup, et même VLC ne sait pas lire un DCP correctement (les fichiers audio et vidéos sont lus séparément).
Il est apparemment possible de lire les DCPs avec VLC, mais cela nécessite de le compiler à partir des sources,
en activant asdcplib (cf. le forum officiel). Je n’ai pas
vérifié si cela fonctionnait…
|
Visualiser un DCP
Tous les DCPs ne sont pas chiffrés : les publicités, les bandes annonces de l’avant-séance ne le sont généralement pas, de même que les DCPs amateurs des personnes souhaitant diffuser au cinéma. Le chiffrement est plutôt réservé aux longs métrages (en particulier pour éviter de trop faciliter le piratage).
Pour visualiser ces DCP, plusieurs solutions donc :
-
Utiliser un matériel dédié (un serveur de projection semblable à ceux que l’on peut trouver dans les cinémas).
-
Utiliser un logiciel dédié (cf. liste Wikipedia ci-dessus).
-
Recompiler VLC avec le plugin dédié (à tester).
-
Convertir le DCP dans un format plus universel, ce qui est l’objet de la suite de cet article…
Le script
Version originale
Pour la manipulation/conversion audio/vidéo, le couteau suisse, c’est ffmpeg. La conversion de
DCP n’échappe pas à cette règle. C’est ffmpeg
qui va nous permettre d’extraire les images et le son du DCP, puis de les
recombiner en un fichier MP4 (ou sous un autre format).
Rendons à Ben Edwards ce qui lui appartient : le script original de conversion m’a été soufflé sur son blog.
Ce script a le mérite d’exister, mais je lui trouve plusieurs défauts :
-
Il est conçu pour Windows.
-
Il prend trois paramètres : le fichier vidéo, le fichier audio, et le nombre d’images par secondes.
Dans les entrailles du DCP
Sans reprendre toute la norme, intéressons-nous à la structure d’un DCP publicitaire.
Un DCP, ce n’est pas un fichier mais un répertoire, comprenant :
-
Un fichier pour la vidéo, au format MKV.
-
Un fichier pour le son, également au format MKV.
-
Un ensemble de fichiers XML de métadonnées (CPL, PKL, ASSETMAP, etc.).
-
Éventuellement d’autres fichiers complémentaires (sous-titres, etc.).
-001-aud_e496f2d4-e12d-b211-85b4-003048c4f1c4.mxf (1)
-001-vid_9886d4e5-d22e-c213-85b4-003048c4f1c4.mxf (2)
ASSETMAP (3)
CPL_bcd28129-d21d-b211-8a28-003048c4f1c4.xml (3)
PKL_952db508-d21d-b211-8a28-003048c4f1c4.xml (3)
VOLINDEX (3)
1 | Fichier son. |
2 | Fichier vidéo. |
3 | Fichiers de métadonnées. |
À l’œil nu, on distingue le fichier son de la vidéo par la taille (la vidéo étant beaucoup plus grosse).
Cependant, on peut facilement faire mieux. Les informations dont on a besoin pour la conversion sont en effet disponibles dans les métadonnées du DCP.
Commençons donc par la "Composition Playlist" (ou CPL).
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<CompositionPlaylist xmlns="http://www.digicine.com/PROTO-ASDCP-CPL-20040511#">
<Id>urn:uuid:789abcde-f012-3456-789a-6543210fedcb</Id>
<AnnotationText>TITRE_DU_DCP</AnnotationText>
<IssueDate>2017-07-12T16:00:00-00:00</IssueDate>
<Issuer>BCO</Issuer>
<Creator>DCP-o-matic</Creator>
<ContentTitleText>TITRE_DU_DCP</ContentTitleText>
<ContentKind>trailer</ContentKind>
<RatingList/>
<ReelList>
<Reel>
<Id>urn:uuid:53c9b54a-d251-48a5-a429-2b654fqbgd12</Id>
<AssetList>
<MainPicture>
<Id>urn:uuid:e6396d6b-70dc-45e0-a17f-b8e6b566e776</Id> (1)
<EditRate>24 1</EditRate>
<IntrinsicDuration>1510</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>1510</Duration>
<Hash>12LedPuaf5OnbWMh8r2dzf60iAc=</Hash>
<FrameRate>24 1</FrameRate> (2)
<ScreenAspectRatio>1.85</ScreenAspectRatio>
</MainPicture>
<MainSound>
<Id>urn:uuid:e496f2d4-e12d-b211-85b4-003048c4f1c4</Id> (3)
<EditRate>24 1</EditRate>
<IntrinsicDuration>1510</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>1510</Duration>
<Hash>PEt07qtKoT0R8jShWbaqttHv57D=</Hash>
<Language>fr</Language>
</MainSound>
</AssetList>
</Reel>
</ReelList>
<!-- Informations de signature du DCP (certificats, etc.). -->
</CompositionPlaylist>
1 | Identifiant du fichier vidéo. |
2 | Nombre d’images par secondes de ce fichier (dans la pratique, presque toujours 24). |
3 | L’identifiant du fichier audio. |
Le fichier ASSETMAP
permet ensuite de faire le lien entre les identifiants trouvés dans la CPL, et le chemin
des fichiers vidéo/audio.
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<AssetMap xmlns="http://www.digicine.com/PROTO-ASDCP-AM-20040311#">
<Id>urn:uuid:789abcde-f012-3456-789a-bcdef0123456</Id>
<AnnotationText>TITRE_DU_DCP</AnnotationText>
<VolumeCount>1</VolumeCount>
<IssueDate>2017-07-12T16:00:00-00:00</IssueDate>
<Issuer>BCO</Issuer>
<Creator>DCP-o-matic</Creator>
<AssetList>
<Asset>
<Id>urn:uuid:e496f2d4-e12d-b211-85b4-003048c4f1c4</Id> (1)
<ChunkList>
<Chunk>
<Path>-001-aud_e496f2d4-e12d-b211-85b4-003048c4f1c4.mxf</Path> (2)
<VolumeIndex>1</VolumeIndex>
<Length>72526512</Length>
</Chunk>
</ChunkList>
</Asset>
<Asset>
<Id>urn:uuid:bcd28129-d21d-b211-8a28-003048c4f1c4</Id>
<ChunkList>
<Chunk>
<Path>CPL_bcd28129-d21d-b211-8a28-003048c4f1c4.xml</Path>
<VolumeIndex>1</VolumeIndex>
</Chunk>
</ChunkList>
</Asset>
<!-- etc. Une entrée par fichier constituant le DCP. -->
</AssetList>
</AssetMap>
1 | Identifiant du fichier audio (identique à celui du fichier CPL). |
2 | Chemin relatif du fichier correspondant. |
Version améliorée du script
Voici donc le script auquel on aboutit, qui n’a plus besoin que d’un unique paramètre : le chemin du DCP à convertir.
#!/bin/bash
WORK_DIR=/tmp
DCP_PATH="$1"
DCP_NAME=`basename ${DCP_PATH}`
MP4_DEST="${WORK_DIR}/${DCP_NAME}.mp4"
# Fichiers CPL and ASSETMAP.
CPL_FILE=`ls ${DCP_PATH}/*CPL*.xml`
ASSETMAP_FILE="${DCP_PATH}/ASSETMAP"
# Extraction du framerate à partir des données XML.
FRAMERATE=`xmllint --xpath "//*[local-name()='MainPicture']/*[local-name()='FrameRate']/text()" ${CPL_FILE} | sed 's/ .*//'`
# Extraction du chemin des fichiers vidéo et audio à partir des données XML.
VIDEO_ID=`xmllint --xpath "//*[local-name()='MainPicture']/*[local-name()='Id']/text()" ${CPL_FILE}`
AUDIO_ID=`xmllint --xpath "//*[local-name()='MainSound']/*[local-name()='Id']/text()" ${CPL_FILE}`
VIDEO_REL=`xmllint --xpath "//*[*[local-name()='Id']='${VIDEO_ID}']/*[local-name()='ChunkList']/*[local-name()='Chunk']/*[local-name()='Path']/text()" ${ASSETMAP_FILE}`
AUDIO_REL=`xmllint --xpath "//*[*[local-name()='Id']='${AUDIO_ID}']/*[local-name()='ChunkList']/*[local-name()='Chunk']/*[local-name()='Path']/text()" ${ASSETMAP_FILE}`
VIDEO_FILE="${DCP_PATH}/${VIDEO_REL}"
AUDIO_FILE="${DCP_PATH}/${AUDIO_REL}"
# Préparation du répertoire de travail
mkdir -p "${WORK_DIR}/jpg"
rm -rf ${WORK_DIR}/jpg/*.jpg
rm -f ${WORK_DIR}/sound.wav
# Conversion
ffmpeg -lowres 0 -i "${VIDEO_FILE}" -q:v 2 "${WORK_DIR}/jpg/image%06d.jpg"
ffmpeg -i "${AUDIO_FILE}" -y "${WORK_DIR}/sound.wav"
ffmpeg -r "${FRAMERATE}" -i "${WORK_DIR}/jpg/image%06d.jpg" -i "${WORK_DIR}/sound.wav" -ac 2 -ab 256k -crf 18 -strict -2 -y "${MP4_DEST}"
Cette version corrige améliore ainsi les deux points qui m’embêtaient dans le script original :
-
Le script est converti au format
Linux
. -
Les 3 paramètres initiaux sont automatiquement lus à partir des métadonnées du DCP.
Pour améliorer la lisibilité du cœur de l’algorithme d’extraction des informations, j’ai supprimé tout le "bruit" qui l’entourait : contrôles de validité, paramètres additionnels, etc. En l’état, le script n’est donc pas très robuste. |
Pour aller plus loin
Pour avoir une version plus robuste et complète, de ce script, quelques pistes (non exhautives) :
-
Contrôler les paramètres (l’existence du répertoire serait un minimum…)
-
Contrôler l’existence des fichiers à chaque étape (CPL, ASSETMAP, vidéo, audio, etc.)
-
Ajouter des paramètres permettant de choisir le répertoire/fichier cible.
-
Ajouter des paramètres permettant d’affiner les options
ffmpeg
de conversion (format, qualité, ratio d’image, etc.).
Outre ces paramètres purement techniques, il faut également prendre en compte plusieurs spécificités que je n’ai pas abordées :
-
Le script par du principe que le fichier CPL peut être retrouvé par son nom. C’est souvent vrai dans la pratique, mais pas systématique. Il faut donc détecter plus finement le fichier CPL pour gérer tous les cas.
-
Les fichiers vidéo et/ou audio peuvent débuter par une mire, et être décalés. Pour corriger le décalage engendré, il faut lire et interpréter les balises
EntryPoint
du fichier CPL. -
J’en oublie sans doute encore beaucoup…