#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
. Поэтому каждый браузер выдаст ошибку, когда вы зададите тип MIMEaudio/wav
. Я обновлю ответ, чтобы указать на это более четко. Единственный известный мне способ извлечь данные PCM из носителяMediaRecorder
-это использоватьaudio/webm;codecs=pcm
. Но это работает только в браузерах на основе Chromium. Это то, что расширяемый-носитель-рекордер использует внутренне.4. ОК. Тогда я неправильно понял ваш комментарий. Так что у меня нет возможности закончить с . wav-файл, если я не сделаю что-то более сложное, верно? Если я создам приложение NodeJS, используя вашу библиотеку; это сделает то, что мне нужно. Скажите мне, если я ошибаюсь, пожалуйста.
5. Да, это верно. Я думаю, что если вы не используете библиотеку для записи wav-файлов в браузере, в конце концов у вас будет собственная библиотека. Вот что случилось со мной. 🙂 Технология бэкенда на самом деле не имеет значения. расширяемый-устройство записи мультимедиа запускается в браузере.