1

I want to link Google Speech to Text engine with my microphone.
I found this page, copied the code to my renderer.ts file (uncommented the lines with const), but when running - getting the following error, due to line 7 (const client = new speech.SpeechClient();):

And yes, I did try to run both yarn install --force (as I'm primarily using Yarn) and npm rebuild, as well as yarn add grpc, yet the problem still occurs.

renderer.ts:

const record = require('node-record-lpcm16');

// Imports the Google Cloud client library
const speech = require('@google-cloud/speech');

// Creates a client
const client = new speech.SpeechClient();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
const encoding = 'LINEAR16';
const sampleRateHertz = 16000;
const languageCode = 'en-US';

const request = {
    config: {
        encoding: encoding,
        sampleRateHertz: sampleRateHertz,
        languageCode: languageCode,
    },
    interimResults: false, // If you want interim results, set this to true
};

// Create a recognize stream
const recognizeStream = client
    .streamingRecognize(request)
    .on('error', console.error)
    .on('data', data =>
        process.stdout.write(
            data.results[0] && data.results[0].alternatives[0]
                ? `Transcription: ${data.results[0].alternatives[0].transcript}\n`
                : `\n\nReached transcription time limit, press Ctrl+C\n`
        )
    );

// Start recording and send the microphone input to the Speech API
record
    .start({
        sampleRateHertz: sampleRateHertz,
        threshold: 0,
        // Other options, see https://www.npmjs.com/package/node-record-lpcm16#options
        verbose: false,
        recordProgram: 'rec', // Try also "arecord" or "sox"
        silence: '10.0',
    })
    .on('error', console.error)
    .pipe(recognizeStream);

console.log('Listening, press Ctrl+C to stop.');

Thanks for the help!

avi12
  • 2,000
  • 5
  • 24
  • 41

2 Answers2

1

What solved my problem is the combination of a few sources.

First, installing gRPC (thanks to murgatroid99 and Nicolas Noble):

npm rebuild grpc --runtime=electron --target=4.0.3

I assume this installs the gRPC binaries so I can use them on Electron 4.0.3 (not the latest because it seems that it doesn't work on the latest)
Though since it just installs gRPC, I still need to install Electron separately, so:

yarn add -D electron@4.0.3

If you want to keep it in one line:

npm rebuild grpc --runtime=electron --target=4.0.3 && yarn add -D electron@4.0.3

Then I received this error and Googled it, though didn't find a clear answer.
Then I realized, thanks to this article (translated to English), that the module node-record-lpcm16 was just being used as a bridge from my software to SoX.
So in fact, this error is just about not being able to use the sox program from Command Line (can't spawn a process), at least not purely based on just typing sox (I could on CMD, but for some reason my application couldn't).
Hence I:

1) Changed recordProgram: 'rec' to recordProgram: 'sox' (renderer.ts)
2) Entered node_modules\node-record-lpcm16\index.js
3) Changed

case 'sox':
  var cmd = 'sox';
  var cmdArgs = [
    '-q',                     // show no progress
    '-t', 'waveaudio',        // audio type
    '-d',                     // use default recording device
    '-r', options.sampleRate, // sample rate
    '-c', options.channels,   // channels
    '-e', 'signed-integer',   // sample encoding
    '-b', '16',               // precision (bits)
    '-',                      // pipe
    // end on silence
    'silence', '1', '0.1', options.thresholdStart || options.threshold + '%',
    '1', options.silence, options.thresholdEnd || options.threshold + '%'
  ];
  break

to

case 'sox':
  var cmd = 'C:\\Program Files (x86)\\sox-14-4-2\\sox.exe';
  var cmdArgs = [ // ^ SPECIFYING FULL PATH
    '-q',                     // show no progress
    '-t', 'waveaudio',        // audio type
    '-d',                     // use default recording device
    '-r', options.sampleRate, // sample rate
    '-c', options.channels,   // channels
    '-e', 'signed-integer',   // sample encoding
    '-b', '16',               // precision (bits)
    '-',                      // pipe
    // end on silence
    'silence', '1', '0.1', options.thresholdStart || options.threshold + '%',
    '1', options.silence, options.thresholdEnd || options.threshold + '%'
  ];
  break

Then, turns out that without adding an extra bit that's mentioned in the aforementioned article,, recording the microphone wouldn't work, so:

case 'sox':
  var cmd = 'C:\\Program Files (x86)\\sox-14-4-2\\sox.exe';
  var cmdArgs = [
    '-q',                     // show no progress
    '-t', 'waveaudio',        // audio type
    '-d',                     // use default recording device
    '-r', options.sampleRate, // sample rate
    '-c', options.channels,   // channels
    '-e', 'signed-integer',   // sample encoding
    '-t', 'raw', // Added
    '-b', '16',               // precision (bits)
    '-',                      // pipe
    // end on silence
    'silence', '1', '0.1', options.thresholdStart || options.threshold + '%',
    '1', options.silence, options.thresholdEnd || options.threshold + '%'
  ];
  break

If you're getting Google Cloud credential authentication issues, refer to this answer

And these resolved my problems of being able to record!

Then I had a problem that Google limits the audio stream to 65 seconds, so via the stack trace lines, I traced down the lines that caused the problem & commented those lines, until I reached the 2nd possible output in renderer.ts (output Reached transcription time limit, press Ctrl+C), so I just wrapped the variable & record functions inside a function and called the function recursively, like so:

function startRecording() {
    // Create a recognize stream
    const recognizeStream = client
        .streamingRecognize(request)
        .on('error', console.error)
        .on('data', data => {
            if (data.results[0] && data.results[0].alternatives[0]) {
                console.log(`Transcription: ${data.results[0].alternatives[0].transcript}\n`);
            } else {
                console.log(`\n\nReached transcription time limit, press Ctrl+C\n`);
                startRecording();
            }
        });

    // Start recording and send the microphone input to the Speech API
    record
        .start({
            sampleRateHertz: sampleRateHertz,
            threshold: 0,
            // Other options, see https://www.npmjs.com/package/node-record-lpcm16#options
            verbose: false,
            recordProgram: 'sox', // Try also "arecord" or "sox"
            silence: '10.0',
        })
        .on('error', console.error)
        .pipe(recognizeStream);
}

startRecording();

And this solution seems to solve that problem!

avi12
  • 2,000
  • 5
  • 24
  • 41
  • This solution was only relevant at the time. These days, you'll need to find a different solution that's using the latest version of Electron (11.1.1 by the time of commenting), and the aforementioned `node-record-lpcm16`'s `index.js` has a modern JS code, thus my solution is no longer relevant for today. – avi12 Jan 10 '21 at 13:20
0

In order to use this library on Electron you have to add extra installation arguments to specifically install for Electron. Electron has generic instructions for using native Node modules.

For gRPC in particular, with the version of Electron you have, you should be able to get it by running

npm rebuild --runtime=electron --target=4.0.0

A word of warning for Electron 4 in particular: Due to a breaking change introduced in Electron 4.0.4, grpc will not work with that version. It will still work with previous versions of Electron 4.

murgatroid99
  • 19,007
  • 10
  • 60
  • 95
  • That's the breaking change in Electron 4.0.4 I warned about in my last paragraph. As I said, the library will not work with that specific version. – murgatroid99 Mar 07 '19 at 16:09
  • So what can I do to fix this? – avi12 Mar 07 '19 at 17:47
  • Rollback to electron 4.0.3 in your package.json by using neither ^ or ~ as a marker. – Nicolas Noble Mar 07 '19 at 18:10
  • After iteratively attempting to install `grpc` and then attempting to install `electron` specifically in version `4.0.3`, I had successfully received a different error related to Google Cloud Authentication. After [resolving this](https://stackoverflow.com/questions/42043611), my only error is [this](https://i.imgur.com/DddQPWk.png) – avi12 Mar 08 '19 at 07:10