You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C#中实现FFmpeg编码进度捕获与进度条更新的可靠方案

在C#中可靠捕获FFmpeg编码进度并更新进度条

你的核心问题是FFmpeg默认将进度日志输出到标准错误流(stderr),但你绑定的是OutputDataReceived事件(对应标准输出流stdout),所以根本接收不到数据。下面是完整的解决方案:

关键修正点

  • 改用ErrorDataReceived事件捕获FFmpeg的stderr输出
  • 调用BeginErrorReadLine()启动异步读取错误流
  • 跨线程更新UI(事件回调在非UI线程,直接操作控件会报错)
  • 解析FFmpeg的进度行,提取有效进度数据

完整实现代码

int totalFiles = 0;
int completedFiles = 0;

if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
    totalFiles = openFileDialog1.FileNames.Length;
    // 全局进度条:追踪总文件完成数
    progressBarGlobal.Maximum = totalFiles;
    progressBarGlobal.Value = 0;

    foreach (string inputFile in openFileDialog1.FileNames)
    {
        string outputFile = Path.Combine(Path.GetDirectoryName(inputFile), 
            $"{Path.GetFileNameWithoutExtension(inputFile)}_encoded{Path.GetExtension(inputFile)}");

        // 当前文件编码进度条:0-100%
        progressBarSingle.Maximum = 100;
        progressBarSingle.Value = 0;
        labelStatus.Text = $"正在编码:{Path.GetFileName(inputFile)}";

        Process ffmpegProcess = new Process();
        ffmpegProcess.StartInfo.FileName = "ffmpeg.exe";
        // 添加-v quiet -stats参数,只保留进度统计输出,减少冗余日志
        ffmpegProcess.StartInfo.Arguments = $"-i \"{inputFile}\" -c:v libx264 -crf 23 -c:a aac -b:a 128k -v quiet -stats \"{outputFile}\"";
        ffmpegProcess.StartInfo.CreateNoWindow = true;
        ffmpegProcess.StartInfo.RedirectStandardError = true;
        ffmpegProcess.StartInfo.UseShellExecute = false;

        // 绑定错误流接收事件(FFmpeg进度输出在这里)
        ffmpegProcess.ErrorDataReceived += (sender, e) =>
        {
            if (string.IsNullOrEmpty(e.Data)) return;

            // 匹配总时长和当前编码时间的行
            var durationMatch = System.Text.RegularExpressions.Regex.Match(e.Data, @"Duration: (\d+:\d+:\d+\.\d+)");
            var timeMatch = System.Text.RegularExpressions.Regex.Match(e.Data, @"time=(\d+:\d+:\d+\.\d+)");
            
            if (durationMatch.Success && timeMatch.Success)
            {
                // 解析时长为秒数计算进度
                TimeSpan totalDuration = TimeSpan.Parse(durationMatch.Groups[1].Value);
                TimeSpan currentTime = TimeSpan.Parse(timeMatch.Groups[1].Value);
                int progress = (int)((currentTime.TotalSeconds / totalDuration.TotalSeconds) * 100);
                
                // 跨线程更新UI控件
                progressBarSingle.Invoke((Action)(() =>
                {
                    progressBarSingle.Value = progress > 100 ? 100 : progress;
                }));
            }
        };

        ffmpegProcess.Start();
        ffmpegProcess.BeginErrorReadLine();
        ffmpegProcess.WaitForExit();
        ffmpegProcess.Close();

        // 更新全局进度
        completedFiles++;
        progressBarGlobal.Invoke((Action)(() =>
        {
            progressBarGlobal.Value = completedFiles;
        }));
    }

    labelStatus.Text = "所有文件编码完成";
}

额外优化建议

  • 异常处理:给Process操作添加try-catch块,避免单个文件编码失败导致整个流程中断
  • 取消功能:添加取消按钮,调用ffmpegProcess.Kill()终止当前编码任务
  • 细节显示:在标签中同步显示当前文件的进度百分比(如"当前进度:65%"),提升用户体验

内容的提问来源于stack exchange,提问作者sadra hoseini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 06:45:13