Выбор формата аудио при локальном сохранении данных в веб-приложении

#javascript #dom-events #html5-audio

Вопрос:

У меня есть веб-приложение, которое получает некоторую входную аудиозапись от пользователя. И есть кнопка, чтобы сохранить его локально в виде аудиофайла. Полученный файл, который я получаю, имеет формат ogg-opus. Конкретно, когда я использую команду file, я получаю это в терминале:

 MyMac$ file Clip.wav 
Clip.wav: Ogg data, Opus audio,
MyMac$ 
 

Я могу проверить, что запись в порядке, используя VLC.
С другой стороны, я не могу воспроизвести файл с помощью afplay, как это обычно возможно с файлами mp3, m4a или wav.

 MyMac$ afplay Clip.wav
Error: AudioFileOpen failed ('typ?')
MyMac$ 
 

Ниже следует мой соответствующий код:

 if (navigator.mediaDevices.getUserMedia) {
  // getUserMedia is supported.
  const constraints = { audio: true };
  let chunks = [];

  let onSuccess = function(stream) {
    const mediaRecorder = new MediaRecorder(stream);
    visualize(stream);
    ........

    mediaRecorder.onstop = function(e) {
      ........
      audio.setAttribute('controls', '');
      ........
      audio.controls = true;
      const blob = new Blob(chunks, { 'type' : 'audio/wav;codecs=0' });
      chunks = [];
      ........
      upload.addEventListener("click", 
        function(event) {loadToServer(blob)})
      ........
    }

    mediaRecorder.ondataavailable = function(e) {
      chunks.push(e.data);
    }
  }

  let onError = function(err) {
    console.log('The following error occured: '   err);
  }

  navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);

} else {
   console.log('getUserMedia not supported on your browser!');
}
 

Я хотел бы знать, как изменить свой код, чтобы сгенерировать правильный wav-файл или даже mp3.

Примечание:

Я провел испытания, изменив эту строку кода:

 const blob = new Blob(chunks, { 'type' : 'audio/wav;codecs=0' });
 

по-разному, но это не имеет никакого эффекта вообще.

Ответ №1:

Чтобы указать тип воспроизведения вашей записи, вам нужно указать MediaRecorder , какой тип воспроизведения вы предпочитаете, прежде чем он начнет запись.

 - const mediaRecorder = new MediaRecorder(stream);
  const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/wav' });
 

К сожалению audio/wav , не поддерживается ни одним браузером. Вы получите ошибку при попытке использовать приведенный выше фрагмент кода.

Поскольку мне также были нужны записи wav, я создал библиотеку, которая предназначена для добавления этой функциональности. Он называется extendable-media-recorder, потому что его можно расширить с помощью любого другого (аудио) кодека, который вам нравится.

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

 - const blob = new Blob(chunks, { 'type' : 'audio/wav;codecs=0' });
  const blob = new Blob(chunks, { 'type' : mediaRecorder.mimeType });
 

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

Вот пример полного HTML-документа, в котором используется jspm для загрузки расширяемого носителя-регистратора без связывателя.

 <!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
    </head>
    <body>
        <button id="start" disabled>start</button>
        <button id="stop" disabled>stop</button>
        <script type="module">
            import { MediaRecorder, register } from 'https://jspm.dev/extendable-media-recorder';
            import { connect } from 'https://jspm.dev/extendable-media-recorder-wav-encoder';

            const $start = document.getElementById('start');
            const $stop = document.getElementById('stop');

            await register(await connect());

            const chunks = [];
            const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
            const mediaRecoder = new MediaRecorder(stream, { mimeType: 'audio/wav' });

            mediaRecoder.addEventListener('dataavailable', ({ data }) => {
                chunks.push(data);
            });
            mediaRecoder.addEventListener('stop', ({ data }) => {
                const blob = new Blob(chunks, { type : mediaRecoder.mimeType });

                console.log(blob);
            });

            $start.addEventListener('click', () => {
                mediaRecoder.start();

                $stop.addEventListener('click', () => {
                    $stop.disabled = true;

                    mediaRecoder.stop();
                });

                $start.disabled = true;
                $stop.disabled = false;
            });

            $start.disabled = false;
        </script>
    </body>
</html>
 

Комментарии:

1. Спасибо. Но я получаю ошибку в первой строке, следуя вашему предложению: Не найдено (в обещании) Исключение DOMException: конструктор MediaRecorder: аудио/wav указывает на неподдерживаемый контейнер

2. Я, конечно, хочу иметь в виду вашу библиотеку для использования в будущем. Но на этот раз я стараюсь избегать каких-либо сторонних дополнений. Я бы хотел сохранить его как обычный HTML/JS. Это не является node.js приложение.

3. Да, как я уже говорил выше, браузер не поддерживает audio/wav . Поэтому каждый браузер выдаст ошибку, когда вы зададите тип MIME audio/wav . Я обновлю ответ, чтобы указать на это более четко. Единственный известный мне способ извлечь данные PCM из носителя MediaRecorder -это использовать audio/webm;codecs=pcm . Но это работает только в браузерах на основе Chromium. Это то, что расширяемый-носитель-рекордер использует внутренне.

4. ОК. Тогда я неправильно понял ваш комментарий. Так что у меня нет возможности закончить с . wav-файл, если я не сделаю что-то более сложное, верно? Если я создам приложение NodeJS, используя вашу библиотеку; это сделает то, что мне нужно. Скажите мне, если я ошибаюсь, пожалуйста.

5. Да, это верно. Я думаю, что если вы не используете библиотеку для записи wav-файлов в браузере, в конце концов у вас будет собственная библиотека. Вот что случилось со мной. 🙂 Технология бэкенда на самом деле не имеет значения. расширяемый-устройство записи мультимедиа запускается в браузере.