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

React/Next.js中访问Audio ref获取音频时长返回NaN问题

问题根因

这个现象和SSR无关,本质是音频元数据加载是异步流程。你在useEffect中刚创建Audio实例、传入src路径后立刻读取duration属性时,浏览器还没完成音频文件的元数据拉取和解析,此时duration的默认值就是NaN。

你在控制台console.log(audioRef)能看到13秒的时长,是因为浏览器控制台对对象类型的打印是懒求值的:你手动点开控制台里的对象折叠项时,才会读取对象当下的最新属性值,这时候音频早就加载完了,自然能看到正确时长,但你执行console.log(audioRef.current.duration)的那一瞬间,值确实是NaN,控制台没有返回错误结果。

修复代码

不要在创建Audio实例后同步读取duration,监听Audio元素原生的loadedmetadata事件,等元数据解析完成后再取值更新状态即可,同时记得组件卸载时做事件和实例清理,避免内存泄漏:

const EXAMPLE_TRACK = {
  title: "Track Title",
  src: "http://goldfirestudios.com/proj/howlerjs/sound.ogg"
}

const Track = ({track = EXAMPLE_TRACK}) => {
  const [duration, setDuration] = useState(0);
  const audioRef = useRef(null);

  useEffect(() => {
    const audioInstance = new Audio(track.src);
    audioRef.current = audioInstance;

    const onMetadataLoaded = () => {
      setDuration(audioInstance.duration);
    };

    audioInstance.addEventListener('loadedmetadata', onMetadataLoaded);

    return () => {
      audioInstance.removeEventListener('loadedmetadata', onMetadataLoaded);
      audioInstance.pause();
      audioRef.current = null;
    };
  }, [track.src]);

  return (
    <>
      <div>标题:{track.title}</div>
      <div>时长:{duration}秒</div>
    </>
  );
}
排查提示

后续调试异步相关的变量时,不要直接信任控制台打印的对象快照——对象的懒求值特性在异步场景下非常容易误导判断。如果需要确认代码执行瞬间的对象值,可以直接打印原始类型字段,或者用console.log(JSON.stringify(目标对象))输出深拷贝后的静态快照。
如果遇到部分浏览器loadedmetadata触发不及时的场景,可以额外加个durationchange事件监听做兜底,回调逻辑和上面的元数据加载回调一致即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:09:16