C#调用FFmpeg管道读取字节流输入报错问题求助
使用FFmpeg Pipe功能处理字节数组输入时报错
问题背景
我尝试用FFmpeg的pipe功能跳过磁盘写入,实现了两种输入方式(文件路径、字节数组)、输出方法和执行方法。文件路径输入正常,但字节数组输入时触发报错。
错误信息
[mov,mp4,m4a,3gp,3g2,mj2 @ 00000137385a10c0] stream 1, offset 0x30: partial file Error demuxing input file 0: Invalid data found when processing input pipe:.mp4: Invalid data found when processing input Cannot determine format of input stream 0:0 after EOF Error marking filters as finished
相关代码实现
输入方法
public FFMPEG input(string path) { parameters.Add($"-i {path}"); return this; } public FFMPEG input(byte[] file) { parameters.Add("-i pipe:.mp4"); files.Add(file); return this; }
输出方法
public FFMPEG output(string format) { _output = $"-f {format} -"; return this; }
执行方法
public byte[] run() { if (_output == "") { throw new Exception("missing output format"); } var process = new Process() { StartInfo = { FileName = @"ffmpeg.exe", Arguments = String.Join(" ", parameters) + " " + _output, RedirectStandardOutput = true, RedirectStandardInput = true, UseShellExecute = false, } }; process.Start(); foreach (var item in files) { process.StandardInput.BaseStream.Write(item); } byte[] result; using(var memstream = new MemoryStream()) { process.StandardOutput.BaseStream.CopyTo(memstream); result = memstream.ToArray(); } process.WaitForExit(); return result; }
调用示例
- 正常运行的文件输入调用:
var result = new FFMPEG() .input("./assets/video.mp4") .output("avi") .run();
- 报错的字节数组输入调用:
var result = new FFMPEG() .input(File.ReadAllBytes("./assets/video.mp4")) .output("avi") .run();
问题原因及解决办法
核心问题
- Pipe语法错误:
-i pipe:.mp4是错误写法,FFmpeg的标准输入pipe应为-i -,后缀.mp4完全多余,FFmpeg会自动识别输入流格式,也可通过-f mp4 -i -手动指定格式。 - 未关闭输入流:写入字节数组后未关闭
StandardInput,FFmpeg会一直等待更多输入,判定数据不完整,触发"partial file"报错。 - 死锁风险:同步读取输出流的逻辑可能导致进程因输出缓冲区满而阻塞。
修改后的代码
输入方法调整
public FFMPEG input(byte[] file) { // 基础写法:让FFmpeg自动识别输入格式 parameters.Add("-i -"); // 若自动识别失败,可手动指定格式:parameters.Add("-f mp4 -i -"); files.Add(file); return this; }
执行方法调整
public byte[] run() { if (_output == "") { throw new Exception("missing output format"); } var process = new Process() { StartInfo = { FileName = @"ffmpeg.exe", Arguments = String.Join(" ", parameters) + " " + _output, RedirectStandardOutput = true, RedirectStandardInput = true, RedirectStandardError = true, // 开启后可读取错误日志,方便调试 UseShellExecute = false, CreateNoWindow = true } }; byte[] result = null; // 异步读取输出流,避免死锁 var outputTask = Task.Run(() => { using(var memstream = new MemoryStream()) { process.StandardOutput.BaseStream.CopyTo(memstream); result = memstream.ToArray(); } }); process.Start(); // 写入所有输入数据后立即关闭标准输入,告知FFmpeg数据已发送完毕 foreach (var item in files) { process.StandardInput.BaseStream.Write(item); } process.StandardInput.Close(); outputTask.Wait(); process.WaitForExit(); // 调试时可打印错误信息 // string errorLog = process.StandardError.ReadToEnd(); // Console.WriteLine(errorLog); return result; }
内容的提问来源于stack exchange,提问作者thiago kaique
相关产品推荐
相关产品推荐

