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

如何用Node.js获取音频文件时长?两种方案对比及实现

Node.js 获取音频时长:方案对比与实现

方案选择:无绝对最优,看业务场景

  • 上传时从缓冲区获取
    • 优势:无需额外网络请求,处理速度快,适配用户上传音频到服务的场景。
    • 劣势:大文件会占用较多内存,需警惕内存溢出风险。
  • 远程音频文件获取
    • 优势:无需本地存储,直接处理线上音频资源,适配第三方音频链接的场景。
    • 劣势:依赖网络稳定性,速度受网络影响,需处理超时、请求失败等异常。

简单总结:处理用户上传的音频优先选缓冲区方案;处理远程链接的音频只能用远程文件方案。

具体实现(基于ffprobe,兼容性最强)

ffprobe是ffmpeg的组件,支持几乎所有音频格式,是解析音频元数据最可靠的工具。我们可以用ffprobe-static包直接引入二进制文件,无需额外安装ffmpeg。

1. 从文件缓冲区获取时长

适合上传场景,比如配合Express接收上传文件:

安装依赖

npm install ffprobe-static fluent-ffmpeg multer

代码示例(Express上传场景)

const ffmpeg = require('fluent-ffmpeg');
const ffprobePath = require('ffprobe-static').path;
const multer = require('multer');
const express = require('express');
const app = express();

// 配置multer用内存存储上传的文件缓冲区
const upload = multer({ storage: multer.memoryStorage() });

// 设置ffprobe路径
ffmpeg.setFfprobePath(ffprobePath);

// 处理上传接口
app.post('/upload-audio', upload.single('audio'), (req, res) => {
  if (!req.file) {
    return res.status(400).send('请上传音频文件');
  }

  // 解析缓冲区中的音频时长
  ffmpeg.ffprobe(req.file.buffer, (err, metadata) => {
    if (err) {
      return res.status(500).send(`解析时长失败:${err.message}`);
    }
    const durationSeconds = metadata.format.duration;
    res.json({
      文件名: req.file.originalname,
      时长: `${Math.round(durationSeconds)}秒`,
      精确时长: `${durationSeconds.toFixed(2)}秒`
    });
  });
});

app.listen(3000, () => console.log('服务启动在3000端口'));

纯Node.js处理本地文件缓冲区

const ffmpeg = require('fluent-ffmpeg');
const ffprobePath = require('ffprobe-static').path;
const fs = require('fs');

ffmpeg.setFfprobePath(ffprobePath);

// 读取本地文件到缓冲区(模拟上传的文件缓冲区)
fs.readFile('./test.mp3', (err, buffer) => {
  if (err) throw new Error(`读取文件失败:${err.message}`);

  ffmpeg.ffprobe(buffer, (err, metadata) => {
    if (err) throw new Error(`解析时长失败:${err.message}`);
    console.log(`音频时长:${metadata.format.duration.toFixed(2)}秒`);
  });
});

2. 获取远程音频文件时长

为提升效率,无需下载整个文件,仅请求文件前1MB内容即可让ffprobe解析出时长。

安装依赖

npm install ffprobe-static fluent-ffmpeg axios

代码示例

const ffmpeg = require('fluent-ffmpeg');
const ffprobePath = require('ffprobe-static').path;
const axios = require('axios');

ffmpeg.setFfprobePath(ffprobePath);

// 封装获取远程音频时长的函数
async function getRemoteAudioDuration(audioUrl) {
  try {
    // 只请求文件的前1MB数据
    const streamResponse = await axios({
      url: audioUrl,
      method: 'GET',
      responseType: 'stream',
      headers: { 'Range': 'bytes=0-1048575' }
    });

    return new Promise((resolve, reject) => {
      ffmpeg.ffprobe(streamResponse.data, (err, metadata) => {
        if (err) reject(new Error(`解析远程音频时长失败:${err.message}`));
        resolve(metadata.format.duration);
      });
    });
  } catch (err) {
    throw new Error(`请求远程音频失败:${err.message}`);
  }
}

// 使用示例
getRemoteAudioDuration('https://example.com/sample-audio.mp3')
  .then(duration => console.log(`远程音频时长:${Math.round(duration)}秒`))
  .catch(err => console.error(err));

注意事项

  • 处理超大音频文件时,避免用内存缓冲区,可临时写入磁盘再解析,之后删除临时文件。
  • 远程音频请求要设置超时时间,避免长时间等待。
  • 若需纯JS实现(不依赖ffmpeg),可尝试audio-duration包,但它仍需依赖ffmpeg环境,兼容性不如直接用ffprobe。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:00:31