Как использовать Google Speech-to-Text, используя Blob, отправленный из браузера на сервер Nodejs - PullRequest
1 голос
/ 05 июня 2019

Я пытаюсь настроить сервер для приема аудио из клиентского браузера с помощью SocketIO, затем обработать его через Google Speech-to-Text и, наконец, ответить клиенту с текстом.

Первоначально и в идеале я хотел настроить функционирование, аналогичное инструменту на этой странице: https://cloud.google.com/speech-to-text/

Я пытался использовать getUserMedia и передавать его через SocketIO-Stream, но не мог понятькак "труба" MediaStream.

Вместо этого теперь я решил использовать MediaRecorder на стороне клиента, а затем отправлять данные в виде большого двоичного объекта (см. В этом примере ).

Затем я применяю toString('base64') для большого двоичного объекта и вызываю google-cloud / speech's client.recognize() для большого двоичного объекта.

Клиентская часть (я использую VueJS):

        new Vue({
            el: '#app',
            data: function () {
                return ({
                    msgs: [],
                    socket: null,
                    recorder: null,
                    : []
                })
            },
            mounted: function () {
                this.socket = io.connect('localhost:3000/user');
                console.log('Connected!')
                this.socket.on('text', function (text) {
                    this.msgs.push(text)
                })
            },
            methods: {
                startRecording: function () {
                    if (this.recorder && this.recorder.state == 'recording') {
                        console.log("Stopping!")
                        this.recorder.stop()
                    } else {
                        console.log("Starting!")
                        navigator.mediaDevices.getUserMedia({ audio: true, video: false })
                            .then(this.handleSuccess);
                    }
                },
                handleSuccess: function (stream) {
                    this.recorder = new MediaRecorder(stream)
                    this.recorder.start(10000)
                    this.recorder.ondataavailable = (e) => {
                        this.chunks.push(e.data)
                        console.log(e.data)
                    }
                    this.recorder.onstop = (e) => {
                        const blob = new Blob(this.chunks, { 'type': 'audio/webm; codecs=opus' })
                        this.socket.emit('audio', blob)
                    }
                }
            }
        })

Сторона сервера:

const speech = require('@google-cloud/speech');
const client = new speech.SpeechClient();

const io = require('socket.io').listen(3000)
const ss = require('socket.io-stream')

const encoding = 'LINEAR16';
const sampleRateHertz = 16000;
const languageCode = 'en-US';

const audio = {
    content: null
}

const config = {
    encoding: encoding,
    sampleRateHertz: sampleRateHertz,
    languageCode: languageCode,
}

async function main() {
    const [response] = await client.recognize({
        audio: audio,
        config: config
    })
    const transcription = response.results
        .map(result => result.alternatives[0].transcript)
        .join('\n');
    console.log(`Transcription: ${transcription}`);
}

io.of('/user').on('connection', function (socket) {
    console.log('Connection made!')
    socket.on('audio', function (data) {
        audio.content = data.toString('base64')
        main().catch(console.error)
    });
});




Журнал функции main() на стороне сервера всегда:

"Транскрипция:"

- пусто!

Он должен содержать текст из отправленного аудио.Заранее спасибо!

1 Ответ

0 голосов
/ 05 июня 2019

Ваше приложение nodejs запрашивает обработку необработанных аудиоданных, записанных в виде массива 16-разрядных целых чисел со знаком ('LINEAR16') со скоростью, равной 16 тыс. Отсчетов / с (16000).Этот вид звукового представления известен как импульсно-кодовая модуляция (PCM) по причинам, потерянным в древних знаниях телефонии.

Но большой двоичный объект, который вы отправляете из своего клиентского кода, не тот.Это медиа-объект с типом контента audio/webm; codecs=opus.Это означает, что аудиодорожка сжимается с использованием кодеков Opus и в штучной упаковке (мультиплексированных) в формате контейнера webm (Matroska, ebml) .Облачный код преобразования текста в речь пытается интерпретировать это как необработанные аудиоданные, терпит неудачу, подбрасывает руки и возвращает пустую строку транскрипции.Это похоже на попытку просмотра двоичного файла в текстовом редакторе: это просто бред.

Чтобы преобразовать текст в речь для работы с мультимедийным объектом, сначала нужно извлечь из него звук PCM.Это печально известная боль в шее для настройки на сервере;Вы должны использовать ffmpeg.В документации к тексту есть руководство по .В учебнике упоминается удаление аудио из видеофайлов.Ваш BLOB - это, по сути, видеофайл без видеодорожки, поэтому те же приемы работают.

Но вам будет намного лучше вернуться к первому подходу, используя браузер MediaStream.API JavaScript .В частности, код вашего браузера должен использовать элементы Web Audio API для перехвата необработанных аудиоданных PCM и отправки их на ваш сервер или напрямую из браузера для преобразования текста в речь.

Объяснение всего этого выходит за рамки ответа StackOverflow.Вот несколько советов. Как использовать API веб-аудио для получения необработанного звука PCM?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...