Воспроизвести аудио из частичного ответа и сохранить буфер после завершения

Фон

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

проблема

С моим текущим состоянием знаний / кода / инструментов возможно только одно из следующих действий:

А) Потоковое аудио с HTMLAudioElement

const audio = new Audio()
audio.src = url
audio.preload = 'auto'
audio.load()

Аудио HTML5 внутренне заботится о частичном ответе, работает само по себе, но я не могу получить доступ к нижележащему буферу для сохранения файла после полной загрузки. Таким образом, я не смогу кешировать файл локально, не загрузив его отдельно (в другом запросе).

Б) Скачать / получить файл целиком, затем воспроизвести его

fetch(url, options) // set content header to array buffer
  .then((response) => {
    var blob = new Blob([response.value], { type: 'audio/mp3' })
    var url = window.URL.createObjectURL(blob)
    const audio = new Audio()
    audio.src = url
    audio.play()
  })

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

C) Использование пользовательского загрузчика и воспроизведение каждого чанка с помощью API WebAudio

Так как A и B было недостаточно, я написал собственный загрузчик, который загружает чанки (который работает нормально) и отправляет событие с текущим чанком (как ArrayBuffer) в качестве данных. Он также отправляет другое событие подряд, которое возвращает все фрагменты, поэтому я могу создать из него большой двоичный объект:

const chunkSize = 2048
const audioContext = new AudioContext()
const loader = new StreamLoader(url,  {step: chunkSize})

loader.on(StreamLoader.event.response, (data) => {
  // data.response is of type ArrayBuffer
  const floats = new Float32Array(data.response)
  const audioBuffer = audioContext.createBuffer(1, chunkSize, 4410)
  audioBuffer.getChannelData(0).set(floats)
  const sourceNode = new AudioBufferSourceNode(audioContext, {buffer: audioBuffer})
  sourceNode.connect(audioContext.destination)
  sourceNode.start(0)
})

loader.once(StreamLoader.event.complete, (data) => {
  const blob = new Blob(Object.values(data), {type: fileType})
  const objectURL = URL.createObjectURL(blob)
  const audio = new Audio();
  audio.src = url;
  audio.play();
})

loader.load()

Проблема здесь в том, что он производит только странный громкий шум. Тем не менее, игра с блоба, после завершения, работает нормально.

Мне известно о проблеме, что заголовок должен присутствовать для правильного декодирования аудио, поэтому мне любопытно, как HTMLAudioElement или MediaStream на самом деле внутренне разрешают это.

D) Использование MediaStream или MediaRecorder с пользовательским загрузчиком

Поскольку я не записываю с локального устройства, я не получил ни одного из них для работы с потоковыми чанками, загруженными с помощью xhr. Они ограничены для использования с местными источниками СМИ?

E) Использование таких инструментов, как Howler, SoundManager, SoundJS.

Я нашел вышеупомянутые инструменты, но, к сожалению, вернулся к выпуску A или B, используя их.

Ожидаемое решение

То, что я ожидаю найти, - это решение, которое позволяет мне воспроизводить аудио из потока (частичный ответ) и получать доступ к буферизованным данным для их кэширования.

Связанные ресурсы SO:

Как воспроизвести аудиопотоки, записанные с помощью WebRTC?

HTML5 запись аудио в файл

Источник HTML Audio из кеша

0 ответов

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