首页 > 解决方案 > 如何使用 Express.js 在有效负载中重新组装带有 MP3 blob 的分块 POST 请求?

问题描述

我正在构建一个语音到音频的网络应用程序,它接受麦克风输入,将录音转换为 MP3(使用 mic-recorder-to-mp3 NPM 包),然后将其发送到 node.js/express 服务器-用于存储并作为后续 POST 请求传递给语音到文本 API(rev.ai)。

UI 上的录音功能很好,我在标签中播放了录音,听起来不错,是全长录音:

      stopBtn.addEventListener("click", () => {

    recorder
      .stop()
      .getMp3().then(([buffer, blob]) => {

        let newBlob = new Blob(buffer);
        recordedAudio.src = URL.createObjectURL(blob);
        recordedAudio.controls=true;
        sendData(blob);
      
      }).catch((e) => {
        console.log(e);
      });
  });

  function sendData(blob) {
    let fd = new FormData();
    fd.append('audio', blob);

    fetch('/audio', {
      headers: { Accept: "application/json", "Transfer-Encoding": "chunked" },
      method: "POST", body: fd
    });
  }

现在,起初在我的服务器端快速路由中,我看到每个记录都有多个请求,并认为这是一个我可以稍后解决的错误,所以我进行了快速布尔检查以查看请求是否已经被处理并且如果是这样,只需 res.end() 回到 UI。

这一切都很好,直到我意识到只有前 4 秒的录音被保存了。这 4 秒的重新编码在服务器端保存为 MP3,并且在音乐应用程序中打开时也可以正常播放,并且在 rev.ai 中也可以正确转录,但仍然只有 4 秒。

我意识到音频 blob 正在以块的形式发送到 UI,每个块都是我看到的多个请求的一部分。因此,我开始研究如何将这些块重新组合到可以保存为 MP3 并在 rev.ai 上正确解析为音频的音频 blob 中,但到目前为止我没有尝试过任何工作。这是我最近的尝试:

app.post("/audio", async (req, res) => {
let audioBlobs = [];
let audioContent;
let filename = `narr-${Date.now()}.mp3`;
//let processed = false;

req.on('readable', async () => {
    //if(!processed){
        //processed = true;
        //let audioChunk = await req.read();
    //}
    while(null !== (audioChunk = await req.read())) {
             console.log("adding chunk")
        
        audioBlobs.push(audioChunk);
    
    }
    
});

req.on("end", () => {
    audioContent = audioBlobs.join('');

    fs.writeFile(`./audio/${filename}`, audioContent, async function(err) {
        if (err) {
            console.log("an error occurred");
            console.error(err);
            res.end();
        }

        const stream = fs.createReadStream(`./audio/${filename}`);
        let job = await client.submitJobAudioData(stream, filename, {}).then(data => {                
            waitForRevProcessing(data.id);
        }).catch(e => {
            console.log("caught an error");
            console.log(e);
        });
        res.end();
    })
});
});

该 blob 使用此代码保存在服务器端,但无法在音乐应用程序中播放,并且 rev.ai 拒绝录制,因为它不会将 blob 解释为音频文件。

我重新组装块的方式正在破坏 MP3 格式的完整性。

我认为这可能有几个原因:

我希望 Express/http 节点模块有内置的东西来自动处理这个问题,而我正在不必要地进行这个手动重组——我很惊讶 Express 中没有现成的东西来处理这个问题,但也许它不像我想象的那么普遍?

任何可以提供的帮助将不胜感激。

标签: javascriptnode.jsexpressweb-audio-apichunked-encoding

解决方案


推荐阅读