Мы проводим некоторые эксперименты с Dialogflow и на данный момент мы полностью остановились. Мы пытаемся настроить клиент браузера, который передает потоки аудио в чанках на Dialogflow через версию узла v2beta1 пакета dialogflow npm. Мы последовали примеру, чтобы запустить его, и он прекрасно работает, когда мы используем сервер узлов для захвата звука с помощью дополнительного программного обеспечения (sox), но мы хотим транслировать из браузера. Итак, мы создали небольшой фрагмент кода, который забирает MediaStream с микрофона.
Когда событие данных запускается триггером, мы получаем чанк (массив буферов), который мы в чанках передаем на наш сервер узлов.
На сервере мы следовали этому примеру: https://cloud.google.com/dialogflow-enterprise/docs/detect-intent-stream#detect-intent-text-nodejs. Единственное, что мы отличаем, - это вместо того, чтобы использовать насос для цепочки потоков, мы просто записываем свои чанки в sessionClient.
streamingDetectIntent().write({ inputAudio: [chunk] })
Во время экспериментов мы получили несколько ошибок, которые мы решили. Но в этот момент мы передаем наши куски и получаем пустые ответы во время и в конце.
Является ли это допустимым способом передачи звука в диалоговый поток, или нам действительно нужно настроить поток? Мы не хотим использовать сервер узла в качестве записи, это должен быть браузер. У нас будет полный контроль.
Клиент
import getUserMedia from 'get-user-media-promise';
import MicrophoneStream from 'microphone-stream';
export const startVoiceStream = () => {
const microphoneStream = new MicrophoneStream();
getUserMedia({ video: false, audio: true })
.then(function(micStream) {
microphoneStream.setStream(micStream);
socket.emit('startMicStream');
state.streamingMic = true;
setTimeout(() => {
// Just closing the stream on a timer for now
socket.emit('endMicStream');
}, 5000);
})
.catch(function(error) {
console.log(error);
});
microphoneStream.on('data', function(chunk) {
if (state.streamingMic) {
socket.emit('micStreamData', chunk);
}
});
};
Серверный код намного длиннее, поэтому я думаю, что пощадлю детали, но это основные части.
const initialStreamRequest = {
session: sessions.sessionPath,
queryParams: {
session: sessions.sessionPath, //TODO: try to delete
},
queryInput: {
audioConfig: {
audioEncoding: 'AUDIO_ENCODING_LINEAR_16',
sampleRateHertz: '16000',
languageCode: 'en-US',
},
singleUtterance: false
},
};
const startRecognitionStream = socketClient => {
streamIntent = sessions.sessionClient
.streamingDetectIntent()
.on('error', error => {
console.error({ error });
socketClient.emit('streamError', error);
})
.on('data', data => {
socketClient.emit('debug', { message: 'STREAM "ON DATA"', data });
if (data.recognitionResult) {
socketClient.emit(
'playerTranscript',
data.recognitionResult.transcript,
);
console.log(
`#Intermediate transcript : ${data.recognitionResult.transcript}`,
);
} else {
socketClient.emit('streamAudioResponse', data);
}
});
streamIntent.write(initialStreamRequest);
};
socket.on('micStreamData', data => {
if (streamIntent !== null) {
stop = true;
streamIntent.write({ inputAudio: data });
}
});