From 89620bc448c3548c8e12591cc24f7a543a8c7a0b Mon Sep 17 00:00:00 2001 From: bhargav-ak Date: Sun, 9 Sep 2018 00:18:44 +0530 Subject: [PATCH 1/2] Transcribing longer audio clips Prerequisites ------------- ~/Deepspeech$ sudo apt install virtualenv ~/Deepspeech$ cd examples/vad_transcriber ~/Deepspeech/examples/vad_transcriber$ virtualenv -p python3 venv ~/Deepspeech/examples/vad_transcriber$ source venv/bin/activate (venv) ~/Deepspeech/examples/vad_transcriber$ pip3 install -r requirements.txt Command line tool ----------------- The command line tool processes a wav file of any duration and returns a trancript which will the saved in the same directory as the input audio file. (venv) ~/Deepspeech/examples/vad_transcriber $ python3 audioTranscript_cmd.py --aggressive 1 --audio ./audio/guido-van-rossum.wav --model ./models/0.2.0/ Minimalistic GUI ---------------- The GUI tool does the same job as the CLI tool. The VAD is fixed at an aggressiveness of 1. The output is displayed in the transcription window and saved into the directory as the input audio file as well. (venv) ~/Deepspeech/examples/vad_transcriber $ python3 audioTranscript_gui.py Changes(v1): 1. Using Deepspeech python module instead of subprocess 2. Moved VAD code to a module 3. Moved all files to bin/ and renamed README.md to Audio_Transcription.md Changes(v2): Renamed files Changes (v2.1): 1. Refactoring between CMD and GUI code 2. Documenting pre-requisites with a virtualenv 3. Loading model only once per long wav file 4. CMD and GUI tool do the same job, perform VAD and consolidate the output. 5. Chunks are not saved in the disk. Using a numpy interger array to store them. Changes (v2.2): 1. Argparse module for command line arguments 2. Everything in virtualenv, with a requirements.txt 3. Older APIs aligned with 0.2.0 release 4. Moved all files into examples/vad_transcriber Changes (v2.3) 1. Updated requirements.txt --- doc/audioTranscript.png | Bin 0 -> 20644 bytes .../vad_transcriber/audioTranscript_cmd.py | 67 +++++ .../vad_transcriber/audioTranscript_gui.py | 257 ++++++++++++++++++ examples/vad_transcriber/requirements.txt | 3 + examples/vad_transcriber/wavSplit.py | 134 +++++++++ examples/vad_transcriber/wavTranscriber.py | 103 +++++++ examples/vad_transcriber/wavTranscription.md | 61 +++++ 7 files changed, 625 insertions(+) create mode 100644 doc/audioTranscript.png create mode 100644 examples/vad_transcriber/audioTranscript_cmd.py create mode 100644 examples/vad_transcriber/audioTranscript_gui.py create mode 100644 examples/vad_transcriber/requirements.txt create mode 100644 examples/vad_transcriber/wavSplit.py create mode 100644 examples/vad_transcriber/wavTranscriber.py create mode 100644 examples/vad_transcriber/wavTranscription.md diff --git a/doc/audioTranscript.png b/doc/audioTranscript.png new file mode 100644 index 0000000000000000000000000000000000000000..ef4a0ac62f7b344b160fbc1776fa3f6c2f063508 GIT binary patch literal 20644 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 0.9 * ring_buffer.maxlen: + triggered = True + # We want to yield all the audio we see from now until + # we are NOTTRIGGERED, but we have to start with the + # audio that's already in the ring buffer. + for f, s in ring_buffer: + voiced_frames.append(f) + ring_buffer.clear() + else: + # We're in the TRIGGERED state, so collect the audio data + # and add it to the ring buffer. + voiced_frames.append(frame) + ring_buffer.append((frame, is_speech)) + num_unvoiced = len([f for f, speech in ring_buffer if not speech]) + # If more than 90% of the frames in the ring buffer are + # unvoiced, then enter NOTTRIGGERED and yield whatever + # audio we've collected. + if num_unvoiced > 0.9 * ring_buffer.maxlen: + triggered = False + yield b''.join([f.bytes for f in voiced_frames]) + ring_buffer.clear() + voiced_frames = [] + if triggered: + pass + # If we have any leftover voiced audio when we run out of input, + # yield it. + if voiced_frames: + yield b''.join([f.bytes for f in voiced_frames]) + diff --git a/examples/vad_transcriber/wavTranscriber.py b/examples/vad_transcriber/wavTranscriber.py new file mode 100644 index 00000000..5fdcb394 --- /dev/null +++ b/examples/vad_transcriber/wavTranscriber.py @@ -0,0 +1,103 @@ +import glob +import webrtcvad +import logging +import wavSplit +from deepspeech import Model +from timeit import default_timer as timer + +''' +Load the pre-trained model into the memory +@param models: Output Grapgh Protocol Buffer file +@param alphabet: Alphabet.txt file +@param lm: Language model file +@param trie: Trie file + +@Retval +Returns a list [DeepSpeech Object, Model Load Time, LM Load Time] +''' +def load_model(models, alphabet, lm, trie): + N_FEATURES = 26 + N_CONTEXT = 9 + BEAM_WIDTH = 500 + LM_WEIGHT = 1.75 + VALID_WORD_COUNT_WEIGHT = 1.00 + + model_load_start = timer() + ds = Model(models, N_FEATURES, N_CONTEXT, alphabet, BEAM_WIDTH) + model_load_end = timer() - model_load_start + logging.debug("Loaded model in %0.3fs." % (model_load_end)) + + lm_load_start = timer() + ds.enableDecoderWithLM(alphabet, lm, trie, LM_WEIGHT, VALID_WORD_COUNT_WEIGHT) + lm_load_end = timer() - lm_load_start + logging.debug('Loaded language model in %0.3fs.' % (lm_load_end)) + + return [ds, model_load_end, lm_load_end] + +''' +Run Inference on input audio file +@param ds: Deepspeech object +@param audio: Input audio for running inference on +@param fs: Sample rate of the input audio file + +@Retval: +Returns a list [Inference, Inference Time, Audio Length] + +''' +def stt(ds, audio, fs): + inference_time = 0.0 + audio_length = len(audio) * (1 / 16000) + + # Run Deepspeech + logging.debug('Running inference...') + inference_start = timer() + output = ds.stt(audio, fs) + inference_end = timer() - inference_start + inference_time += inference_end + logging.debug('Inference took %0.3fs for %0.3fs audio file.' % (inference_end, audio_length)) + + return [output, inference_time] + +''' +Resolve directory path for the models and fetch each of them. +@param dirName: Path to the directory containing pre-trained models + +@Retval: +Retunns a tuple containing each of the model files (pb, alphabet, lm and trie) +''' +def resolve_models(dirName): + pb = glob.glob(dirName + "/*.pb")[0] + logging.debug("Found Model: %s" % pb) + + alphabet = glob.glob(dirName + "/alphabet.txt")[0] + logging.debug("Found Alphabet: %s" % alphabet) + + lm = glob.glob(dirName + "/lm.binary")[0] + trie = glob.glob(dirName + "/trie")[0] + logging.debug("Found Language Model: %s" % lm) + logging.debug("Found Trie: %s" % trie) + + return pb, alphabet, lm, trie + +''' +Generate VAD segments. Filters out non-voiced audio frames. +@param waveFile: Input wav file to run VAD on.0 + +@Retval: +Returns tuple of + segments: a bytearray of multiple smaller audio frames + (The longer audio split into mutiple smaller one's) + sample_rate: Sample rate of the input audio file + audio_length: Duraton of the input audio file + +''' +def vad_segment_generator(wavFile, aggressiveness): + logging.debug("Caught the wav file @: %s" % (wavFile)) + audio, sample_rate, audio_length = wavSplit.read_wave(wavFile) + assert sample_rate == 16000, "Only 16000Hz input WAV files are supported for now!" + vad = webrtcvad.Vad(int(aggressiveness)) + frames = wavSplit.frame_generator(30, audio, sample_rate) + frames = list(frames) + segments = wavSplit.vad_collector(sample_rate, 30, 300, vad, frames) + + return segments, sample_rate, audio_length diff --git a/examples/vad_transcriber/wavTranscription.md b/examples/vad_transcriber/wavTranscription.md new file mode 100644 index 00000000..e34c1c75 --- /dev/null +++ b/examples/vad_transcriber/wavTranscription.md @@ -0,0 +1,61 @@ +## Transcribing longer audio clips + +The Command and GUI tools perform transcription on long wav files. +They take in a wav file of any duration, use the WebRTC Voice Activity Detector (VAD) +to split it into smaller chunks and finally save a consolidated transcript. + +### 0. Prerequisites +Setup your environment + +``` +~/Deepspeech$ sudo apt install virtualenv +~/Deepspeech$ cd examples/vad_transcriber +~/Deepspeech/examples/vad_transcriber$ virtualenv -p python3 venv +~/Deepspeech/examples/vad_transcriber$ source venv/bin/activate +(venv) ~/Deepspeech/examples/vad_transcriber$ pip3 install -r requirements.txt +``` + +### 1. Command line tool + +The command line tool processes a wav file of any duration and returns a trancript +which will the saved in the same directory as the input audio file. + +The command line tool gives you control over the aggressiveness of the VAD. +Set the aggressiveness mode, to an integer between 0 and 3. +0 being the least aggressive about filtering out non-speech, 3 is the most aggressive. + +``` +(venv) ~/Deepspeech/examples/vad_transcriber +$ python3 audioTranscript_cmd.py --aggressive 1 --audio ./audio/guido-van-rossum.wav --model ./models/0.2.0/ + + +Filename Duration(s) Inference Time(s) Model Load Time(s) LM Load Time(s) +sample_rec.wav 13.710 20.797 5.593 17.742 + +``` + +### 2. Minimalistic GUI + +The GUI tool does the same job as the CLI tool. The VAD is fixed at an aggressiveness of 1. +The output is displayed in the transcription window and saved into the directory as the input +audio file as well. + +``` +(venv) ~/Deepspeech/examples/vad_transcriber +$ python3 audioTranscript_gui.py + +``` + +![Deepspeech Transcriber](../../doc/audioTranscript.png) + + +#### 2.1. Sporadic failures in pyqt +Some systems have encountered **_Cannot mix incompatible Qt library with this with this library_** issue. +In such a scenario, the GUI tool will not work. The following steps is known to have solved the issue in most cases +``` +(venv) ~/Deepspeech/examples/vad_transcriber$ pip3 uninstall pyqt5 +(venv) ~/Deepspeech/examples/vad_transcriber$ sudo apt install python3-pyqt5 canberra-gtk-module +(venv) ~/Deepspeech/examples/vad_transcriber$ export PYTHONPATH=/usr/lib/python3/dist-packages/ +(venv) ~/Deepspeech/examples/vad_transcriber$ python3 audioTranscript_gui.py + +``` \ No newline at end of file From d1d559355ab71b763eefaa5318dfbd10a585438b Mon Sep 17 00:00:00 2001 From: Alexandre Lissy Date: Wed, 3 Oct 2018 10:19:25 +0200 Subject: [PATCH 2/2] Remove WarpCTC --- DeepSpeech.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/DeepSpeech.py b/DeepSpeech.py index 4b989f18..01e80996 100755 --- a/DeepSpeech.py +++ b/DeepSpeech.py @@ -67,8 +67,6 @@ def create_flags(): tf.app.flags.DEFINE_boolean ('test', True, 'whether to test the network') tf.app.flags.DEFINE_integer ('epoch', 75, 'target epoch to train - if negative, the absolute number of additional epochs will be trained') - tf.app.flags.DEFINE_boolean ('use_warpctc', False, 'whether to use GPU bound Warp-CTC') - tf.app.flags.DEFINE_float ('dropout_rate', 0.05, 'dropout rate for feedforward layers') tf.app.flags.DEFINE_float ('dropout_rate2', -1.0, 'dropout rate for layer 2 - defaults to dropout_rate') tf.app.flags.DEFINE_float ('dropout_rate3', -1.0, 'dropout rate for layer 3 - defaults to dropout_rate') @@ -519,11 +517,8 @@ def calculate_mean_edit_distance_and_loss(model_feeder, tower, dropout, reuse): # Calculate the logits of the batch using BiRNN logits, _ = BiRNN(batch_x, batch_seq_len, dropout, reuse) - # Compute the CTC loss using either TensorFlow's `ctc_loss` or Baidu's `warp_ctc_loss`. - if FLAGS.use_warpctc: - total_loss = tf.contrib.warpctc.warp_ctc_loss(labels=batch_y, inputs=logits, sequence_length=batch_seq_len) - else: - total_loss = tf.nn.ctc_loss(labels=batch_y, inputs=logits, sequence_length=batch_seq_len) + # Compute the CTC loss using TensorFlow's `ctc_loss` + total_loss = tf.nn.ctc_loss(labels=batch_y, inputs=logits, sequence_length=batch_seq_len) # Calculate the average loss across the batch avg_loss = tf.reduce_mean(total_loss)