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

录制的音频文件时长未知,如何解决?(附TypeScript代码)

解决MediaRecorder录制音频后文件时长未知的问题

你遇到的时长无法识别问题,核心原因有两个:

  1. 浏览器的MediaRecorder原生不支持直接录制MP3格式,你在创建Blob时指定type: 'audio/mp3'仅为文件添加了类型标记,实际录制的音频编码是浏览器默认格式(如Opus封装在WebM容器中),播放器无法解析这种"伪MP3"的时长信息。
  2. 直接拼接dataArray中的Blob片段生成的文件,缺少音频文件必需的元数据头部(如MP3的ID3标签、时长索引),播放器无法通过文件头快速读取时长。

具体解决办法

方法一:先按浏览器支持格式录制,再转码为标准MP3

步骤1:适配浏览器支持的编码格式

先检测浏览器支持的音频编码,优先选择带完整元数据的格式录制,再转码为标准MP3:

let recorder: MediaRecorder,
dataArray: Blob[]

async function InitializeAudio(): Promise<void> {
    let audioIN = { audio: true }
    try {
        const mediastremObj = await navigator.mediaDevices.getUserMedia(audioIN)
        // 检测并选择浏览器支持的编码格式
        const supportedType = MediaRecorder.isTypeSupported('audio/webm; codecs=opus') 
            ? 'audio/webm; codecs=opus'
            : MediaRecorder.isTypeSupported('audio/mp4; codecs=aac')
                ? 'audio/mp4; codecs=aac'
                : 'audio/wav'; // 兜底用无压缩WAV,元数据完整
        
        const mediaRecorder = new MediaRecorder(mediastremObj, { mimeType: supportedType })
        recorder = mediaRecorder
        recorder.ondataavailable = (ev)=>{
            dataArray.push(ev.data)
        }
        recorder.onstop = async (ev) => {
            const recordedBlob = new Blob(dataArray, { type: supportedType })
            // 转码为带完整元数据的标准MP3
            const mp3Blob = await convertToMP3(recordedBlob)
            
            const downloadTag = document.querySelector('#file-download') as HTMLAnchorElement
            const url = window.URL.createObjectURL(mp3Blob)
            downloadTag.href = url
            downloadTag.download = `my-${Date.now()}-audio.mp3`
            downloadTag.click()
            window.URL.revokeObjectURL(url)
            dataArray = []
        }
    } catch (e) {
        throw new Error(e as string)
    }
}

步骤2:用ffmpeg.wasm转码生成标准MP3

借助ffmpeg.wasm处理转码,自动添加MP3必需的元数据:

  1. 安装依赖:
npm install @ffmpeg/ffmpeg @ffmpeg/core
  1. 实现转码函数:
import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile } from '@ffmpeg/util';

const ffmpeg = new FFmpeg();

async function convertToMP3(inputBlob: Blob): Promise<Blob> {
    // 首次加载ffmpeg核心文件
    if (!ffmpeg.loaded) {
        await ffmpeg.load();
    }

    // 将录制的Blob写入虚拟文件系统
    const inputFileName = 'input.webm';
    const outputFileName = 'output.mp3';
    await ffmpeg.writeFile(inputFileName, await fetchFile(inputBlob));

    // 执行转码命令,生成带元数据的MP3
    await ffmpeg.exec([
        '-i', inputFileName,
        '-codec:a', 'libmp3lame',
        '-q:a', '2', // 音质参数,2为高质量,范围0-9
        outputFileName
    ]);

    // 读取转码后的文件并返回Blob
    const data = await ffmpeg.readFile(outputFileName);
    return new Blob([data], { type: 'audio/mp3' });
}

方法二:直接录制为WAV格式(简单但文件体积大)

如果对文件大小要求不高,可以直接录制为WAV格式,WAV是无压缩格式,元数据完整,播放器可直接识别时长:
只需将supportedType设置为'audio/wav',下载文件后缀改为.wav即可,无需转码。


注意事项

  • 不要直接给MediaRecorder指定audio/mp3类型,几乎没有浏览器原生支持该录制格式,强行指定会导致录制失败或生成无效文件。
  • ffmpeg.wasm首次加载需下载核心文件,建议在页面初始化时提前加载,优化用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 05:01:06