将时间片音频附加到发送到dialogflow.streamingDetectIntent

问题描述

序言

我实现了一个搜索表单(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();
    };

但是问题是:

  1. 当服务器接收到流的第二个块时,第一个块被覆盖,只有第二个块被处理以检测到Intent。 我希望将BLOB的每个块都附加到上一个块。在处理到detectIntent之前。

  2. 当前,麦克风按钮是按下,按住并说出按钮。因此,当用户按住并讲话8秒钟时,由于以3秒为间隔对记录进行切片,因此6秒钟后的音频不会在服务器上接收到。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)