使用 XMLHttpRequest 发送录制的音频数据只能工作一次

问题描述 投票:0回答:1

我正在用 javascript / python 构建一个句子识别器。过程很简单:

  • 首先使用 navigator.mediaDevices.getUserMedia 获取媒体流
  • 然后,我将 MediaRecorder 与一个名为 hark 的小型库一起使用,以在用户停止说话时自动停止录制
  • 最后我将 .ogg 格式的所有内容作为表单数据发送到服务器。

这是代码:

let recorder;
let stream;
let hk;
let chunks = [];

function recoverAudio(cks) {
    const blob = new Blob(cks, {type: "audio/ogg"});
    const http = new XMLHttpRequest();

    const fd = new FormData();
    fd.set("audio", blob);
    http.open("POST", "/api/recognize");
    http.onreadystatechange = () => {
    };
    http.send(fd);

    chunks = [];
}

function record(e) {
    chunks.push(e.data);

    console.log(e);
}

window.addEventListener("load", async () => {
    let el = document.querySelector(".footer-main-button");

    [stream, recorder] = await prepareRecorder();
    recorder.ondataavailable = record;

    hk = hark(stream);
    hk.on("stopped_speaking", () => {
        console.log("stopped speaking");
        el.style.removeProperty("color")
        setTimeout(() => {
            hk.suspend();
            recorder.stop();
            recoverAudio(chunks);
        }, 1000);  // Wait for the last chunk to be recorded
    });
    el.addEventListener("click", e => {
        if (recorder.state !== "recording") {
            recorder.start(1000);
            hk.resume();
            el.style.color = "red";
        }
    });
}, true);

在服务器端(带有烧瓶),我按如下方式读取文件:

@app.route("/api/recognize", methods=["POST"])
def recognize():
    audio = flask.request.files["audio"]
    if not audio:
        return flask.abort(400)
    audio.save("./resources/temp/audio.ogg")

但是,虽然我第一次录制某些内容,一切正常,但一旦我重新录制某些内容,文件

./resources/temp/audio.ogg
就是空的。我检查了 DevTools Network,请求包含有效的音频。更奇怪的是,如果我重新加载窗口,代码第一次可以正常工作,但之后就不行了。

有什么想法吗? (这里作为参考的是包含整个项目的 github:https://github.com/atzitz-amos/TM

javascript flask web-mediarecorder
1个回答
0
投票

我让你的代码工作正常,如下:

let recorder;
let stream;
let hk;
let chunks = [];

function recoverAudio(cks) {
    const blob = new Blob(cks, {type: "audio/ogg"});
    const http = new XMLHttpRequest();

    const fd = new FormData();
    fd.set("audio", blob);
    http.open("POST", "/api/recognize");
    http.onreadystatechange = () => {
    };
    http.send(fd);

    chunks = []; // EVEN WITH THIS AFTER FIRST RECORDING THERE IS 1 Blob WHEN START THE ENXT RECORDING (REMOVE THIS LINE OF CODE)
}

function record(e) {
    chunks.push(e.data);

    console.log(e);
}

window.addEventListener("load", async () => {
    let el = document.querySelector(".footer-main-button");

    [stream, recorder] = await prepareRecorder();
    recorder.ondataavailable = record;

    hk = hark(stream);
    hk.on("stopped_speaking", () => {
        console.log("stopped speaking");
        el.style.removeProperty("color")
        setTimeout(() => {
            hk.suspend();
            recorder.stop();
            recoverAudio(chunks);
        }, 1000);  // Wait for the last chunk to be recorded
    });
    el.addEventListener("click", e => {
        if (recorder.state !== "recording") {
            console.log(`chunks.length before recorder.start: ${chunks.length}`) // <== Second time ==> chunks.length before recorder.start: 1
            chunks = []; // RESET chunks HERE // <== THIS MADE FOLLOWING RECORDS WORKS OK
            recorder.start(1000);
            hk.resume();
            el.style.color = "red";
        }
    });
}, true);
© www.soinside.com 2019 - 2024. All rights reserved.