Objectif
Déployer un serveur web pour utiliser deepspeech
Matériels nécessaires
- Un client (Raspberry PI)
- Un serveur (Celui utilisé dans ce tutoriel : Deepspeech serveur)
Technologies utilisées
- NodeJS
- Python
Comment ça fonctionne
- J'enregistre un échantillon vocale que je veux traduire en texte.
- J'envoi le fichier enregistrer sur le serveur
- le serveur le reçoit.
- Le serveur enregistre le fichier dans un répertoire
- Le serveur traite le fichier reçu grâce au model qui a été créé préalablement.
- une réponse est retourné en JSON.
Configuration du serveur
Mon serveur ne supporte pas AVX alors je dois tout recompiler pour supporter mon système.
La base de ce tutoriel ce trouve ici : Installation et configuration de Deepspeech serveur
L'architecture des dossiers ressemble à ceci:
├── DeepSpeech └── tensorflow
Première étape
Installer toutes les dépendances
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - sudo apt-get install -y nodejs
Copier les fichiers nécessaires et qui ont été compilés dans le dossier tensorflow.
mkdir DeepSpeech/native_client/javascript/lib/binding/v0.1.0/linux-x64/ cp tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so DeepSpeech/native_client/javascript/lib/binding/v0.1.0/linux-x64/ cp tensorflow/bazel-bin/tensorflow/libtensorflow_framework.so DeepSpeech/native_client/javascript/lib/binding/v0.1.0/linux-x64/ cp tensorflow/bazel-bin/native_client/libdeepspeech_utils.so DeepSpeech/native_client/javascript/lib/binding/v0.1.0/linux-x64/ cp tensorflow/bazel-bin/native_client/libdeepspeech.so DeepSpeech/native_client/javascript/lib/binding/v0.1.0/linux-x64/
Deuxième étape
Installer Deepspeech depuis NPM,
Normalement, c'est la seule étape, cependant mon système ne supporte pas AVX.
npm install deepspeech ├── DeepSpeech ├── node_modules └── tensorflow
Maintenant, on doit copier le fichier deepspeech.node
cp node_module/deepspeech/lib/binding/v0.1.0/linux-x64/node-v46/linux-x64/node-v46/deepspeech.node DeepSpeech/native_client/javascript/lib/binding/v0.1.0/linux-x64/node-v46/
Dans le cas où vous n'avez pas la même architecture, vous pouvez vérifier à partir de ce répertoire : DeepSpeech/native_client/javascript/lib/binding/v0.1.0/ les autres versions disponibles.
Troisième étape
On peut à présent créer un serveur web pour recevoir les enregistrements.
cd DeepSpeech/native_client/javascript ls -al npm install npm install --save node-wav multer express body-parser fs nano server.js ### Ajouter ce qui suit : const express = require('express') const app = express() const port = 3000 const bodyParser = require('body-parser') const Deepspeech = require('./client') const fs = require('fs') const multer = require('multer'); const wav = require('node-wav'); app.use(bodyParser.json({ limit: '50mb' })); app.use(bodyParser.raw({ type: 'audio/wav', limit: '50mb' })); app.get('/', (request, response) => { response.send('Hello You ! Please use the route : /recognize') }) const path = '/home/tgingras/vocal/tfv1/DeepSpeech/native_client/javascript/' const storage = multer.diskStorage({ destination: function(req, file, cb){ cb(null, './') }, filename: function(req, file, cb){ cb(null, file.fieldname + '-' + Date.now() + '.wav') } }); const upload = multer({ storage: storage }); app.post('/recognize', upload.single('document'), (req, res) => { console.log(req.body) if(req.body){ const result = wav.decode(req.body); const file = 'Sample' + '-' + Date.now() + '.wav' const audio = new Buffer(req.body, 'base64').toString('binary') const _audioBuffer = new Buffer(audio, 'binary') fs.writeFile(file, _audioBuffer, {encoding: null}, function(err){ console.error(err) if(!err) Deepspeech.transcribe(path+"output_graph.pb", path+file, path+"alphabet.txt", path+"lm.binary", path+"trie", function(result, time, audioTime){ console.log(result) console.log(time) console.log(audioTime) return res.status(200).json({ 'message':'Success', 'response':result, 'totalTime':time, 'audioFileTime':audioTime }) }); }); } else if(req.file && req.file.filename) { Deepspeech.transcribe(path+"output_graph.pb", path+req.file.filename, path+"alphabet.txt", path+"lm.binary", path+"trie", function(result, time, audioTime){ console.log(result) console.log(time) console.log(audioTime) return res.status(200).json({ 'message':'Success', 'response':result, 'totalTime':time, 'audioFileTime':audioTime }) }); }else{ res.status(500).json({message: 'An error occur'}) } }) app.listen(port, (err) => { if (err) { return console.log('something bad happened', err) } console.log('server is listening on port : ' + port) }) ### Modifier la variable path pour réfléter votre chemin
Ne pas oublier de modifier la variable path pour entrer votre chemin absolu.
Le script accepte deux type de transmission.
Celui avec le form-data et celle par buffer. Je recommande d'utiliser la première (req.body) et l'example client utilise celle-là.
Quatrième étape
Démarrer le serveur web
node server.js
Si tout va bien il va écouter patiemment de recevoir un fichier audio.
Il écoute sur le port 3000 et la route doit être de type POST par exemple : POST X.X.X.X:3000/recognize
Configuration du client
Ceci est un example que j'ai fait avec jasper (Jasper Project)
J'utilise cet outil pour me faciliter la vie avec les fonctions futures qui seront adaptés à ce projet.
La partie transcribe est celle qui peut vous intéresser le plus.
import json import logging import urllib import urlparse import wave import requests from jasper import plugin #from requests_toolbelt import MultipartEncoder from requests_toolbelt.multipart import encoder class DeepspeechSTTPlugin(plugin.STTPlugin): """ Speech-To-Text implementation which relies on the Tensorflow DeepSpeech API. Customized by Tommy Gingras. """ def __init__(self, *args, **kwargs): plugin.STTPlugin.__init__(self, *args, **kwargs) self._logger = logging.getLogger(__name__) self._request_url = None self._http = requests.Session() @property def request_url(self): return self._request_url @classmethod def get_config(cls): # No need config = {} return config def transcribe(self, fp): """ Performs STT via the DeepSpeech API, transcribing an audio file and returning a string. Arguments: audio_file_path -- the path to the .wav file to be transcribed """ dataWav = fp.read() r = requests.post("http://mysuper.server.local:3000/recognize", data=dataWav, headers={'Content-Type': 'audio/wav'}) try: r.raise_for_status() except requests.exceptions.HTTPError: self._logger.critical('Request failed with http status %d', r.status_code) if r.status_code == requests.codes['forbidden']: self._logger.warning('Status 403 is probably caused by an ' + 'invalid request.') return [] r.encoding = 'utf-8' try: recognition = r.json() print(recognition) print(recognition['response']) if recognition == {}: # Response result is empty raise ValueError('Nothing has been transcribed.') except ValueError as e: self._logger.warning('Empty response: %s', e.args[0]) results = [] else: # Convert all results to uppercase results = recognition['response'].upper() self._logger.info('Transcribed: %r', results) return results @classmethod def is_available(cls): return diagnose.check_network_connection()
Comment obtenir jasper (J'utilise la version dev Jasper-dev):
git clone https://github.com/jasperproject/jasper-client.git jasper cd jasper git checkout jasper-dev