Отправка аудиозаписи с js на сервер actix-web для сохранения на диск

В настоящее время пытаюсь отправить записанный звук из браузера на сервер actix-web и сохранить его на диск таким образом, чтобы в результате получилась воспроизводимая дорожка из обычного медиаплеера. Мне это сложно сделать, особенно потому, что я никогда раньше не работал со СМИ. Я основываю все, что делаю. сочетание некоторого поиска в Google и некоторого GPT. Проблема: похоже, что файл сохраняется на диске. Это файл ненулевого размера, однако он не воспроизводится в медиаплеере VLC. Скрипт для отправки записи на сервер 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.info("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.

Тело будет закодировано как данные формы, как указано в JS, но вы просто берете все байты тела и помещаете их в файл.

cdhowie 06.05.2024 22:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Тип JavaScript FormData кодирует тело как "multipart/form-data". Это не просто необработанные байты файла. Чтобы декодировать это тело в обработчике Actix-Web, вам нужно использовать actix-multipart.

Самый простой способ его использования — использовать макрос получения для структуры, отражающей данные формы.

  • Используйте 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
}

Существует также возможность принять actix_multipart::Multipart в свой обработчик, чтобы обрабатывать поле и потоковую передачу контента более вручную, чем описанный выше метод, если это необходимо.

Другие вопросы по теме