cClaude.rocks ☕ Le blog

L'informatique et les nouvelles technologies

Menu
Ce billet a été édité le : 2020-04-13

Lorsqu’on édite les textes sur kdenlive il est très facile de faire d’effacer des caractères lors de certaines manipulations. De manière générale, l’éditeur de texte n’est pas super conviviale, le curseur étant peu visible. De plus suivant les effets que l’on cherche à produire, le texte peut être difficilement lisible, on se retrouve avec du noir sur noir par exemple.

L’idée est donc la suivante :

Extraire le texte des fichiers projets de kdenlive.

Les fichiers projets de kdenlive sont stockés sur le disque sous la forme d’un fichier XML nommé « exemple.kdenlive ».

Pour gérer, les fichiers XML, je vais utiliser ici xpath en essayant de décrire la procédure étape par étape.

Prérequis

Il faut tout d’abord un outil permettant de manipuler le XML et pour cela j’ai choisi la solution basée sur perl. Une solution robuste et bien intégrée au système. Sur les systèmes basés sur Debian (comme Ubuntu et Mint) installe la commande xpath comme suit :

sudo apt update && sudo apt install -y libxml-xpath-perl

Configuration de votre environnement de test

Pour suivre ce tutoriel sur votre propre machine, dans un terminal affecter à la variable FILE le nom d’un fichier projet kdenlive contenant du texte.

FILE=~/kdenlive/mes-projets/mon-film.kdenlive

Prenez quelques minutes pour regarder la structure de ce fichier dans l’éditeur de votre choix.

Analyse des besoins

On va chercher à récupérer le texte et on s’aperçoit qu’il est en fait dans un code XML « encodé » dans le XML de base.

Il va donc valoir isoler le code XML embarqué, le reformater correctement, puis extraire le texte.

Pour extraire le code XML embarqué, on va isoler les éléments de type property avec l’attribut name valant xmldata.

Cela s’obtient comme suit :

xpath -e '//property[@name="xmldata"]' "${FILE}"

Comme on ne veut que le contenu de l’élément on peut même écrire :

xpath -e '//property[@name="xmldata"]/text()' "${FILE}"

Pour convertir ce XML encodé, en XML valide, il faut ajouter une entête, et un élément racine.

La conversion est très simple à faire avec la commande sed :

xpath -e '//property[@name="xmldata"]/text()' "${FILE}" | sed -e 's,&lt;,<,g'

Pour ajouter un entête et un élément racine, on peut utiliser l’astuce suivante, basée sur cat :

cat <<EOF
<?xml version='1.0' encoding='utf-8'?>
<root>
$(
  xpath -e '//property[@name="xmldata"]/text()' "${FILE}" | sed -e 's,&lt;,<,g'
  )
</root>
EOF

Maintenant on a un nouveau flux XML valide que l’on va pouvoir utiliser. Dans ce flux on cherche à obtenir le contenu de l’élément content qui lui-même se trouve dans l’élément item de l’élément kdenlivetitle.

Cela s’écrit comme suit :

xpath -e '//kdenlivetitle/item/content'

Et donc on a une première solution (quick and dirty) qui s’écrit comme cela :

cat <<EOF | xpath -e '//kdenlivetitle/item/content/text()'
<?xml version='1.0' encoding='utf-8'?>
<root>
$(
  xpath -e '//property[@name="xmldata"]' "${FILE}" | sed -e 's,</property>,,g' | sed -e 's,<property name="xmldata">,,g' | sed -e 's,&lt;,<,g'
  )
</root>
EOF

On peut améliorer le résultat avec un peu de ménage :

cat <<EOF | xpath -q -e '//kdenlivetitle/item/content/text()'
<?xml version='1.0' encoding='utf-8'?>
<root>
$(
  xpath -q -e '//property[@name="xmldata"]/text()' "${FILE}" | sed -e 's,&lt;,<,g'
  )
</root>
EOF

On a plus ou moins ce qu’on souhaitait, mais si on veut corriger un texte, cela risque de ne pas être simple de le retrouver dans kdenlive.

On a perdu l’ordre et le nom des zones de texte. L’ordre n’est pas si important, puis que dans kdenlive il est basé sur le nom du clip. Au final seul le nom du clip est nécessaire.

Pour énumérer les noms des éléments contenant du texte on peut commencer par :

xpath -q -e '//property[@name="kdenlive:clipname"]/text()' "${FILE}"

Cependant on ne veut que les éléments répondant à property[@name="xmldata"], on doit donc adapter le code comme suit :

xpath -q -e '//property[@name="xmldata"]/../property[@name="kdenlive:clipname"]/text()' "${FILE}"

Ici .. permet de revenir à l’élément parent pour donner une nouvelle condition.

OK, maintenant on va revenir un peu en mode bash pour pouvoir associer ces deux solutions, puisque l’on souhaite associer le nom du clip au texte correspondant :

Dans un premier temps, il faut réécrire la ligne précédente comme suit :

while read -r clipname ; do
  echo "> ${clipname} :"
done < <(
  xpath -q -e '//property[@name="xmldata"]/../property[@name="kdenlive:clipname"]/text()' "${FILE}"
  )

Presque rien n’a changé, juste un peu de présentation ajoutée au passage.

Il ne reste plus qu’à rechercher les éléments du fichier ayant un élément property avec attribut name valant kdenlive:clipname et un contenu correspondant au nom du clip courant and .="${clipname}".

Il y a quelque problème de guillemets à régler au passage…

Et finalement :

On peut mettre tout cela dans une fonction, et on obtient :

function extract_text {
  local file="$1"

  while read -r clipname ; do
    echo
    echo "> ${clipname} :"
    echo

    cat <<EOF | xpath -q -e '//kdenlivetitle/item/content/text()'
<?xml version='1.0' encoding='utf-8'?>
<root>
$(
  xpath -q -e "//property[@name=\"kdenlive:clipname\" and .=\"${clipname}\" ]/../property[@name=\"xmldata\"]/text()" "${file}" | sed -e 's,&lt;,<,g'
  )
</root>
EOF

  done < <( xpath -q -e '//property[@name="xmldata"]/../property[@name="kdenlive:clipname"]/text()' "${file}" | sort )
}

Que l’on peut utiliser comme suit :

extract_text ~/kdenlive/mes-projets/mon-film.kdenlive >textes-de-la-vidéo.txt

C’est cool, non ?

Limitations

On ne peut pas vraiment utiliser la même méthode pour réinjecter le texte, cela casserait la présentation. Sinon, il faut tenir compte de la géométrie du projet, de la longueur du texte, de la géométrie de la police de caractère et ce pour chaque caractère.

ᦿ


ℹ 2006 - 2020 | 🕸 Retour à l'accueil du domaine | 🏡 Retour à l'accueil du blog