问题描述
序言
我实现了一个搜索表单(react窗口小部件),用户可以单击麦克风按钮并使用他/她的声音填写该表单。我正在使用: ReacordRTC用于录制音频。 用于NLP功能的Dialogflow API。 stream.io-stream.io-client,用于将BLOB从我的React小部件流传输到节点服务器。
当前实施
在客户端:
const captureUserMedia = () => {
setIsRecording(true);
navigator.getUserMedia(
{ audio: true },function (stream) {
const recordAudio = recordrtc(stream,{
type: 'audio',mimeType: 'audio/webm',sampleRate: 44100,recorderType: recordrtc.StereoAudioRecorder,numberOfAudioChannels: 1,desiredSampRate: 16000,});
setRecordAudio(recordAudio);
recordAudio.startRecording();
setIsRecording(true);
},function(error) {
console.error(JSON.stringify(error));
});
};
const endCaptureMedia = () => {
setIsRecording(false);
recordAudio.stopRecording(()=>{
const blob = recordAudio.getBlob();
console.log(blob);
const audioStream = ss.createStream();
ss(socket).emit('stream_audio',audioStream,{
name: '_temp/stream.wav',size: blob.size,language: 'en-US',});
ss.createBlobReadStream(blob).pipe(audioStream);
});
};
在服务器端:
ss(socket).on('stream_audio',(stream,data) => {
handleAudioStream(sessionId,stream,data);
});
handleAudioStream
export default async (sessionId,data) => {
const filename = path.basename(data.name);
stream.pipe(fs.createWriteStream(filename));
detectIntentStream(getAudioQueryRequest(sessionId),async function(response){
//callback function body
});
}
detectIntentStream
export default async (request,filename,cb) => {
const detectStream = sessionsClient.streamingDetectIntent()
.on('data',(data) => {
cb(data);
})
.on('error',(e) => {
console.log(e);
})
.on('end',() => {
console.log('on end');
});
detectStream.write(request);
await pump(
fs.createReadStream(filename),new Transform({
objectMode: true,transform: (obj,_,next) => {
next(null,{ inputAudio: obj });
},}),detectStream,);
};
问题
上面提到的当前实现工作正常,但是问题是我仅在记录停止后才在客户端收集Blob,然后开始发送它。这会导致获取识别成绩单和检测意图的延迟。 我要实现的目标是在录制过程中开始发送“ timeSliced”音频流,以便“ dialogflow”可以在用户自己讲话时启动检测意图的过程。我尝试过的
所以我尝试了以3秒为间隔对timeSlicing进行录音并将其流式传输到ondataavailable上。客户端:
const captureUserMedia = () => {
setIsRecording(true);
navigator.getUserMedia(
{ audio: true },timeSlice: 3000,ondataavailable: function(blob) {
console.log('ondataavailable');
console.log(blob);
const audioStream = ss.createStream();
ss(socket).emit('stream_audio',{
name: '_temp/stream.wav',});
ss.createBlobReadStream(blob).pipe(audioStream);
}
});
setRecordAudio(recordAudio);
recordAudio.startRecording();
setIsRecording(true);
},function(error) {
console.error(JSON.stringify(error));
});
};
const endCaptureMedia = () => {
setIsRecording(false);
recordAudio.stopRecording();
};
但是问题是:
-
当服务器接收到流的第二个块时,第一个块被覆盖,只有第二个块被处理以检测到Intent。 我希望将BLOB的每个块都附加到上一个块。在处理到detectIntent之前。
-
当前,麦克风按钮是按下,按住并说出按钮。因此,当用户按住并讲话8秒钟时,由于以3秒为间隔对记录进行切片,因此6秒钟后的音频不会在服务器上接收到。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)