Jan*_*nkt 6 javascript streaming html5-audio web-audio-api
背景
我正在编写一个服务来以块的形式提供静态音频文件,以支持带宽较低的用户的流畅体验。一旦文件完全流式传输(块序列是线性的,用户将无法“跳转”范围),我想将文件保存到本地缓存中(使用 localforage,但这不是这个问题的一部分)到稍后从那里加载缓存文件并节省带宽。
问题
根据我目前的知识/代码/工具状态,只能执行以下操作之一:
A) 使用HTMLAudioElement流式传输音频
const audio = new Audio()
audio.src = url
audio.preload = 'auto'
audio.load()
Run Code Online (Sandbox Code Playgroud)
HTML5 音频在内部处理部分响应,本身工作正常,但一旦完全加载,我就无法访问底层缓冲区来保存文件。因此,如果不单独下载(在另一个请求中),我将无法在本地缓存文件。
B) 下载/获取整个文件,然后播放
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()
})
Run Code Online (Sandbox Code Playgroud)
这使我可以访问数据,以便我可以缓存它以供离线重用。但是我放弃了流媒体选项,这使得几乎不可能在没有长时间等待的情况下播放更大的文件。
C) 使用自定义加载器并使用 WebAudio API 播放每个块
由于 A 和 B 不够用,我编写了一个自定义 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()
Run Code Online (Sandbox Code Playgroud)
这里的问题是它只产生奇怪的巨响。但是,一旦完成,从 blob 播放就可以正常工作。
I am aware of the issue, that the header needs to be present in order to decode the audio correctly, so I am curious how the HTMLAudioElement or MediaStream actually internally resolve this.
D) Using MediaStream or MediaRecorder with custom loader
Since I am not recording from a local device, I did not got any of these to work with streaming the chunks, that I loaded using xhr. Are they restricted to be used with local media sources?
E) Using tools like Howler, SoundManager, SoundJS.
I found the above mentioned tools, but unfortunately came back to issue A or B using them.
Expected Solution
What I expect to find is a solution, that allows me to play the audio from stream (partial response) and to access the buffered data in order to cache it.
Related SO resources:
| 归档时间: |
|
| 查看次数: |
1903 次 |
| 最近记录: |