/// <summary> /// Establishes whether the data contains progress information. /// </summary> /// <param name="rawData">Event data from ffmpeg.</param> /// <param name="progressEventArgs">If successful, outputs a <see cref="FFmpegProgressEventArgs"/> which is generated from the data.</param> internal static ConversionProgessData GetProgressData(string rawData, ConversionInput inputData) { if (!HasProgressData(rawData)) { return(null); } var matchSize = _expressions[Find.ConvertProgressSize].Match(rawData); var matchTime = _expressions[Find.ConvertProgressTime].Match(rawData); var matchBitrate = _expressions[Find.ConvertProgressBitrate].Match(rawData); var matchFrame = _expressions[Find.ConvertProgressFrame].Match(rawData); var matchFps = _expressions[Find.ConvertProgressFps].Match(rawData); var matchSpeed = _expressions[Find.ConvertProgressSpeed].Match(rawData); TimeSpan.TryParse(matchTime.Groups[1].Value, out TimeSpan processedDuration); long.TryParse(matchFrame.Groups[1].Value, out long frame); double.TryParse(matchFps.Groups[1].Value, out double fps); int.TryParse(matchSize.Groups[1].Value, out int sizeKb); double.TryParse(matchBitrate.Groups[1].Value, out double bitrate); double.TryParse(matchSpeed.Groups[1].Value, out double speed); return(new ConversionProgessData { OutputFile = inputData.OutputFile, InputFile = inputData.InputFile, CommandLine = inputData.CommandLine, ProcessedDuration = processedDuration, TotalDuration = TimeSpan.Zero, Frame = frame, Fps = fps, SizeKb = sizeKb, Bitrate = bitrate, Speed = speed }); }
/// <summary> /// Establishes whether the data indicates the conversion is complete. /// </summary> /// <param name="rawData">Event data from ffmpeg.</param> /// <param name="conversionCompleteEvent">If successful, outputs a <see cref="FFmpegCompletedEventArgs"/> which is generated from the data.</param> /// <returns></returns> internal static ConversionCompletedData GetConversionCompletedData(string rawData, ConversionInput inputData) { if (!HasConversionCompleted(rawData)) { return(null); } var matchFinished = _expressions[Find.ConvertProgressFinished].Match(rawData); double.TryParse(matchFinished.Groups[2].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out double muxingOverhead); return(new ConversionCompletedData { CommandLine = inputData.CommandLine, InputFile = inputData.InputFile, OutputFile = inputData.OutputFile, MuxingOverhead = muxingOverhead, TotalDuration = GetMediaDuration(rawData) }); }
private Task StartConversion(ConversionInput input, CancellationToken cancellationToken) { return(Task.Run(() => { var receivedMessagesLog = new List <string>(); Exception caughtException = null; var processStartInfo = GenerateStartInfo(input.CommandLine); OnData?.Invoke(this, new FFmpegRawDataEventArgs(input.CommandLine)); using (FFmpegProcess = Process.Start(processStartInfo)) { FFmpegProcess.ErrorDataReceived += (sender, received) => { if (received.Data == null) { return; } try { receivedMessagesLog.Insert(0, received.Data); OnData?.Invoke(this, new FFmpegRawDataEventArgs(received.Data)); if (RegexEngine.HasProgressData(received.Data)) { OnProgress?.Invoke(this, new FFmpegProgressEventArgs(RegexEngine.GetProgressData(received.Data, input))); } else if (RegexEngine.HasConversionCompleted(received.Data)) { OnCompleted?.Invoke(this, new FFmpegCompletedEventArgs(RegexEngine.GetConversionCompletedData(received.Data, input))); } } catch (Exception ex) { // catch the exception and kill the process since we're in a faulted state caughtException = ex; try { FFmpegProcess.Kill(); } catch (InvalidOperationException) { // Swallow exceptions that are thrown when killing the process, ie. the application is ending naturally before we get a chance to kill it. } } }; FFmpegProcess.BeginErrorReadLine(); if (cancellationToken != null) { while (!FFmpegProcess.WaitForExit(100)) { if (!cancellationToken.IsCancellationRequested) { continue; } try { FFmpegProcess.Kill(); } catch (Win32Exception) { // The associated process could not be terminated or the process is terminating. } } } else { FFmpegProcess.WaitForExit(); } if (cancellationToken.IsCancellationRequested) { cancellationToken.ThrowIfCancellationRequested(); } if (FFmpegProcess.ExitCode == 0 && caughtException == null) { return; } if (FFmpegProcess.ExitCode != 1 && receivedMessagesLog.Count >= 2) { throw new FFmpegException(FFmpegProcess.ExitCode + ": " + receivedMessagesLog[1] + receivedMessagesLog[0], caughtException); } else { throw new FFmpegException(string.Format($"ffmpeg exited with exitcode {FFmpegProcess.ExitCode}"), caughtException); } } })); }