private static void DoEncoding(string videoPath, VideoMetaInfo metaInfo, string outputPath) { var process = new Process { StartInfo = new ProcessStartInfo { FileName = EncoderPath, Arguments = GenerateEncodingCommand(videoPath, outputPath, 1), UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = true } }; process.ErrorDataReceived += (sender, data) => { if (data.Data != null) { AnalyzeEncodingInfo(data, metaInfo, 1); } }; process.Start(); process.BeginErrorReadLine(); process.WaitForExit(); if (process.ExitCode != 0) { OnEncodingFailure(); return; } process = new Process() { StartInfo = new ProcessStartInfo() { FileName = EncoderPath, Arguments = GenerateEncodingCommand(videoPath, outputPath, 2), UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = true } }; process.ErrorDataReceived += (sender, data) => { if (data.Data != null) { AnalyzeEncodingInfo(data, metaInfo, 2); } }; process.Start(); process.BeginErrorReadLine(); process.WaitForExit(); OnEncodingSuccess(); }
private static VideoMetaInfo CheckVideoForEncoding(string videoPath) { var process = new Process { StartInfo = new ProcessStartInfo { FileName = ProberPath, Arguments = $"-show_streams -show_format -of json \"{videoPath}\"", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true } }; process.Start(); var probeResult = process.StandardOutput.ReadToEnd(); process.WaitForExit(); var resultData = JObject.Parse(probeResult); var streamData = resultData["streams"].Value <JArray>(); if (streamData.Count < 2) { throw new InvalidVideoMetaInfo("Video is lack of video track or audio track!"); } var videoMetaInfo = new VideoMetaInfo(); foreach (var trackData in streamData) { if (trackData["codec_type"].Value <string>() == "video") { videoMetaInfo.FrameNum = int.Parse(trackData["nb_frames"].Value <string>()); videoMetaInfo.Duration = (int)double.Parse(trackData["duration"].Value <string>()); break; } } if (!videoMetaInfo) { throw new InvalidVideoMetaInfo("Video meta info is incomplete!"); } return(videoMetaInfo); }
private static void AnalyzeEncodingInfo(DataReceivedEventArgs data, VideoMetaInfo info, int currentPass) { Debug.WriteLine($"Analyzing on thread {Thread.CurrentThread.ManagedThreadId}"); const string pat = @"frame= *(\d+) *fps= *(\d+\.?\d+).+time= *(\d+):(\d+):(\d+).+speed= *(\d+\.?\d+).*"; var matches = Regex.Match(data.Data, pat); if (matches.Success) { // General formulas for calculating progress and remaining time: // Progress: ((cur_pass - 1) / total_pass) * 100 + num / dem * 100 / total_pass // ETA: ((total_pass / cur_pass) * total - elapsed) / velocity const int totalPass = 2; var percent = -1; var timeLeft = -1; if (info.FrameNum != 0) { var totalFrameNum = info.FrameNum; var frameNum = int.Parse(matches.Groups[1].Value); var fps = double.Parse(matches.Groups[2].Value); percent = Percentize(currentPass - 1, totalPass) + Percentize(frameNum, totalFrameNum) / totalPass; timeLeft = Math.Abs(fps) < 0.001 ? -1 : (int)((totalPass / currentPass * totalFrameNum - frameNum) / fps); } else if (info.Duration != 0) { var duration = info.Duration; var h = int.Parse(matches.Groups[3].Value); var m = int.Parse(matches.Groups[4].Value); var s = int.Parse(matches.Groups[5].Value); var elapsed = h * 3600 + m * 60 + s; var speed = double.Parse(matches.Groups[6].Value); percent = Percentize(currentPass - 1, totalPass) + Percentize(elapsed, duration) / totalPass; timeLeft = Math.Abs(speed) < 0.001 ? -1 : (int)((totalPass / currentPass * duration - elapsed) / speed); } OnEncodingProgressUpdated(Tuple.Create(percent, timeLeft)); } }