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

Node.js中如何将多段文本转语音生成的音频缓冲区拼接为单个音频文件

问题根因
  1. 当前代码中audioContents.join()的逻辑完全错误:audioContent是Node.js Buffer类型,默认的join()方法会将Buffer转为字符串并用逗号拼接,直接破坏了二进制音频数据。
  2. 即使替换为Buffer.concat(audioContents)拼接MP3也无法正常播放:TTS接口返回的每一段MP3都是独立完整的文件,自带文件头/帧头元数据,直接拼接后播放器无法识别多段头信息,会出现只有第一段能播放、时长错误、杂音等问题。
方案1:改用LINEAR16编码(TTS领域推荐方案)

LINEAR16是无压缩的原始PCM音频流,没有任何文件头元信息,只要所有TTS请求的采样率、声道数、位深参数完全一致,多段音频可以直接二进制拼接,零额外处理开销,是长文本TTS拼接场景的首选方案。
实现代码参考:

const client = new textToSpeech.TextToSpeechClient();
// 全局统一音频参数,所有请求必须使用同一套配置
const AUDIO_CONFIG = {
  audioEncoding: 'LINEAR16',
  sampleRateHertz: 16000, // 可选8000/16000/24000/48000,保持统一即可
  audioChannelCount: 1 // 单声道是TTS场景通用配置
}
const promises = ['hi','world'].map(text => {
  const requestBody = {
    audioConfig: AUDIO_CONFIG,
    input: { text },
    voice: {
      languageCode: 'en-US',
      ssmlGender: 'NEUTRAL'
    },
  };
  return client.synthesizeSpeech(requestBody)
})
const responses = await Promise.all(promises)
const audioContents = responses.map(res => res[0].audioContent)
// 直接拼接Buffer即可得到完整可用的LINEAR16流
const fullAudioPcm = Buffer.concat(audioContents)

使用说明:

  • 拼接完成的LINEAR16可以直接送入语音识别、直播推流等链路使用
  • 如果需要导出为可直接播放的WAV格式,只需要给拼接后的PCM添加标准WAV头即可;如果需要转MP3,可以统一调用一次FFmpeg转码即可,比多段MP3拼接性能高很多
  • 浏览器环境下可以直接用AudioContext解码LINEAR16流实时播放,适合长文本流式合成场景
方案2:继续使用MP3格式的拼接方案

如果业务要求必须输出MP3,有两种实现方式:

  • Node.js环境下用fluent-ffmpeg合并:将每一段MP3 Buffer写入临时文件,调用FFmpeg的concat滤镜合并多段音频,自动处理头信息兼容问题
  • 浏览器/轻量场景下用mp3-concat等专门的JS库:自动剥离每段MP3的头信息,只拼接有效音频帧,最终输出完整MP3

内容的提问来源于stack exchange,提问作者Wt.N

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 18:15:01