小Q的博客

  • 首页
  • net编程
    • 产品和框架
    • 开发实例
    • 经验技巧
    • 开源组件
  • wp独立站
  • 自媒体
  • 日记本
  • 工具箱
每个程序员,都应该有一个自己的博客站
  1. 首页
  2. net编程
  3. 开发实例
  4. 正文

ffmpeg教程 如何输出任务日志?用于进度条显示

2022年10月22日 3178点热度 2人点赞 0条评论

一般我们使用ffmpeg对音频和视频进行编辑。因为是命令行操作,所以它不限任何编程语言,net或java程序员都可以使用,只要拼接的参数能被解析就没有问题。如果想玩点高级的,就要深入研究下了。比如今天这个,应该很多人都想实现,就是在ffmpeg执行任务的时候,能够及时返回任务的进度,被可视化控件调用时,可以及时输出任务进度百分比。

ffmpeg教程

 

还是直接看源码,大约100行,比较直观

private string ExecFfmpegByArgs(string ffmpeg_exe, string args, int rowIndex)
{
    Process p = new Process();
    p.StartInfo.FileName = ffmpeg_exe;
    p.StartInfo.RedirectStandardError = true;
    p.StartInfo.CreateNoWindow = true;
    p.StartInfo.Arguments = args;
    p.StartInfo.UseShellExecute = false;
    p.Start();

    double totalDuration = 0;       //总时长            
    double currDuration = 0;        //当前处理时长
    double currProgress = 0;        //生前处理进度
    string currFileSize = null;     //当前生成的文件大小            

    string line;
    List<string> listLine = new List<string>();

    StreamReader reader = p.StandardError;
    while ((line = reader.ReadLine()) != null)
    {
        if (!string.IsNullOrEmpty(line))
        {
            string line2 = line.ToLower();

            if (line2.Contains("duration") && line2.Contains("bitrate") && line2.Contains("start"))
            {
                //示例
                //Duration: 00:03:12.42, start: 0.000000, bitrate: 1694 kb/s
                string durationTemp = StringHelper.Between(line2, "duration:", ", start");

                TimeSpan tsTemp = TimeSpan.Parse(durationTemp);
                totalDuration = tsTemp.TotalSeconds;
            }

            //if (line2.Contains("frame=") && line2.Contains("size=") && line2.Contains("time="))
            if (line2.Contains("size=") && line2.Contains("time="))
            {
                //示例
                //size=    1024kB time=00:00:57.20 bitrate= 146.6kbits/s speed=57.2x

                //解析生成文件大小
                currFileSize = StringHelper.Between(line2, "size= ", "time=");

                //解析生成文件进度
                string timeTemp = StringHelper.Between(line2, "time=", " bitrate");
                TimeSpan tsTemp = TimeSpan.Parse(timeTemp);
                currDuration = tsTemp.TotalSeconds;

                //获取进度百比分
                currProgress = Math.Round(currDuration / totalDuration, 2);

                //回填至Grid控件
                if (rowIndex >= 0)
                {
                    this.Invoke((EventHandler)delegate
                    {
                        //记录任务耗时
                        object beginTimeTemp = FormUIHelper.GetGridCellValue(this.gridviewFile, rowIndex, "BeginTime");
                        if (!StringHelper.ObjectIsNullOrEmpty(beginTimeTemp))
                        {
                            DateTime beginTime = DateTime.Parse(beginTimeTemp.ToString());

                            TimeSpan ts1 = DateTime.Now - beginTime;
                            FormUIHelper.SetGridCellValue(this.gridviewFile, rowIndex, "TotalSeconds", Math.Round(ts1.TotalSeconds, 2).ToString() + "秒");
                        }

                        FormUIHelper.SetGridCellValue(this.gridviewFile, rowIndex, "Progress", currProgress * 100);
                        this.gridviewFile.RefreshRow(rowIndex);
                    });
                }
            }

            listLine.Add(line);
        }
    }

    p.Close();

    DateTime endTime = DateTime.Now;
    string ps = string.Join(Environment.NewLine, listLine);

    this.Invoke((EventHandler)delegate
    {
        //记录任务耗时
        object beginTimeTemp = FormUIHelper.GetGridCellValue(this.gridviewFile, rowIndex, "BeginTime");
        if (!StringHelper.ObjectIsNullOrEmpty(beginTimeTemp))
        {
            DateTime beginTime = DateTime.Parse(beginTimeTemp.ToString());

            TimeSpan ts1 = endTime - beginTime;
            FormUIHelper.SetGridCellValue(this.gridviewFile, rowIndex, "TotalSeconds", Math.Round(ts1.TotalSeconds, 2).ToString() + "秒");
        }

        //回填返回日志
        FormUIHelper.SetGridCellValue(this.gridviewFile, rowIndex, "Content", ps);
        this.gridviewFile.RefreshRow(rowIndex);
    });        

    return ps;
}

 

代码说明

1、CreateNoWindow,是否弹出cmd界面。这里设置成不弹出

2、StandardError属性,用于接收日志,我们会用到

如果参数被正确解析,ffmpeg可以通过StandardError属性输出日志。日志中有几行是返回关键字:frame、fps、size、time。我们用到的是size:生成的文件大小、time:生成时间进度。根据之前生成的duration总时长,就可以计算出任务的进度

frame=    1 fps=0.0 q=0.0 size=       0kB time=00:00:00.23 bitrate=   1.7kbits/s speed=5.06x    
frame=   79 fps=0.0 q=29.0 size=       0kB time=00:00:02.85 bitrate=   0.1kbits/s speed=5.18x    
frame=  144 fps=137 q=29.0 size=     256kB time=00:00:05.01 bitrate= 418.2kbits/s speed=4.76x    
frame=  200 fps=127 q=29.0 size=     512kB time=00:00:06.89 bitrate= 608.2kbits/s speed=4.38x    
frame=  258 fps=124 q=29.0 size=     768kB time=00:00:08.80 bitrate= 715.0kbits/s speed=4.24x    
frame=  312 fps=121 q=29.0 size=    1024kB time=00:00:10.61 bitrate= 790.6kbits/s speed= 4.1x    
frame=  387 fps=125 q=29.0 size=    1280kB time=00:00:13.11 bitrate= 799.3kbits/s speed=4.23x    
frame=  460 fps=127 q=29.0 size=    1536kB time=00:00:15.55 bitrate= 808.8kbits/s speed= 4.3x    
frame=  545 fps=132 q=29.0 size=    2048kB time=00:00:18.36 bitrate= 913.5kbits/s speed=4.46x    
frame=  641 fps=139 q=29.0 size=    2304kB time=00:00:21.59 bitrate= 874.1kbits/s speed=4.67x    
frame=  739 fps=144 q=29.0 size=    2560kB time=00:00:24.84 bitrate= 844.1kbits/s speed=4.84x    
frame=  809 fps=144 q=29.0 size=    2816kB time=00:00:27.19 bitrate= 848.4kbits/s speed=4.82x    
frame=  878 fps=143 q=29.0 size=    3072kB time=00:00:29.48 bitrate= 853.4kbits/s speed= 4.8x    
frame=  949 fps=143 q=29.0 size=    3328kB time=00:00:31.83 bitrate= 856.4kbits/s speed=4.79x    
frame= 1025 fps=143 q=29.0 size=    3584kB time=00:00:34.38 bitrate= 853.8kbits/s speed= 4.8x    
frame= 1105 fps=144 q=29.0 size=    3840kB time=00:00:37.03 bitrate= 849.4kbits/s speed=4.83x    
frame= 1201 fps=147 q=29.0 size=    4096kB time=00:00:40.26 bitrate= 833.4kbits/s speed=4.93x    
frame= 1297 fps=150 q=29.0 size=    4352kB time=00:00:43.42 bitrate= 821.1kbits/s speed=5.01x

 

只这一个方法就可以了。如果想在第三方的UI控件中展示,就用下面的代码输出即可,记得要用this.Invoke方法,不然会报错的

this.Invoke((EventHandler)delegate
{
    //记录任务耗时
    object beginTimeTemp = FormUIHelper.GetGridCellValue(this.gridviewFile, rowIndex, "BeginTime");
    if (!StringHelper.ObjectIsNullOrEmpty(beginTimeTemp))
    {
        DateTime beginTime = DateTime.Parse(beginTimeTemp.ToString());

        TimeSpan ts1 = DateTime.Now - beginTime;
        FormUIHelper.SetGridCellValue(this.gridviewFile, rowIndex, "TotalSeconds", Math.Round(ts1.TotalSeconds, 2).ToString() + "秒");
    }

    FormUIHelper.SetGridCellValue(this.gridviewFile, rowIndex, "Progress", currProgress * 100);
    this.gridviewFile.RefreshRow(rowIndex);
});

 

这是ffmpeg教程的第一篇,欢迎收藏

标签: ffmpeg教程 显示进度 输出日志
最后更新:2022年10月22日

小Q

80后中年不油腻大叔,喜欢编写代码、打羽毛球、做木制玩具。目前定居浙江杭州

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2022 小Q的博客. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

浙ICP备2022019157号-2