Comment faire pour que mon navigateur préféré me lise ou enregistre la synthèse vocale d'articles ? J'ai rapidement fait le tour de quelques solutions:

  • Fire Vox, une extension Firefox pour mal-voyants, ou CLiCk, Speak, sa déclinaison "grand public", c'est à dire juste pour lire les contenus, sans les aide à la navigations spécifiques pour les mal voyants. Je n'ai pas testé mais Aurélien Lévy par exemple semble en penser le plus grand bien;
  • utiliser un service tiers, comme par exemple sur le blog d'Aurélien;
  • utiliser mon propre service;

J'ai évidemment commencé à étudier la réalisation de la 3° solution, la plus amusante. Disposer d'un petit service installé sur un serveur et capable de convertir de l'écrit en parole.

J'ai fouillé un peu parmi les différentes solutions de synthèse vocale disponibles pour Nunux. Après quelques essais, j'ai jeté mon dévolu sur espeak et MBROLA. La qualité n'est pas parfaite, mais ça arrive à rendre un texte en français de manière à peu près compréhensible. espeack est un logiciel libre, mais ses voix françaises sont encore un peu métalliques. Ce n'est pas pour me gêner, mais pour convaincre de la viabilité de la solution, je l'ai couplé avec MBROLA, qui malheureusement n'est pas libre [1] mais propose plusieurs voix francophones de bonne qualité. Je vous renvoie à la documentation Ubuntu pour l'installation du tout, c'est très bien expliqué.

Le reste est un jeu d'enfant: trois lignes de script sur le serveur pour appeler les programmes externes et renvoyer le son, et une interface à coup de bookmarklet ou de commande Ubiquity pour appeler le service. Comme j'avais envie de tester la balise audio de Firefox 3.5, j'ai choisi de créer une commande Ubiquity qui appelle le web service en lui transmettant le texte dans l'URL. Vous pouvez évidemment préférer un appel AJAX en POST pour récupérer le son et l'enregistrer.

Hop, le service PHP:

<?php
 $temp_file = tempnam(sys_get_temp_dir(), 'speech');
 file_put_contents($temp_file, $_REQUEST["q"]);
 header("Content-Type: audio/ogg");
 if ($_REQUEST["f"]) {
   header("Content-Disposition: attachment; filename=" . ($_REQUEST["f"]) . ".ogg");
 }
 passthru("LANG=fr_FR.UTF-8 && /usr/bin/espeak -v mb/mb-fr4 -f $temp_file | /path/mbrola /path/fr4 - -.wav | oggenc -Q -");
 unlink($temp_file);

Le texte à lire est passé dans la variable q (en GET ou POST)[2], pour enregistrer le résultat envoyez-lui un nom de fichier dans f. espeak lit le texte avec une voix spéciale, mb/mb-fr4, qui génère un fichier de phonèmes pour mbrola, ce dernier lit les phonèmes sur son entrée standard, les prononce avec la voix fr4 et envoi le résultat en sortie au format wav, que je converti en OGG Vorbis pour économiser la bande passante. A vous de trouver les réglages fins et les voix qui vous plaisent le plus. La plus grande difficulté à été de penser à forcer la locale car par défaut Apache était en anglais et prononçait tous les accents (bénévole devenait bé euh accent aigu haine euh accent aigu vol)

Côté client, une commande Ubiquity d'une ligne suffit: Mise à jour du 17 mars: version un chouïa plus jolie de la commande :

CmdUtils.CreateCommand({
 name: "speak",
 description: "read the current selection",
 execute: function() {
   var document = CmdUtils.getDocument();
   var player = jQuery("#clochix_reader", document);
   if (player.length != 1) {
       CmdUtils.injectHtml('<div id="clochix_reader" style="position: fixed; top: 10px; left: 10px; z-index: 100; background-color: rgba(255, 255, 255, .5); -moz-border-radius: 10px; border: 1px solid #888;"><audio controls="true" src=""></audio><em id="clochix_reader_close">X</em></div>');
       jQuery("#clochix_reader_close", document).click(function(){jQuery("#clochix_reader", document).remove()});
   }
   jQuery("#clochix_reader AUDIO", document).attr({ src: Utils.url("http://monserve.ur/speech/speech.php?q="+CmdUtils.getSelection()).resolve('')});
   player = jQuery("#clochix_reader AUDIO", document).get(0);
   player.load();
   player.play();
 }
});

J'ai fait au plus simple, en rajoutant le lecteur dans la page avec un CmdUtils.injectHtml et en lançant la lecture automatiquement (présence de l'attribut autoplay). On pourrait aussi insérer le lecteur directement sous la sélection, en affichant les boutons permettant de contrôler la lecture (en ajoutant l'attribut controls), mais il faudrait faire ça un peu proprement, en permettant par exemple de supprimer le lecteur. Pas bien compliqué mais vu l'heure à laquelle j'ai fini, je ne suis pas entré là dedans, ça sera pour une prochaine fois.

Je vois pas mal d'applications. Par exemple avec un webmail (Couac ?) pour télé-charger les synthèses vocales de ses messages et pouvoir les écouter quand on ne peut pas avoir d'écran sous les yeux.

Pour vous donner une idée du résultat, voici le rendu du premier paragraphe de ce billet.

J'attends avec impatience vos avis.

Notes

[1] disponible uniquement sous forme binaire, avec une licence limitant ses usages. Développé par des chercheurs, obtenir l'accord de tous les contributeurs pour le libérer semble difficile, d'autant que des histoires de brevet seraient aussi de la partie

[2] mise à jour du 17 mars : si PHP est installé avec le module Suhosin, ce qui est le cas par défaut sous Debian je crois, celui-ci limite la taille des données contenues dans les variables GET. Si vous rencontrez des problèmes pour lire de longs textes, jetez un œil de ce côté