使用fluent-ffmpeg合并.ts转.mp3时偶发错误码228问题求助
合并多个.ts文件为.mp3时间歇性出现ffmpeg退出码228错误
问题代码
我使用fluent-ffmpeg编写了以下代码,试图将多个.ts文件合并为单个.mp3文件:
import ffmpeg from 'fluent-ffmpeg' const tsDest = 'dir/file.ts' const mp3Dest = 'dir/file.mp3' const ff = ffmpeg(urls[0]) urls.slice(1).map(url => ff.input(url)) ff.on('error', function (err) { logger.error('An error occurred: ' + err.message) reject(err) }) .on('end', function () { return ffmpeg(tsDest) .videoCodec('libx264') .audioCodec('libmp3lame') .on('error', function (err) { logger.error('An error occurred: ', err) reject(err) }) .on('end', function () { resolve(mp3Dest) }) .save(mp3Dest) }).mergeToFile(tsDest, dir)
出现的错误
合并.ts文件阶段会间歇性触发错误,无固定规律:
An error occurred: ffmpeg exited with code 228: size= 259KiB time=00:00:04.95 bitrate= 428.6kbits/s speed=58.1x Conversion failed!
问题分析与解决建议
ffmpeg退出码228通常关联输入文件的完整性或兼容性问题,结合间歇性触发的特点,大概率是以下原因导致:
- 部分.ts文件存在损坏、截断(比如网络下载不完整)
- 不同.ts文件的音频编码参数(采样率、声道数、编码格式)不一致
- 网络拉取远程.ts文件时出现临时波动,导致输入流异常
1. 校验输入文件的一致性与完整性
在合并前先检查所有.ts文件的音频参数是否一致,同时验证文件是否可正常读取:
const checkFileValidity = (url) => { return new Promise((resolve, reject) => { ffmpeg.ffprobe(url, (err, metadata) => { if (err) reject(err); const audioStream = metadata.streams.find(s => s.codec_type === 'audio'); if (!audioStream) reject(new Error(`文件${url}无有效音频流`)); resolve({ sampleRate: audioStream.sample_rate, channels: audioStream.channels, codec: audioStream.codec_name }); }); }); }; // 批量校验所有文件 const allAudioParams = await Promise.all(urls.map(checkFileValidity)); const paramsMatch = allAudioParams.every(p => p.sampleRate === allAudioParams[0].sampleRate && p.channels === allAudioParams[0].channels && p.codec === allAudioParams[0].codec ); if (!paramsMatch) { throw new Error('存在音频参数不一致的.ts文件,无法直接合并'); }
2. 优化合并逻辑,减少中间步骤
原代码先合并为.ts再转mp3,多了一次转码环节,可直接在合并阶段输出mp3,同时禁用视频流(因为目标是音频文件):
import ffmpeg from 'fluent-ffmpeg' const mp3Dest = 'dir/file.mp3' const ff = ffmpeg(urls[0]) urls.slice(1).forEach(url => ff.input(url)) ff.on('error', (err) => { logger.error('合并转码出错: ' + err.message) reject(err) }) .on('end', () => { resolve(mp3Dest) }) // 指定音频编码器,跳过视频流处理 .outputOptions('-c:a', 'libmp3lame') .outputOptions('-vn') .save(mp3Dest)
3. 处理网络输入的稳定性问题
如果urls是远程地址,建议先将所有.ts文件下载到本地临时目录,再读取本地文件进行合并,避免网络波动导致的输入异常:
// 示例:用axios下载文件到本地 import axios from 'axios' import fs from 'fs/promises' import path from 'path' const tempDir = './temp_ts' await fs.mkdir(tempDir, { recursive: true }) const localFiles = await Promise.all(urls.map(async (url, index) => { const localPath = path.join(tempDir, `file_${index}.ts`) const response = await axios.get(url, { responseType: 'stream' }) await new Promise((resolve, reject) => { response.data.pipe(fs.createWriteStream(localPath)) .on('finish', resolve) .on('error', reject) }) return localPath })) // 用localFiles替代原urls进行合并
4. 依赖版本升级
尝试升级fluent-ffmpeg到最新稳定版,同时确保系统中的ffmpeg工具也是最新版本,旧版本可能存在已知的合并兼容性bug。
内容的提问来源于stack exchange,提问作者Nadia Ghebreial
相关产品推荐
相关产品推荐

