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); } } })); }
private void FFmpegRunner(string inputFile, string outputFile, string ffmpegCommandLine, CancellationToken cancellationToken) { List <string> receivedMessagesLog = new List <string>(); TimeSpan totalMediaDuration = new TimeSpan(); bool totalMediaDurationKnown = false; Exception caughtException = null; ProcessStartInfo processStartInfo = this.GenerateStartInfo(ffmpegCommandLine); this.OnData?.Invoke(this, new FFmpegDataEventArgs(ffmpegCommandLine)); using (this.FFmpegProcess = Process.Start(processStartInfo)) { this.FFmpegProcess.ErrorDataReceived += (sender, received) => { if (received.Data == null) { return; } try { receivedMessagesLog.Insert(0, received.Data); this.OnData?.Invoke(this, new FFmpegDataEventArgs(received.Data)); if (!totalMediaDurationKnown) { totalMediaDurationKnown = RegexEngine.MediaDuration(received.Data, out totalMediaDuration); } if (RegexEngine.IsProgressData(received.Data, out FFmpegProgressEventArgs progressEvent)) { progressEvent.InputFile = inputFile; progressEvent.OutputFile = outputFile; progressEvent.TotalDuration = totalMediaDuration; this.OnProgress?.Invoke(this, progressEvent); } else if (RegexEngine.IsConvertCompleteData(received.Data, out FFmpegCompletedEventArgs convertCompleteEvent)) { convertCompleteEvent.InputFile = inputFile; convertCompleteEvent.OutputFile = outputFile; convertCompleteEvent.TotalDuration = totalMediaDuration; this.OnCompleted?.Invoke(this, convertCompleteEvent); } } catch (Exception ex) { // catch the exception and kill the process since we're in a faulted state caughtException = ex; try { this.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. } } }; this.FFmpegProcess.BeginErrorReadLine(); if (cancellationToken != null) { while (!this.FFmpegProcess.WaitForExit(100)) { if (cancellationToken.IsCancellationRequested) { try { this.FFmpegProcess.Kill(); } catch (Win32Exception) { // The associated process could not be terminated or the process is terminating. } } } } else { this.FFmpegProcess.WaitForExit(); } if (cancellationToken.IsCancellationRequested) { cancellationToken.ThrowIfCancellationRequested(); } if (this.FFmpegProcess.ExitCode != 0 || caughtException != null) { if (this.FFmpegProcess.ExitCode != 1 && receivedMessagesLog.Count >= 2) { throw new FFmpegException(this.FFmpegProcess.ExitCode + ": " + receivedMessagesLog[1] + receivedMessagesLog[0], caughtException); } else { throw new FFmpegException(string.Format($"ffmpeg exited with exitcode {this.FFmpegProcess.ExitCode}"), caughtException); } } } }