Search code examples
androidvoicerecordingyandex

YandexSpeechKit Recognizer with voice recording


Can I record sound from a microphone in a file at the same time when running YandexSpeechKit Recognizer?

There was a need for simultaneous speech recognition (using the class Recognizer) and recording sound from a devices microphone to a file. Use a standard mechanism MediaRecord is not possible, because MediaRecord and YandexSpeechKit used native methods and the same resource. It is causing the fall of some of the processes (MediaRecord or Recognizer).

I'm trying use RecognizerListener -> onSoundDataRecorded(Recognizer recognizer, byte[] bytes) code is bellow:

@Override
public void onSoundDataRecorded(Recognizer recognizer, byte[] bytes) {

    Logger.d(TAG, "onSoundDataRecorded");
    write(bytes);
}     


public void write(byte[] bytes) {

    File file = getTmpFile();
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(file, true);
        fos.write(bytes);
    } catch (IOException e1) {
        e1.printStackTrace();
    } finally {
        if(fos != null) {
            try {
                fos.flush();
                fos.close();
            } catch(IOException e) {

            }
        }
    }
}

But while the resulting file is not possible to play. Can somebody help me?

Thanks!


Solution

  • Yandex SpeechKit returns raw PCM (16 kHz mono 16 bit) data. You should add WAV header or play as PCM. For example in unix-like OS via sox:

    play -r 16000 -b 16 -c 1 -e signed-integer filename.pcm

    For adding WAV header you can use this class https://github.com/MohammadAG/Android-SoundRecorder/blob/master/src/com/mohammadag/soundrecorder/WavConverter.java with parameters

    private static final long SAMPLE_RATE = 16000; private static final int RECORDER_BPP = 16; private static final int CHANNELS = 1; private static final long BYTE_RATE = RECORDER_BPP * SAMPLE_RATE * CHANNELS/8;

            @Override
            public void onRecognizerRecordingBegin() {
                try {
                    tempFileName = getFilename();
                    os = new FileOutputStream(tempFileName, true);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onRecognizerRecordingDone() {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                int bufferSize = AudioRecord.getMinBufferSize(
                        16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
                WavConverter.copyWaveFile(tempFileName, getFilename(), bufferSize);
                deleteTempFile();
            }
    
            @Override
            public void onRecognizerSoundDataRecorded(byte[] bytes) {
                try {
                    os.write(bytes);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }