Обрезать или обрезать звук, записанный с помощью медиа-рекордера JS

Требуемые знания

Как укоротить (спереди) массив аудио-блобов и при этом иметь воспроизводимый звук.

Цель

В конечном итоге я пытаюсь записать непрерывный 45-секундный цикл аудио с использованием API JS MediaRecorder. Пользователь сможет нажать кнопку, и последние 45 секунд звука будут сохранены. Я могу записать, воспроизвести и загрузить одну запись просто отлично.

вопрос

Когда у меня есть массив с именем chunks скажем 1000 BLOB-объектов из MediaRecorder и использовать chunks.slice(500, 1000) Полученный массив BLOB-объектов нельзя использовать для воспроизведения или загрузки аудио.

Довольно странно chunks.slice(0,500) все еще работает нормально.

Код

let chunks = [];

navigator.mediaDevices.getUserMedia({ audio: true })
  .then((stream) => {
    const mediaRecorder = new MediaRecorder(stream);
    mediaRecorder.ondataavailable = (e) => chunks.push(e.data);
  }

// At some later time, attempt to trim
const trimmedAudio = chunks.slice(500, 1000)
const blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
const audioURL = URL.createObjectURL(blob);
// audio is an audio DOM element
audio.src = audioURL;
// At this point the audio won't play

Попытки решения

Поскольку срезы от начала до середины работают, я попытался повернуть назад, разрезать и повернуть назад в исходное направление. Не удалось.

Я попытался оставить 16 капель в начале и удалить некоторые из середины. Не удалось.

ломоть

Я догадываюсь, что BLOB- объекты не всегда содержат данные и требуют некоторого преобразования в ArrayBuffer или определенный TypedArray. Я попробовал несколько таких преобразований, но до сих пор не нашел решения. Буду очень признателен за любые рекомендации, так как я могу найти любую документацию для редактирования записанных массивов BLOB-объектов.

Обновление 2017-02-11

Основываясь на совете Кайидо, чтобы объединить фрагменты, преобразовать их в ArrayBuffer и затем передать его в веб-аудио API, я попробовал следующее.

const blob = new Blob(chunksFromMediaRecorder, { 'type' : 'audio/ogg codecs=opus' })
// blob is Blob size: 32714, type: "audio/ogg codecs=opus"}
function playFromBlob(blob) {
  const aCtx = new (window.AudioContext || window.webkitAudioContext)()
  const source = aCtx.createBufferSource()
  const fileReader = new FileReader()
  let arrayBuffer
  fileReader.onload = function() {
    arrayBuffer = this.result
    console.log('arrayBuffer', arrayBuffer) // ArrayBuffer {} with byte length 32714
    aCtx.decodeAudioData(arrayBuffer) // throws: Uncaught (in promise) DOMException: Unable to decode audio data
      .then(decodedData => {
        // use the decoded data here
        source.buffer = decodedData
        source.connect(audioCtx.destination)
      })
  }

  fileReader.readAsArrayBuffer(blob);
}

Вышеприведенный пример успешен при создании ArrayBuffer того же размера, что и Blob, но когда я передаю его в decodeAudioData функция, она бросает Unable to decode audio data ошибка. Есть ли шаг, который мне не хватает в процессе конвертации?

Обновление 2017-02-18

Кайидо отметил, что существует известная ошибка с Chrome, которая помешала бы мне сместить массив аудиоданных. Насколько я могу судить, это делает невозможным любое обрезание или обрезку аудио в Chrome (Firefox обрезка аудио массива работает, см. Комментарий Кайидо).

Чтобы достигнуть моей конечной цели непрерывных 45-летних ретроактивных записей, я сейчас создаю два экземпляра MediaRecorders смещение на 45 с и обмен их. Поэтому, когда один в 45-х, а другой в 90-х, я начинаю новую запись и избавляюсь от 90-х MediaRecorder, Определенно неоптимальный, но лучшее решение, которое я могу найти в настоящее время.

0 ответов

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