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

如何获取网络电台音频流的MIME类型及检测音频比特率?

解决方案:检测网络电台的音频类型与比特率

一、通过Fetch加载片段检测音频类型

可以用Fetch请求流的前几十字节,解析音频文件的**文件头标识(Magic Number)**来判断格式——不同音频格式有独特的开头二进制特征,具体实现步骤如下:

  • 用fetch请求音频流时,通过Range头只获取前128字节(足够识别绝大多数主流音频格式)
  • 读取响应的ArrayBuffer,解析二进制数据匹配对应格式
  • 确认格式后,再将完整流交给Audio元素播放

示例代码:

async function detectAudioFormat(streamUrl) {
  try {
    // 请求前128字节,减少资源消耗
    const response = await fetch(streamUrl, {
      headers: { 'Range': 'bytes=0-127' }
    });
    if (!response.ok) throw new Error('请求片段失败');
    
    const buffer = await response.arrayBuffer();
    const view = new Uint8Array(buffer);
    
    // 匹配各格式的特征标识
    // MP3:开头为ID3标签(0x494433)或帧同步字
    if (view[0] === 0x49 && view[1] === 0x44 && view[2] === 0x33) {
      return 'mp3';
    }
    // OGG:开头为OggS(0x4F676753)
    if (view[0] === 0x4F && view[1] === 0x67 && view[2] === 0x67 && view[3] === 0x53) {
      return 'ogg';
    }
    // AAC:ADTS头以0xFFF0开头
    if ((view[0] & 0xFF) === 0xFF && (view[1] & 0xF0) === 0xF0) {
      return 'aac';
    }
    // 可根据需求补充WAV、FLAC等其他格式的检测逻辑
    return 'unknown';
  } catch (err) {
    console.error('检测格式出错:', err);
    return 'unknown';
  }
}

// 使用示例
const streamUrl = 'https://some-radio-station.com/stream';
detectAudioFormat(streamUrl).then(format => {
  console.log('音频类型:', format);
  // 格式检测完成后初始化播放器
  const audio = new Audio();
  audio.addEventListener('loadeddata', () => audio.play());
  audio.src = streamUrl;
});

注意:部分电台服务器可能不支持Range请求,这种情况下可以尝试读取响应的Content-Type头,但多数流媒体的该字段仅为audio/mpeg这类通用类型,无法精确到具体格式,因此解析文件头是更可靠的方案。

二、检测音频比特率

比特率检测分两种场景实现:

1. 从文件头解析(针对带元数据的格式)

主流音频格式的文件头会携带比特率信息,直接解析对应字段即可:

  • MP3:解析ID3标签或帧头的比特率索引
  • AAC:读取ADTS头的比特率参数
  • OGG:提取Vorbis头中的比特率数据

以MP3为例的解析代码:

function getMP3Bitrate(buffer) {
  const view = new Uint8Array(buffer);
  let offset = 0;
  // 跳过ID3标签(如果存在)
  if (view[0] === 0x49 && view[1] === 0x44 && view[2] === 0x33) {
    const tagSize = ((view[6] & 0x7F) << 21) | ((view[7] & 0x7F) << 14) | ((view[8] & 0x7F) << 7) | (view[9] & 0x7F);
    offset = 10 + tagSize;
  }
  // 寻找第一个MP3帧同步字(0xFFE0及以上)
  while (offset < view.length - 1) {
    if ((view[offset] === 0xFF) && ((view[offset+1] & 0xE0) === 0xE0)) {
      // 提取比特率索引,匹配标准比特率表
      const bitrateIndex = (view[offset+2] >> 4) & 0x0F;
      const bitrates = [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320];
      return bitrates[bitrateIndex] + ' kbps';
    }
    offset++;
  }
  return 'unknown';
}

// 可在detectAudioFormat返回'mp3'时调用该函数
// detectAudioFormat(streamUrl).then(format => {
//   if (format === 'mp3') {
//     const buffer = await response.arrayBuffer(); // 需调整代码逻辑传递buffer
//     console.log('比特率:', getMP3Bitrate(buffer));
//   }
// });

2. 实时估算(适合流媒体场景)

如果无法从文件头获取比特率,可以统计一段时间内加载的数据量来估算:

function estimateBitrate(audioElement) {
  const startTime = Date.now();
  const startBytes = audioElement.buffered.end(0);
  
  setTimeout(() => {
    const endTime = Date.now();
    const endBytes = audioElement.buffered.end(0);
    const duration = (endTime - startTime) / 1000; // 转换为秒
    const bytesLoaded = endBytes - startBytes;
    // 字节转比特,再转换为kbps
    const bitrate = (bytesLoaded * 8) / duration / 1000;
    console.log('估算比特率:', Math.round(bitrate) + ' kbps');
  }, 5000); // 5秒后计算,可根据需求调整时长
}

// 使用示例
const audio = new Audio();
audio.src = streamUrl;
audio.addEventListener('loadeddata', () => {
  audio.play();
  estimateBitrate(audio);
});

这种方法是近似值,受流媒体波动影响,但足够满足显示需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 01:55:22