YandexSpeechKit Recognizer с записью голоса

Можно ли записывать звук с микрофона в файл одновременно с запущенным YandexSpeechKit Recognizer?

Возникла необходимость одновременного распознавания речи (с помощью класса Recognizer) и записи звука с микрофона устройства в файл. Использовать стандартный механизм MediaRecord не представляется возможным, так как MediaRecord и YandexSpeechKit используют нативные методы и один и тот же ресурс. Это вызывает падение некоторых процессов (MediaRecord или Recognizer).

Я пытаюсь использовать RecognizerListener -> onSoundDataRecorded (распознаватель 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) {

            }
        }
    }
}

Но пока полученный файл не возможно воспроизвести. Кто-нибудь может мне помочь?

Спасибо!


person Dmitry Sokolov    schedule 24.09.2015    source источник


Ответы (1)


Yandex SpeechKit возвращает необработанные данные PCM (16 кГц, моно, 16 бит). Вы должны добавить заголовок WAV или играть как PCM. Например, в unix-подобных ОС через sox:

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

Для добавления заголовка WAV вы можете использовать этот класс 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();
            }
        }
person anisart    schedule 28.09.2015