一般我们使用ffmpeg对音频和视频进行编辑。因为是命令行操作,所以它不限任何编程语言,net或java程序员都可以使用,只要拼接的参数能被解析就没有问题。如果想玩点高级的,就要深入研究下了。比如今天这个,应该很多人都想实现,就是在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教程的第一篇,欢迎收藏
文章评论