目前正在try 将一些录制的音频从浏览器发送到Actix-Web服务器,并try 将其保存到磁盘,从而从通用媒体播放器中生成可播放的曲目.我发现这很难做到,特别是因为我以前从未与媒体合作过.我所做的一切都基于一些谷歌搜索和一些GPT的结合. 问题:文件似乎确实已保存到磁盘上.这是一个非零大小的文件,但似乎无法在SLC媒体播放器中播放. 将录音发送到Actix-Web服务器的脚本:

const blob = new Blob(chunks, { type: "audio/mp3" });
  const audioURL = URL.createObjectURL(blob);
  const audio = new Audio(audioURL);

  // create a button
  let button = document.createElement("BUTTON");
  // creating text to be
  //displayed on button
  let text = document.createTextNode("Play recording ", audio_rec_num + 1);
  button.appendChild(text);
  button.setAttribute("num", audio_rec_num);

  audio_rec_num++;
  document.body.appendChild(button);
  button.addEventListener("click", function () {
    let num = Number(button.getAttribute("num"));

    // audio_chunks[num].play();

    // Create FormData object to send the audio data
    const formData = new FormData();
    formData.append("audio", blob, "recorded_audio.mp3");

    // Send the audio data to the server using fetch or XMLHttpRequest
    fetch("http://127.0.0.1:8080/track_sample", {
      method: "POST",
      body: formData,
    })
      .then((response) => {
        if (response.ok) {
          console.log("Audio sent successfully");
        } else {
          console.error("Failed to send audio");
        }
      })
      .catch((error) => {
        console.error("Error sending audio: ", error);
      });
  });

接收数据的处理程序:

async fn track_sampler(req_body: web::Bytes) -> impl Responder {
println!("track sampler hit");
let audio_data = req_body.to_vec();
println!("Received audio data with length: {}", audio_data.len());

// Save the audio data to a WAV file
let file_path = "received_audio.mp3";
let mut file = match File::create(file_path) {
    Ok(file) => file,
    Err(_) => return HttpResponse::InternalServerError().finish(),
};

// Write the bytes of the audio file to the file on disk
if let Err(_) = file.write_all(&audio_data) {
    return HttpResponse::InternalServerError().finish();
}
println!("done");
// Return a success response
HttpResponse::Ok().body("Audio file uploaded successfully")

}

我只需要一些明确的指针就能实现这一点.我不一定需要代码,但这也可能非常有帮助.我做错了什么?我知道我保存得不正确,但如何"正确"呢?

注意:我不希望直接从JS将音频保存到磁盘

推荐答案

JavaScript FormData类型将正文编码为"multipart/form-data".它不仅仅是您的原始文件字节.要在Actix-Web处理程序中解码此正文,您需要使用actix-multipart.

使用它的简单方法是在反映表单数据的 struct 上使用派生宏.

  • 使用actix_multipart::form::bytes::Bytes将字节存储在内存中:

    use actix_multipart::form::MultipartForm;
    use actix_multipart::form::bytes::Bytes;
    
    #[derive(MultipartForm)]
    struct TrackUpload {
        audio: Bytes,
    }
    
  • 或者使用actix_multipart::form::tempfile::TempFile将其立即存储到磁盘:

    use actix_multipart::form::MultipartForm;
    use actix_multipart::form::tempfile::TempFile;
    
    #[derive(MultipartForm)]
    struct TrackUpload {
        audio: TempFile,
    }
    
  • 有关更多选项,请参阅#[derive(MultipartForm)]上的文档.

然后在您的处理程序中使用它,如下所示:

use actix_multipart::form::MultipartForm;

async fn track_sampler(MultipartForm(upload): MultipartForm<TrackUpload>) -> impl Responder {
    // use upload.audio
}

如果需要,还可以 Select 接受actix_multipart::Multipart到您的处理程序中,以比上述技术更手动地处理字段和内容流传输.

Javascript相关问答推荐

TestCafe预计文本等于以下内容之一

想要检测字符串中的所有单词

为什么在react js中没有调用加载器函数?

我的YouTube视频没有以html形式显示,以获取免费加密信号

我的glb文件没有加载到我的three.js文件中

我应该在redux reducer中调用其他reducer函数吗?

按钮未放置在html dis位置

过滤对象数组并动态将属性放入新数组

为什么我的includes声明需要整个字符串?

防止用户在selectizeInput中取消 Select 选项

将状态向下传递给映射的子元素

Redux查询多个数据库Api reducerPath&

自定义高图中的x轴标签序列

无法访问Vue 3深度监视器中对象数组的特定对象值'

如何在ASP.NET项目中使用Google Chart API JavaScript将二次轴线值格式化为百分比

WP Bootstrap NavWaker:下拉菜单一次打开所有下拉菜单

在开发期间,Web浏览器如何运行&qot;.jsx&qot;文件?

无法重定向到Next.js中的动态URL

JAVASCRIPT SWITCH CASE语句:当表达式为';ALL';

为什么我不能使用其同级元素调用和更新子元素?