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

如何用JavaScript获取WebM/Opus原始音频时长?loadedmetadata未触发

解决Audio元素loadedmetadata事件不触发的问题

问题核心原因

你的代码存在两个关键问题:

  • 直接将完整的Data URI字符串传入Blob,而非解码后的二进制音频数据
  • 创建Blob时未指定正确的MIME类型,浏览器无法识别音频格式,导致无法解析元数据

修复方案

1. 正确解码Data URI为二进制Blob

先从Data URI中剥离前缀,解码base64内容为二进制数据,再生成带正确MIME类型的Blob:

function dataUriToBlob(dataUri) {
  // 拆分Data URI,提取MIME类型和base64数据
  const [typeSection, dataSection] = dataUri.split(',');
  const mimeType = typeSection.match(/:(.*?);/)[1];
  // 解码base64为二进制字符串
  const byteString = atob(dataSection);
  // 转换为ArrayBuffer
  const arrayBuffer = new ArrayBuffer(byteString.length);
  const uint8Array = new Uint8Array(arrayBuffer);
  for (let i = 0; i < byteString.length; i++) {
    uint8Array[i] = byteString.charCodeAt(i);
  }
  // 生成指定MIME类型的Blob
  return new Blob([arrayBuffer], { type: mimeType });
}

2. 修正音频加载逻辑,确保触发元数据加载

创建Audio元素后主动调用load()方法,同时添加错误监听排查潜在问题:

const onDrop = (audioBlob) => {
  const audio = document.createElement("audio");
  audio.src = URL.createObjectURL(audioBlob);
  audio.crossOrigin = "anonymous";

  // 监听错误事件,快速定位格式/解码问题
  audio.addEventListener("error", (e) => {
    console.error("音频加载失败:", e.target.error);
  });

  audio.addEventListener("loadedmetadata", () => {
    console.log("loadedmetadata");
    console.log("音频时长:", audio.duration);
    // 释放ObjectURL资源,避免内存泄漏
    URL.revokeObjectURL(audio.src);
  });

  // 主动触发音频加载流程
  audio.load();
};

// 处理音频数据并调用加载逻辑
const processedBlob = dataUriToBlob(Card.audios.explain[0]);
onDrop(processedBlob);

额外排查点

如果修复后事件仍不触发,检查以下内容:

  • 音频文件本身是否损坏:可以直接将Data URI粘贴到浏览器地址栏,验证是否能正常播放
  • 浏览器是否支持该格式:WebM/Opus是主流浏览器支持的格式,但部分旧版本浏览器可能存在兼容问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:16:12