播放部分响应的音频,并在完成后保存缓冲区

时间:2018-10-05 14:20:58

标签: javascript streaming html5-audio web-audio

背景

我正在编写一项服务,以分块方式提供静态音频文件,以为带宽较低的用户提供流畅的体验。文件完全流化后(块顺序是线性的,用户将无法“跳转”范围),我想将文件保存到本地缓存中(使用localforage,但这不是此问题的一部分)稍后从那里加载缓存的文件并节省带宽。

问题

根据我当前的知识/代码/工具,只能执行以下操作之一:

A)使用HTMLAudioElement

流式传输音频
const audio = new Audio()
audio.src = url
audio.preload = 'auto'
audio.load()

HTML5音频在内部负责部分响应,本身可以正常工作,但是一旦完全加载,我将无法访问基础缓冲区来保存文件。因此,如果不单独下载(在另一个请求中),我将无法在本地缓存文件。

B)下载/ fetch整个文件,然后播放

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)使用自定义加载程序,并使用WebAudio API播放每个块

由于A和B不够用,所以我写了custom loader,它加载了块(工作正常),并以当前块(作为ArrayBuffer)调度一个事件作为数据。它还在末尾调度另一个事件,该事件返回所有块,因此我可以从中创建一个blob:

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()

这里的问题是,它只会产生奇怪的响亮噪音。但是,一旦完成,从Blob播放就可以了。

我知道这个问题,为了正确解码音频,需要提供标头,所以我很好奇HTMLAudioElement或MediaStream实际上是如何在内部解决此问题的。

D)在自定义加载程序中使用MediaStreamMediaRecorder

由于我不是从本地设备进行录制的,因此我没有使用这些文件来处理使用xhr加载的块。是否仅限与本地媒体源一起使用?

E)使用诸如Howler,SoundManager,SoundJS之类的工具。

我找到了上面提到的工具,但是很遗憾再次使用它们来发行A或B。

期望的解决方案

我希望找到一种解决方案,该解决方案使我可以播放流中的音频(部分响应)并访问缓冲的数据以对其进行缓存。

相关的SO资源:

How to play audio stream chunks recorded with WebRTC?

HTML5 record audio to file

HTML Audio element source from cache

0 个答案:

没有答案