You must have JavaScript enabled to use the comments.

François Elie's blog - Si ça intéresse quelqu'un...

 [tags]   [archives]   [logiciels libres]   [informatique]   [programmation]   [logique]   [philosophie]   [épistémologie]   [divers]
24-10-2021

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 :)

La solution: Nerd-dictation3

Nerd-dictation est un script python qui exploite une bibliothèque open source excellente: vosk4.

  • Pas besoin de training, il reconnaît toutes les voix
  • Fonctionne offline!
  • La reconnaissance fonctionnera dans toutes les applications.
  • C'est de l'open source: pas de key

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

Notes de bas de page:

Tags: informatique divers