Flutter使用ffmpeg_kit_flutter裁剪音频失败,返回returnCode 1
音频裁剪功能异常排查与修复
问题概述
音频裁剪功能无法正常工作,执行后返回returnCode 1,输出路径下无目标文件,后续操作抛出文件未找到异常。
环境信息
- Flutter版本:3.0.2
- Dart版本:2.17.3
- 使用依赖包:
ffmpeg_kit_flutter: ^4.5.1
输入输出路径
- 输入文件路径:
"/data/user/0/com.goonetech.v1.gofinal/cache/file_picker/sample-15s.mp3" - 输出文件路径:
"/data/user/0/com.goonetech.v1.gofinal/app_flutter/output.mp3"
原实现代码
double start=2, double end=5; String path="/data/user/0/com.goonetech.v1.gofinal/cache/file_picker/sample-15s.mp3" static Future<String> cutAudio(String path, double start, double end) async { final Directory dir = await getApplicationDocumentsDirectory(); final outPath = "${dir.path}/output.mp3"; double start = 1; double end = 5; try { await File(outPath).delete(); } catch (e) { print("Delete Error"); } var cmd = "-y -i \"$path\" -vn -ss $start -to $end -ar 16k -ac 2 -b:a 96k -acodec libmp3lame $outPath"; FFmpegKit.executeAsync(cmd, (session) async { final returnCode = await session.getReturnCode(); print("returnCode $returnCode"); }); return outPath; }
问题分析
- 参数被覆盖:函数参数
start和end被内部重新赋值为1和5,导致外部传入的裁剪时间完全无效。 - 异步任务未等待:
FFmpegKit.executeAsync是异步执行逻辑,函数直接返回outPath时,FFmpeg的裁剪任务可能还未完成,此时输出文件尚未生成,后续读取必然触发文件未找到异常。 - 路径引号问题:输入路径被双引号包裹,部分环境下会导致FFmpeg无法正确解析路径,找不到输入文件。
- 错误信息缺失:仅打印返回码,未获取FFmpeg的详细错误输出,无法精准定位问题根源。
修复方案
1. 移除参数覆盖
删除函数内部的double start = 1; double end = 5;,保留外部传入的参数值。
2. 等待FFmpeg任务完成
改用FFmpegKit.execute同步执行,确保裁剪任务完成后再返回输出路径;或者通过Completer监听异步任务状态,完成后再返回。推荐同步方式简化逻辑。
3. 修正命令行路径格式
移除输入路径的双引号,直接使用原始路径字符串。
4. 捕获详细错误日志
通过session.getErrorOutput()获取FFmpeg的执行错误信息,便于快速定位问题。
修正后的代码
double start = 2; double end = 5; String path = "/data/user/0/com.goonetech.v1.gofinal/cache/file_picker/sample-15s.mp3"; static Future<String> cutAudio(String path, double start, double end) async { final Directory dir = await getApplicationDocumentsDirectory(); final outPath = "${dir.path}/output.mp3"; // 尝试删除旧输出文件,忽略删除失败 try { await File(outPath).delete(); } catch (_) {} // 修正FFmpeg命令:移除路径引号,使用传入的裁剪参数 var cmd = "-y -i $path -vn -ss $start -to $end -ar 16k -ac 2 -b:a 96k -acodec libmp3lame $outPath"; // 同步执行FFmpeg任务,等待完成 final session = await FFmpegKit.execute(cmd); final returnCode = await session.getReturnCode(); if (ReturnCode.isSuccess(returnCode)) { print("音频裁剪成功"); return outPath; } else { // 获取详细错误信息 final errorLog = await session.getErrorOutput(); print("裁剪失败,错误日志:$errorLog"); // 抛出异常供上层处理 throw Exception("音频裁剪失败,错误码:$returnCode,详情:$errorLog"); } }
额外注意事项
- 确保应用拥有存储读写权限:Android 13+需申请
READ_MEDIA_AUDIO或WRITE_EXTERNAL_STORAGE权限,iOS需在Info.plist中配置文档目录访问权限。 - 提前验证输入文件:调用裁剪函数前,通过
await File(path).exists()检查输入文件是否存在,避免因文件不存在导致的FFmpeg执行失败。 - 裁剪精度与速度权衡:若需要高精度裁剪,可将
-ss参数移至-i之后(即-i $path -ss $start -to $end),但会降低裁剪速度;反之-ss放在-i前速度更快,但精度稍低。
内容的提问来源于stack exchange,提问作者Sharath Appesh
相关产品推荐
相关产品推荐

