带有录音功能的 Yandex SpeechKit 识别器

YandexSpeechKit Recognizer with voice recording

我可以在 运行 YandexSpeechKit Recognizer 的同时将麦克风的声音录制到文件中吗?

需要同时进行语音识别(使用 class 识别器)并将设备麦克风的声音录制到文件中。使用标准机制 MediaRecord 是不可能的,因为 MediaRecord 和 YandexSpeechKit 使用本机方法和相同的资源。它导致某些进程(MediaRecord 或 Recognizer)崩溃。

我正在尝试使用 RecognizerListener -> onSoundDataRecorded(Recognizer recognizer, byte[] bytes) 代码如下:

@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) {

            }
        }
    }
}

但是生成的文件无法播放。 有人可以帮我吗?

谢谢!

Yandex SpeechKit returns 原始 PCM(16 kHz 单声道 16 位)数据。您应该添加 WAV header 或作为 PCM 播放。例如在 unix-like OS 通过 sox:

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

要添加 WAV header,您可以使用此 class https://github.com/MohammadAG/Android-SoundRecorder/blob/master/src/com/mohammadag/soundrecorder/WavConverter.java 和参数

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();
            }
        }