能否为HLS音频流添加three.js AudioAnalyser?尝试后频率数据始终为0
为HLS音频流添加Three.js AudioAnalyser/Web API AnalyserNode的可行方案
问题分析
你的HLS音频流可正常播放,但Three.js AudioAnalyser返回的平均频率始终为0,Web API AnalyserNode的尝试也未成功,核心原因包括:
- 初始化分析器后立即调用频率获取方法,此时音频未开始播放或源未正确关联
- Three.js Audio未绑定实际的audio元素
- Web API尝试中误用
createMediaStreamSource(该方法需要MediaStream对象,而非audio元素)
解决方案一:使用Three.js AudioAnalyser
实现步骤
- 监听HLS流加载完成事件,确保音频源就绪后再初始化分析器
- 将audio元素关联到Three.js Audio对象
- 通过
requestAnimationFrame循环实时获取频率数据(单次调用无法获取动态变化的音频数据)
完整代码
let audioContext = new (window.AudioContext || window.webkitAudioContext)(); let streamAudio = document.querySelector('#player'); let hls; let listener, audio, analyser; const fftSize = 256; if (Hls.isSupported()) { hls = new Hls(); hls.loadSource('https://stream.revma.ihrhls.com/zc2593/hls.m3u8'); hls.attachMedia(streamAudio); // 监听HLS清单解析完成事件,确保音频源就绪 hls.on(Hls.Events.MANIFEST_PARSED, () => { // 初始化Three.js音频监听器 listener = new THREE.AudioListener(); perspectiveCamera.add(listener); // 创建Three.js Audio对象并关联audio元素 audio = new THREE.Audio(listener); audio.setMediaElementSource(streamAudio); // 初始化音频分析器 analyser = new THREE.AudioAnalyser(audio, fftSize); // 播放音频并开始实时获取频率数据 streamAudio.play().then(() => { function updateFrequency() { const averageFrequency = analyser.getAverageFrequency(); console.log(averageFrequency); requestAnimationFrame(updateFrequency); } updateFrequency(); }); }); } plyr.setup(streamAudio);
解决方案二:使用Web API AnalyserNode
实现步骤
- 使用
createMediaElementSource创建音频源(对应audio元素) - 正确连接音频节点链:
source -> analyser -> audioContext.destination - 循环获取频率数据并计算平均值
完整代码
let audioContext = new (window.AudioContext || window.webkitAudioContext)(); let streamAudio = document.querySelector('#player'); let hls; let analyser, frequencyData; const fftSize = 256; if (Hls.isSupported()) { hls = new Hls(); hls.loadSource('https://stream.revma.ihrhls.com/zc2593/hls.m3u8'); hls.attachMedia(streamAudio); hls.on(Hls.Events.MANIFEST_PARSED, () => { // 创建媒体元素音频源 const source = audioContext.createMediaElementSource(streamAudio); analyser = audioContext.createAnalyser(); analyser.fftSize = fftSize; // 连接音频节点 source.connect(analyser); analyser.connect(audioContext.destination); // 创建存储频率数据的数组 frequencyData = new Uint8Array(analyser.frequencyBinCount); streamAudio.play().then(() => { function updateFrequency() { // 获取当前频率数据 analyser.getByteFrequencyData(frequencyData); // 计算平均频率 let total = 0; frequencyData.forEach(val => total += val); const averageFrequency = total / frequencyData.length; console.log(averageFrequency); requestAnimationFrame(updateFrequency); } updateFrequency(); }); }); } plyr.setup(streamAudio);
关键注意事项
- 必须在用户交互事件(如点击)中初始化AudioContext或触发播放,否则浏览器会因自动播放政策阻止音频
- 确保音频流的CORS配置正确,你的audio标签已添加
crossorigin="anonymous",符合要求 - 频率数据是动态变化的,必须通过循环实时获取,单次调用无法得到有效数据
内容的提问来源于stack exchange,提问作者Nate LeGrand
相关产品推荐
相关产品推荐

