Faire un screencast en Webm

Introduction

Un screencast (alias série de capture d'écran) est parfois un bon outil didactique et auto-suffisant pour montrer, de manière conviviale, comment exécuter telle ou telle action graphique. Ce n'est pas toujours le cas et, pour les tâches d'administration système, il est préferrable de recourrir à de la documentation classique (du texte).

J'ai développé un plugin Qgis dans le cadre de mon travail. Ce dernier permet d'ajouter un menu dynamique à l'interface de Qgis. L'intérêt est de manipuler les 300 couches qui composent le système d'information géographique de la structure où je travaille en quelques clics.

L'installation du plugin est une tâche assez simple. Néanmoins, j'ai souhaité m'adresser aux utilisateurs sous une forme plus originale: la vidéo (le screencast). Mon objectif était donc de créer une vidéo lisible avec un navigateur Web et que chaque géomaticien (quelquesoit son niveau) pourrait retrouver et visionner en quelques clics.

L'optimal était de déposer une vidéo dans un format lisibile par le navigateur Web que nous utilisons au travail (c'est Firefox) au sein de notre Intranet, histoire de ne pas éparpiller les ressources documentaires à droite à gauche et perdre ainsi les utilisateurs (qui n'ont pas que ça à faire de rechercher de la doc sur l'Intranet).

Le format que Firefox sait lire depuis au moins la version 3.6 est le format Webm. Il est, de plus, bien plus performant que d'autres formats libres (Theora par exemple). Toutefois, je dois composer avec plusieurs points que je ne maîtrise pas:

  • Les utilisateurs sont encore sous Firefox v3.6 (la version stable est la 11 au moment de la rédaction de cet article). Néanmoins, ça devrait aller pour lire du Theora ou du webm.
  • Le CMS qui nous sert d'Intranet est SPIP. A priori, il doit gérer la vidéo correctement.
  • Toutefois, il s'avère que tout fichier WebM uploadé n'est pas bien géré par le serveur Web (sur lequel je n'ai pas la main). En effet, ce dernier retourne un MimeType à text/plain lorsque je tente de télécharger le fichier WebM et ce ,quelquesoit le client (Firefox/wget/etc.).
  • Ce n'est pas le cas avec les fichiers OGV qui sont servis avec le bon MimeType: video/ogg.

Me voilà donc contraint de faire une capture vidéo en Ogg/Theora.

Capture

La démo se fera sous Windows XP dans une machine virtuelle. VirtualBox est le logiciel de virtualisation bureautique que j'utilise car il est bien intégré dans Debian et il est très facile à administrer même si ses possibilités sont assez limitées. De plus, il me sembe bien intégré au contexte graphique du monde de la bureautique. C'est donc une solution simple à mettre en oeuvre lorsqu'on désire émuler une machine qui fonctionne avec un système d'exploitation 100% graphique (genre Windows XP).

VirtualBox permet un affichage centré sur l'écran. Pour minimiser la taille de la vidéo, j'ai abaissé la taille de l'écran (virtuel) à 1024x768. Mon écran sous GNU/Linux a une résolution de 1680x1050. Ces données nous permettent de calculer le décalage à donner pour concentrer la capture sur le bon endroit, à savoir, l'écran de la machine virtuelle.

La capture est uniquement sur la partie vidéo. Je n'ai pas de micro au bureau !

Au final, voici une simple ligne de commande permettant une capture au format WebM de qualité ainsi que la conversion au format ogg/theora.

  ffmpeg -f x11grab -r 8 -s 1024x768 -i :0.0+328,147 -vcodec libvpx -quality best screencast.webm
  ffmpeg2theora -s 5 screencast.webm -o screencast.ogv

Chargement dans l'intranet

Un gros défaut de l'Intranet du boulot est de reposer sur SPIP... C'est un CMS assez ancien avec peu de fonctionnalité. Le gros inconvénient que j'ai déjà évoqué auparavant est surtout que le serveur Web qui l'héberge ne gère pas correctement le type MIME des vidéos, notamment WebM. J'ai donc dû me rabattre sur le format Ogg/Theora.

Après avoir créé un article dans SPIP, vous pouvez uploader votre vidéo. Ensuite, vous pouvez ajouter ce document dans l'article. Si vous utilisez l'option "embeded" de SPIP (proposée par défaut), ça va planter: SPIP traduit ça sous forme d'objet HTML. Il ne génère pas de balise vidéo. Néanmoins, comme vous avez la main pour injecter du HTML classique, voici une solution de contournement:

  <html>
  <video controls="true" width="1024" height="768">
  <source type="video/ogg" src="http://my_intranet_srv.mydomain.gouv.fr/IMG/ogv/screencast_cle6b1143.ogv" />
  </video>
  </html>

Vous devez bien entendu récupérer l'URL de votre vidéo ogv à mettre dans l'attribut src de la balise source.

Le résultat est correct: l'utilisateur qui visionne la page récupère une vidéo lisible directement dans le navigateur (pas super au niveau de la mise en page mais on n'a pas le choix).

Faire un film avec une seule image

il est possible de faire une vidéo à partir d'une seule image grâce à ffmpeg. L'inconvénient c'est que pour faire cette vidéo, vous devez dupliquer votre fichier d'image autant de fois que nécéssaire, c'est à dire, en fonction de la durée finale de la vidéo.

Par exemple, si vous voulez une vidéo qui diffuse 25 images par secondes et qui dure 2 secondes, il vous faudra théoriquement 50 images nommée image_00.png/image_01.png/image_02.png, etc.

On peut également ruser et jouer sur le framerate pour utiliser moins d'image. Par exemple, si vous indiquez que votre flux d'entrée sera composé de 1 image par seconde, vous aurez besoin d'au moins 2 images pour faire votre vidéo ou bien encore de 10 images si vous voulez que ça dure 10 secondes.

   # on va générer nos 10 images à partir du fichier titre.png:
   for f in $(seq 1 10); do cp titre.png titre_$f.png; done
   # Ensuite, on fait l'assemblage avec ffmpeg:
   ffmpeg -y -r 1 -f image2 -i titre_%d.png -r 25 test.webm

Il existe une autre commande bien plus efficace (sur une seule ligne):

    ffmpeg -y -loop_input -f image2 -i titre.png -t 10 -r 25 titre.webm

Concaténer deux vidéos

On dispose maintenant, de notre titre et de notre vidéo. Il faut les assembler. Le moyen le plus simple est d'utiliser mkvmerge du paquet mkvtoolinux:

    mkvmerge -w -o video.webm titre.webm +screencast.webm

Attention, il semble qu'il faille utiliser les mêmes framerate et même tailles pour les vidéos.

Insérer une vidéo à un endroit précis d'une autre !

Ok, on sait mettre une vidéo avant ou après une autre. Mais ce qui serait vraiment bien, c'est de la placer où on veut dans la vidéo initiale. Par exemple, pour notre screencast, on pourrait générer plusieurs pauses sous formes d'images et les insérer progressivement. L'intérêt de cette méthode serait de faciliter le travail de prise d'images: on fait tout le screencast en une passe (et on peut s'y préparer avant sérieusement en se focalisant uniquement dessus) et, enfin, on insère nos diapos aux bons endroits en post-poduction...

Prenons l'exemple d'une insertion de la vidéo titre.webm après 10 secondes:

    # On commence par casser le fichier en deux
    mkvmerge -w -o tmp_movie.webm --split "timecodes:00:00:10.00" screencast.webm
    # Cette commande génère deux fichiers: tmp_movie-001.webm et tmp_movie-002.webm
    # On peut ensuite concaténer le tout:
    mkvmerge -w -o video.webm tmp_movie-001.webm +titre.webm +tmp_movie-002.webm && rm tmp_movie*

Conclusion

Voici une méthode courte et efficace pour faire une capture d'écran depuis une machine sous GNU/Linux Debian (et autres distributions). Elle privilégie la ligne de commande qui se révèle au final bien plus simple à manier que le reste.

Des pistes d'amélioration seraient l'intégration de sous-titres (non permanents) destinés à accompagner par du texte le déroulement de la vidéo.