You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使AAC数据包适配createSourceBuffer API以在Safari上兼容HLS

解决Safari中提取HLS音频数据做多通道分析的问题

核心问题

Safari无法直接从媒体元素源提取音频数据,通过hls.js拿到解复用后的裸AAC音频块后,浏览器解码API(包括AudioDecoder和decodeAudioData)无法识别这些裸数据——因为裸AAC缺少ADTS头部,必须先补全头部才能被正确解码。

解决方案步骤

  1. 生成ADTS头部:根据你的AAC编码参数(采样率48000、双通道、mp4a.40.2编码),生成对应ADTS头字节,添加到每个AAC块前。
  2. 拼接完整AAC数据流:把带ADTS头的AAC块拼接成连续的二进制数据。
  3. 解码并接入分析器:用AudioContext.decodeAudioData解码处理后的数据流,得到AudioBuffer后接入分析器节点。

修正后的代码示例

// 实现ADTS头部生成函数
function generateADTSHeader(frameLength, sampleRate = 48000, channels = 2) {
    const sampleRateIndex = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350].indexOf(sampleRate);
    const adtsHeader = new Uint8Array(7);
    
    adtsHeader[0] = 0xFF; // 同步字
    adtsHeader[1] = 0xF1; // MPEG-4、无CRC校验
    adtsHeader[2] = (0x00 << 6) | (sampleRateIndex << 2) | (channels >> 2);
    adtsHeader[3] = ((channels & 0x3) << 6) | ((frameLength + 7) >> 11);
    adtsHeader[4] = ((frameLength + 7) & 0x7FF) >> 3;
    adtsHeader[5] = (((frameLength + 7) & 0x7) << 5) | 0x1F;
    adtsHeader[6] = 0xFC;
    
    return adtsHeader;
}

hls.on(Hls.Events.BUFFER_APPENDING, function (event, data) {
  if (data.type === "audio") {
    const context = new (window.AudioContext || window.webkitAudioContext)();
    const analyser = context.createAnalyser();
    analyser.connect(context.destination);

    // 给裸AAC块添加ADTS头部
    const aacFrame = data.data;
    const adtsHeader = generateADTSHeader(aacFrame.length);
    const fullFrame = new Uint8Array(adtsHeader.length + aacFrame.length);
    fullFrame.set(adtsHeader, 0);
    fullFrame.set(new Uint8Array(aacFrame), adtsHeader.length);

    // 解码处理后的完整AAC数据
    context.decodeAudioData(fullFrame.buffer, (audioBuffer) => {
      const srcNode = context.createBufferSource();
      srcNode.buffer = audioBuffer;
      srcNode.connect(analyser);
      srcNode.start();
    }, (err) => {
      console.error("解码失败:", err);
    });
  }
});

为什么之前的方法无效?

  • 直接用createBuffer把AAC字节当成PCM采样数据:AAC是压缩编码格式,不是原始音频采样值,这样处理会产生噪音或无有效数据。
  • 未加头部直接用AudioDecoder:AudioDecoder需要完整的编码帧结构,裸AAC块缺少ADTS头,解码器无法识别帧边界和编码参数,导致解码失败。

内容的提问来源于stack exchange,提问作者Dan Rossi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 04:02:47