VoiceToText sous Linux
État de l'art
On croit habituellement qu'il n'y a pas de solution décente1 de reconnaissance de la parole sous Linux. Mais en cherchant bien, on peut trouver au moins cinq "solutions" fonctionnelles.
… Sans parler des solutions en version bêta depuis des lustres!
Quatre solutions qu'on oublie
Solution rudimentaire: Voicenote II, extension de Chrome
Il semble que ça puisse marcher. Pas testé, souci d'autorisation et de repéragre du micro. Inconvénient: cela ne marche que dans une fenêtre.
Une solution qui ne semble plus marcher: Android-Linux: kdeconnect + Google speech
Grâce à l'appli kdeconnect sur le mobile et kdeconnect sur l'ordi (on peut le lancer sous gnome ou xfce), il est possible d'échanger beaucoup de chose entre le pc et le mobile. En particulier, il est possible de se servir du mobile comme d'un clavier externe… et vous me voyez venir, on pourrait donc utiliser la reconnaissance vocale de Google qui tourne sur les mobiles Android. Il semble que cela a fonctionné. Mais même avec GBoard seule l'appui sur le clavier fonctionne: la reconnaissance vocale n'envoie rien. Big fail pour moi.
Une solution professionnelle
Il existe par exemmple un script2 pour exploiter une "API key" (qu'il faut acquérir auprès de Google).
DragonDictate dans VirtualBox
DragonDictate peut peut-être tourner sous Wine (mais bon c'est trop aléatoire). Cela fonctionne sous VirtualBox.
- C'est forcément moins vif qu'une application native
- Repérer le micro peut occuper
- Cela ne fonctionnera que dans le windows tournant dans la VirtualBox, et il faudra soit gérer un dossier partagé, soit le copier-coller entre les systèmes. Pas trivial pour l'utilisateur lambda.
- Et puis il faut disposer d'une version de DragonDictate, qui n'est pas très cher, mais qui change souvent :)
Comment utiliser nerd-dictation
Installation
- Si vous n'avez pas pip3 installé, il s'installe et se met à jour par (il faut au moins la version 20.3 de pip).
sudo apt install python3-pip pip3 install --upgrade pip pip3 --version
- installer vosk et xdotool
pip3 install vosk xdotool
- télécharger le code de nerd-dictation
Il faut disposer de git
sudo apt install git
git clone https://github.com/ideasman42/nerd-dictation.git cd nerd-dictation
- télécharger un modèle de reconnaissance apdaté à sa langue
sur https://alphacephei.com/vosk/models on trouve des modèles pour un nombre impressionnant de langues
On télécharge le fichier zip que l'on souhaite utiliser, on le déplie, et on renomme le répertoire produit model.
wget <url du fichier.zip> unzip <nom du fichier.zip> mv <nom du répertoire> model
Repérage du périphérique micro
Pour éviter un grand moment de solitude il faut s'assurer que le script prendra bien en compte le micro.
Pour repérer les périphériques:
pactl list sources
On repère le Nom du périphérique d'entrée (input).
Principe d'utilisation
Pour lancer la reconnaissance vocale
Remarque: la reconnaissance fonctionnera ensuite dans tous les programmes)
Voici la commande à lancer dans répertoire nerd-dictation (mon micro s'appelle alsa_input.pci-0000_00_1b.0.analog-stereo):
./nerd-dictation begin --pulse-device-name alsa_input.pci-0000_00_1b.0.analog-stereo --vosk-model-dir=./model &
Pour arrêter la reconnaissance vocale
./nerd-dictation end
Exploration
Reconnaissance de la ponctuation
Pour peu que l'on transporte le nerd-dictation.py (qui se trouve dans examples/default) dans un répertoire ~/.config/nerd-dictation, il est possible de coder dedans les suites de mots ou les mots qui doivent être remplacés (par exemple "virgule" ou "guillemets ouvrants", etc…
Reconnaissance (bonne) d'un fichier audio
Avec l'API Vosk https://itectec.com/ubuntu/ubuntu-speech-recognition-app-to-convert-mp3-to-text/
- test_text.py convertit un wav en texte brut Il faut que le wav soit en mono
Pour convertir un fichier son en av mono:
ffmpeg -i <fichier source> -ar 16000 -ac 1 file.wav
dans vosk-api/python/example il y a des scripts intéressants
- test_simple.py convertit un wav en texte dans un fichier json, avec les timecode
-test_simple.py convertit un wav en texte brut
- test_srt.py fabrique le fichier de sous-titres automatique!
Comment monter un server vosk
Le serveur que nous allons installer reçoit un fichier son et renvoie le texte dans le navigateur. On pourrait améliorer les choses, permettre d'envoyer plusieurs fichiers et renvoyer un lien vers un zip par exemple. Mais à ce stade, c'est expérimental, comme un POC, une preuve de concept.
Je n'ai pas réussi sur une raspberry-pi, j'ai monté ce serveur sur une machine avec un amd64 sous ubuntu 18.04.
prérequis
Pour que les fichiers de son soient mis en mono et normalisés, il faut disposer de ffmpeg et de sox
sudo apt install ffmpeg sox
Une ruse pour que les scripts python s'exécutent ensuite pour l'utilisateur www-data (le serveur web)
Par défaut, le comportement de pip, qui installe des modules python, est que ces modules sont disponibles seulement pour l'utilisateur qui lance pip. Si vous lancez pip en root, root pourra accéder à ces modules… et seulement lui. À force, j'ai trouvé le moyen d'installer les modules pour tous les utilisateurs d'une machine, dont www-data, le serveur web.
sudo su cd ~ umask 022 pip install what-you-like
Installation
Il faut installer vosk (via la ruse ci-dessus) et un model de reconnaissance TODO
pip3 install vosk
le script qui va bien
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <?php if (isset($_POST['submit'])) { //print_r($_POST); //print_r($_FILES); $seed=rand(1,100000); //echo "$seed<br/>"; move_uploaded_file($_FILES['file']['tmp_name'],"$seed.wav"); putenv('LANG=fr_FR.UTF-8'); $command = escapeshellcmd("./rv $seed"); $output = shell_exec($command); file_put_contents("$seed.txt",$output); exec("cd /var/www/html/vr;./substitutions $seed.txt"); echo "<pre>$output<hr/></pre>Après substitutions<pre>".file_get_contents("$seed.txt")."</pre>"; unlink("$seed.txt"); unlink("$seed.wav"); unlink("son$seed.wav"); unlink("son_norm$seed.wav"); exit; } ?> <h3>Serveur vosk de reconnaissance vocale</h3> Vous envoyez votre enregistrement (jusqu'à 500Mo). Le serveur va vérifier qu'il est en mono, le normaliser et vous renvoyer le texte.<br/> <p/> Pour un enregistrement d'une minute, patientez 30 secondes... <br/> Les enregistrements sont aussitôt détruits, et les textes ne sont pas conservés. <p/> <form method="post" enctype="multipart/form-data"> <input type="hidden" name="MAX_FILE_SIZE" value="500000000" /> <input type="file" name="file" /> <input type="submit" name="submit" value="Envoyer" /> </form> <p/> Voici le fichier de substitutions qui est utilisé: <p/> <?php $sub=file_get_contents('substitutions'); echo "<div style='width:50%;background-color:lightgreen'><pre>$sub</pre></div>"; ?>
Le script rv auquel il est fait référence, et qui exécute la reconnaissance vocale:
ffmpeg -i $1.wav -y -ar 16000 -ac 1 son$1.wav sox --norm son$1.wav son_norm$1.wav vosk-api/python/example/test_text.py son_norm$1.wav
Le fichier de post-traitement pour les substitutions
Ce fichier de substitution permet de dire la ponctuation à la voix # Autant que possible le système mettra les majuscules au déut des phrases # Remplace tous les sauts de lignes par des espaces sed -i ':z;N;s/\n/ /;bz' $1 sed -i -z '{ s/nouveau paragraphe/\n\t/g; s/point-virgule/;/g; s/ ;/;/g; s/deux points/:/g; s/ :/:/g; s/point d.interrogation/?/g; s/ ?/?/g; s/mettre un point/./g; s/ \././g; s/virgule/,/g; s/ ,/,/g; s/point d.exclamation/!/g; s/ \!/!/g; s/points de suspension/.../g s/ \.\.\./.../g; s/ouvre les guillemets/«/g; s/« /«/g; s/ferme les guillemets/»/g; s/ »/»/g; s/ouvre une parenth.se/(/g; s/( /(/g; s/ferme une parenthèse/)/g; s/ )/)/g; s/ouvre une accolade/{/g; s/{ /{/g; s/ferme une accolade/}/g; s/{ /{/g; s/ouvre les crochets/[/g; s/\[ /[/g; s/ferme les crochets/]/g; s/ \]/]/g; s/long tire./—/g; s/signe du paragraphe/§/g; s/signe du dollar/$/g; s/signe de la livre/£/g; s/signe de l.euro/€/g; s/signe de l.art aux bases/@/g; s/signe du di.se/#/g s/signe de l.ast.risque/*/g; s/signe du pourcentage/%/g; s/signe au carr./²/g; s/signe au cube/³/g}' $1 # Met une majuscule au premier mot de la ligne (même s'il y a des espaces ou des signes de tabulation avant) sed -i 's/^\([\t ]*\)\(.\)/\1\u\2/g' $1 # Met une majuscule après le ., le ? et le ! (a fortiori après ...) sed -i 's/\([\.\!\?] \)./\U&/g' $1