Benoît Courtine



    Navigation
     » Accueil
     » A propos
     » XML Feed

    Convertion d’un DCP en MP4

    24 Jul 2017 » script, cinema

    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 :

    • Il est décomposé en plusieurs fichiers (métadonnées, son, vidéo…).

    • Il pèse 10 fois plus lourd en taille qu’un fichier mp4 de qualité équivalente.

    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…
    Les listes Wikipedia des logiciels permettant d’éditer et de lire ce format sont plutôt à jour.

    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 :

    1. Il est conçu pour Windows.

    2. 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.).

    Un DCP typique
    -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).

    Le fichier 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.

    Le fichier ASSETMAP
    <?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.

    Il ne reste donc plus qu’à extraire des fichiers XML les informations dont on a besoin. On va pour cela utiliser l’outil XMLLint, et des expressions XPath.

    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.

    Script de conversion d’un DCP
    #!/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…