通过ffmpeg实现音频转码,无需部署可本地直接调用

548 阅读2分钟

背景

在Electron项目中需要实现所有用户上传的音频转码为wav格式,为方便后续的操作。

方案

通过调研,目前市场上能很好地支持音频互相转码的工具只有ffmpeg,其他的大多是只支持部分固定格式的转化。由于是Electron项目,所以能够很方便地使用node的能力,那么控制台能做的事我也能通过node实现了。所以我不必费尽心思把ffmpeg集成到页面内,直接很粗暴地
通过child_process的exec调用ffmpeg.exe的能力,实现音频转码。

具体实现

直接上代码

/**
 * 主进程接收需要转码的音频绝对路径
 */
ipcMain.on('transcode', (event, { inputPath, audioId }) => {
  const audioDir = path.join(process.cwd(), 'download/audio')
  const ffmpegPath = path.join(process.cwd(), 'ffmpeg/ffmpeg.exe')
  const command = `${ffmpegPath} -i ${inputPath}  -ac 1 -ar 16000 -y ${audioDir}/${audioId}.wav`
  if (!fs.existsSync(audioDir)) {
    fs.mkdirSync(audioDir, { recursive: true })
  }
  exec(command, error => {
    if (error) {
      log.error(`ffmpeg error: ${error}`)
    }
  })
})

拼接好的ffmpeg命令是

ffmpeg.exe -i my_audio.m4a -ac 1 -ar 16000 -y my_audio.wav

等同于直接在控制台执行如上命令: image.png

执行完成: image.png

其中-i 参数表示输入文件,-ac 1 表示输出的音频将是单声道的,-ar 参数用于设置音频采样率,即每秒采集声音信号的次数,这里设置为 16000 Hz,-y 这个选项告诉 FFmpeg 在覆盖现有文件时无需提示用户确认,my_audio.wav这是输出文件的名称和路径。

整个命令的意思是:使用 FFmpeg 将名为 my_audio.m4a 的 M4A 音频文件转换为单声道、16kHz 采样率的 WAV 格式,并且覆盖任何现有的同名输出文件。运行这个命令后,你会在相同的目录下得到一个名为 my_audio.wav 的文件,它已经是经过处理的音频文件了。

更多的参数及解释

参数作用
-i <input>指定输入文件名(音频或视频)。
-acodec <codec>-c:a <codec>设置音频编码器。例如:-acodec libmp3lame 表示使用 MP3 编码器。
-ab <bitrate>-b:a <bitrate>设置音频比特率(kbps),控制音频质量与文件大小的关系。例如:-ab 128k 表示设置为 128 千比特每秒。
-ac <channels>-c:a:0 channels=<num>设置音频通道数(单声道或立体声)。例如:-ac 2 表示输出为立体声,-ac 1 表示输出为单声道。
-ar <rate>-c:sr <rate>设置音频采样率(Hz)。例如:-ar 44100 表示设置为 CD 质量的 44.1kHz。
-y直接覆盖输出文件,无需提示用户确认。
-vn只转换音频,忽略视频部分(如果输入文件包含视频)。
<output>输出文件名和路径。

总结

ffmpeg很强大,能做的远远不止于此。需要ffmpeg.exe可执行文件的评论区留言吧,有人需要我再打给包丢到云上