Toggle navigation
首页
技术
骑行
羽毛球
资讯
联络我
登录
.net-core获取ffmpeg转码进度及剩余时间
2019-02-02
.NET Core
> ffmpeg虽然可以转码,但是从默认的输出信息无法看出转码进度及剩余时间 # ffmpeg的转码输出信息 ffmpeg 转码的过程中输出的信息,无法直接获取当前转码的进度,一个示例的输出如下: frame= 1777 fps=108 q=40.0 Lsize= 1954kB time=00:04:55.89 bitrate= 54.1kbits/s dup=0 drop=4141 speed=17.9x frame=16788 fps=108 q=40.0 size= 1536kB time=00:04:39.38 bitrate= 45.0kbits/s dup=0 drop=3907 speed= 18x # 如何获取转码进度? 从如上的输出信息可以发现,可以从两个方面获取进度: * frame * time 对应的进度计算公式如下: * 1 - (total_frame - frame) / total_frame * time / duration ## 如何获取总帧数和持续时间 可以通过ffprobe工具来获取视频信息 ffprobe -v quiet -print_format json -show_format -show_streams [video file] 输出的结果类似: ```json { "streams": [ { "index": 0, "codec_name": "aac", "codec_long_name": "AAC (Advanced Audio Coding)", "profile": "LC", "codec_type": "audio", "codec_time_base": "1/44100", "codec_tag_string": "mp4a", "codec_tag": "0x6134706d", "sample_fmt": "fltp", "sample_rate": "44100", "channels": 2, "channel_layout": "stereo", "bits_per_sample": 0, "r_frame_rate": "0/0", "avg_frame_rate": "0/0", "time_base": "1/44100", "start_pts": 0, "start_time": "0.000000", "duration_ts": 102390024, "duration": "2321.769252", "bit_rate": "141914", "max_bit_rate": "236004", "nb_frames": "100088", "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0 }, "tags": { "creation_time": "2018-04-25T11:29:17.000000Z", "language": "eng", "handler_name": "Mainconcept MP4 Sound Media Handler" } }, { "index": 1, "codec_name": "h264", "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10", "profile": "High", "codec_type": "video", "codec_time_base": "46480601/1859160000", "codec_tag_string": "avc1", "codec_tag": "0x31637661", "width": 1364, "height": 768, "coded_width": 1376, "coded_height": 768, "has_b_frames": 1, "sample_aspect_ratio": "1024:1023", "display_aspect_ratio": "16:9", "pix_fmt": "yuv420p", "level": 32, "color_range": "tv", "color_space": "bt709", "color_transfer": "bt709", "color_primaries": "bt709", "chroma_location": "left", "refs": 1, "is_avc": "true", "nal_length_size": "4", "r_frame_rate": "20/1", "avg_frame_rate": "929580000/46480601", "time_base": "1/20000", "start_pts": 1000, "start_time": "0.050000", "duration_ts": 46479000, "duration": "2323.950000", "bit_rate": "413761", "bits_per_raw_sample": "8", "nb_frames": "46479", "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0 }, "tags": { "creation_time": "2018-04-25T11:29:17.000000Z", "language": "eng", "handler_name": "Mainconcept MP4 Video Media Handler", "encoder": "AVC Coding" } } ], "format": { "filename": "3.mp4", "nb_streams": 2, "nb_programs": 0, "format_name": "mov,mp4,m4a,3gp,3g2,mj2", "format_long_name": "QuickTime / MOV", "start_time": "0.000000", "duration": "2323.950000", "size": "162498216", "bit_rate": "559386", "probe_score": 100, "tags": { "major_brand": "mp42", "minor_version": "0", "compatible_brands": "isommp42", "creation_time": "2018-04-25T11:29:16.000000Z" } } } ``` 可以看到,获取总帧数和持续时间的 JSonPath 分别如下: * $.streams[1].nb_frames * $.format.duration 用JObject解析JSon示例代码如下: ```c# var videoFormatObject = JObject.Parse(json); var durationObject = videoFormatObject.SelectToken("$.format.duration"); var duration = durationObject.Value<double>(); ``` # 如何获取转码剩余时间? 虽然从转码进度可以得出转码所需时间,但并不直观,如何直观的显示出剩余时间? 分析ffmpeg转码时的输出发现,可以从 time, speed, duration 这3个数据计算出转码剩余时间: 剩余时间 = (duration - timeTranscoded) / speed 代码示例如下: ```c# var transcodeLog = "frame= 1777 fps=108 q=40.0 Lsize= 1954kB time=00:04:55.89 bitrate= 54.1kbits/s dup=0 drop=4141 speed=17.9x"; var match = Regex.Match(transcodeLog, "time=(\\S+)"); if (match.Success) { var timeTranscoded = TimeSpan.Parse(match.Groups[1].Value).TotalSeconds; // Trim() remove space when speed= 18x speed = Convert.ToDouble(Regex.Match(transcodeLog, "speed=(.+)x").Groups[1].Value.Trim()); Console.WriteLine($"Percentage: {(timeTranscoded / duration).ToString("p")}, Remaining time: {((duration - timeTranscoded) / speed).ToString("f1")}s"); } ``` # 如何调用进程并持续获取进程的输出? 调用进程时,需要设定 StartInfo.Redirect... = true,并监听数据接收事件,示例代码如下: ```c# string param = $"-y -i [input video] -vcodec libx264 -vf scale=1280:720 -r 6 -crf 40 -acodec aac -q:a 0.4 -ac 1 [output video]"; using (Process p = new Process()) { p.StartInfo.FileName = "ffmpeg.exe"; p.StartInfo.Arguments = param; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; var output = new DataReceivedEventHandler((sender, e) => { if (!String.IsNullOrEmpty(e.Data)) { Console.WriteLine(e.Data); } }); p.OutputDataReceived += output; p.ErrorDataReceived += output; p.Start(); p.BeginOutputReadLine(); p.BeginErrorReadLine(); // ffmpeg的进度输出是通过 Error 管道 p.WaitForExit(); } ``` 完成之后的转码进度及剩余时间显示: Percentage: 2.37 %, Remaining time: 21.7s Percentage: 5.40 %, Remaining time: 18.1s Percentage: 8.44 %, Remaining time: 16.6s ... Percentage: 96.83 %, Remaining time: 0.5s Percentage: 99.87 %, Remaining time: 0.0s Percentage: 100.00 %, Remaining time: 0.0s # 参考: * [ffmpeg libx264编码介绍](https://trac.ffmpeg.org/wiki/Encode/H.264) * [ffmpeg aac编码介绍](https://trac.ffmpeg.org/wiki/Encode/AAC) * [ffmpeg Documentation](https://ffmpeg.org/ffmpeg.html)
×
本文为博主原创,如需转载,请注明出处:
http://www.supperxin.com
返回博客列表