C# Windows Forms调用FFmpeg转换视频无响应问题排查
问题分析与修复
对Process.StartInfo的理解纠正
Process.StartInfo不是仅用于获取信息,它是用来配置要启动的进程的所有参数(比如程序路径、命令行参数、工作目录、是否使用shell等),Process.Start()会完全按照StartInfo的配置来启动目标进程。你的核心理解偏差在这里——StartInfo是配置项,而非只读的信息容器。
代码中的具体错误与修复
1. FFmpeg命令参数格式错误
Arguments里不需要重复写ffmpeg:因为FileName已经指定了ffmpeg.exe,命令行参数只需要写-i及后续选项,重复写ffmpeg会导致FFmpeg解析失败。- 参数之间缺少空格:比如
-i和输入文件路径、输入文件和-s选项、最后一个选项和输出文件路径之间都没有空格,FFmpeg会把这些连在一起当成无效参数。
2. 字符串处理逻辑错误
- 循环条件错误:原代码
for (int i = (inputLength - 1); inputLength > -1; i--)的循环条件永远为真(inputLength是固定的输入字符串长度,不会变化),应该改为i >= 0,否则会导致索引越界。 - 输出路径截取错误:
output = input.Substring(0, l - 1)会去掉原文件名的最后一个字符,正确写法是input.Substring(0, l)(截取到点号之前的全部字符)。 - 文件类型截取错误:
outputFileType = input.Substring(l + 1, inputLength - 1)的长度参数错误,应该直接用input.Substring(l + 1)(从点号后截取到末尾),否则会超出字符串长度。
3. 进程配置不利于调试
- 设置
UseShellExecute = false,同时开启RedirectStandardError和RedirectStandardOutput,这样可以捕获FFmpeg的输出和错误信息,方便排查问题。 - 加上
WaitForExit()等待FFmpeg进程执行完成,避免程序提前退出导致转换中断。
修正后的完整代码
private void convertButton_Click(object sender, EventArgs e) { String input = filepathTextBox.Text; String outputResolution = resolutionLabel.Text; String output; String outputFileType; int inputLength = input.Length; int l = 0; // 修正循环条件,从末尾找第一个点号 for (int i = inputLength - 1; i >= 0; i--) { if (input[i] == '.') { l = i; break; } } // 修正输出路径截取,保留原文件名到点号前 output = input.Substring(0, l); // 修正文件类型截取,直接取点号后的部分 outputFileType = input.Substring(l + 1); Process process = new Process(); // 关闭ShellExecute,开启重定向以便捕获输出 process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.CreateNoWindow = true; // 不显示控制台窗口 process.StartInfo.FileName = "ffmpeg.exe"; process.StartInfo.WorkingDirectory = @"C:\Users\User\Downloads\ffmpeg-2023-05-15-git-2953ebe7b6-full_build\bin"; // 修正参数:去掉开头的ffmpeg,给参数之间加上空格,路径加双引号避免空格问题 process.StartInfo.Arguments = $"-i \"{input}\" -s {outputResolution} -r 25 -b:v 500000 -pix_fmt yuv420p -c:v libx264 -vprofile baseline -level 2.1 -x264opts stitchable=1:level=3.0:keyint=15:ref=1:merange=16:mvrange=32 -acodec pcm_s16le -ar 16000 -ac 1 \"{Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Downloads), Path.GetFileNameWithoutExtension(input))}_converted.mp4\""; // 注册输出事件,捕获FFmpeg的日志 process.OutputDataReceived += (s, args) => Console.WriteLine(args.Data); process.ErrorDataReceived += (s, args) => Console.WriteLine(args.Data); process.Start(); // 开始异步读取输出 process.BeginOutputReadLine(); process.BeginErrorReadLine(); // 等待进程完成 process.WaitForExit(); // 检查退出码,0表示成功 if (process.ExitCode == 0) { MessageBox.Show("转换完成!"); } else { MessageBox.Show("转换失败,请查看控制台输出!"); } }
额外说明
- 给文件路径加上双引号
\"{input}\",避免路径中包含空格时FFmpeg解析错误。 - 输出路径直接指定到下载文件夹,避免覆盖原文件,你可以根据需求调整文件名规则。
- 捕获FFmpeg的输出可以帮助你快速定位转换失败的原因(比如编码不支持、文件不存在等)。
内容的提问来源于stack exchange,提问作者TSLee
相关产品推荐
相关产品推荐

