在C#中使用FFMpeg流裁剪MP3时遇通道关闭异常问题咨询
问题分析
你遇到的System.IO.IOException: Channel is closed.异常,本质是FFmpeg在满足-t参数指定的时长要求后,会主动关闭标准输入通道,但此时C#代码里的input.CopyTo(process.StandardInput.BaseStream)还在尝试向已关闭的流写入剩余数据,从而触发异常。因为FFmpeg已经拿到了生成30秒MP3所需的全部数据,所以输出文件是正常的;而移除-t后,FFmpeg会等待输入流完全结束才关闭通道,因此不会报错。
解决方案
以下是几种可行的处理方式:
1. 捕获并忽略特定异常
既然输出文件已经正确生成,这个异常不影响最终结果,可以在写入流时捕获并忽略该IOException:
var inputFile = @"D:\TestInput.mp3"; var process = new Process { StartInfo = new ProcessStartInfo { FileName = @"path\to\ffmpeg.exe", Arguments = "-i - -vn -acodec copy -ss 00:00:00 -t 00:00:30 -y D:\\TestFFMpeg.mp3", RedirectStandardInput = true, UseShellExecute = false }, EnableRaisingEvents = true }; process.Start(); using (var input = File.OpenRead(inputFile)) { try { input.CopyTo(process.StandardInput.BaseStream); } catch (IOException ex) { // 判断是否是通道关闭的异常(不同系统可能异常消息略有差异) if (ex.Message.Contains("Channel is closed")) { // 忽略该异常,因为FFmpeg已经完成所需数据读取 } else { // 其他IO异常正常抛出 throw; } } } process.WaitForExit();
2. 异步写入并监听进程退出
通过异步写入数据,同时监听进程的退出事件,一旦进程退出就停止写入,避免向已关闭的流写入数据:
var inputFile = @"D:\TestInput.mp3"; var process = new Process { StartInfo = new ProcessStartInfo { FileName = @"path\to\ffmpeg.exe", Arguments = "-i - -vn -acodec copy -ss 00:00:00 -t 00:00:30 -y D:\\TestFFMpeg.mp3", RedirectStandardInput = true, UseShellExecute = false }, EnableRaisingEvents = true }; // 标记进程是否已退出 bool processExited = false; process.Exited += (sender, e) => processExited = true; process.Start(); using (var input = File.OpenRead(inputFile)) { var buffer = new byte[4096]; int bytesRead; while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0 && !processExited) { process.StandardInput.BaseStream.Write(buffer, 0, bytesRead); process.StandardInput.BaseStream.Flush(); } } process.WaitForExit();
3. 调整FFmpeg参数顺序(可选优化)
将时间参数-ss和-t移至输入参数-i -之前,让FFmpeg更早地处理时间裁剪逻辑(不过这不会完全避免异常,但可能减少写入的无效数据量):
Arguments = "-ss 00:00:00 -t 00:00:30 -i - -vn -acodec copy -y D:\\TestFFMpeg.mp3"
内容的提问来源于stack exchange,提问作者oLaDushek
相关产品推荐
相关产品推荐

