public static GlobalExportProgress BuildFromRenderOptionsSingleCommand(ICollection <VideoRenderOption> videoRenderOptions, Action <string, double, double, double> progressChangedCallback) { var progress = new GlobalExportProgress(videoRenderOptions.Any(v => v.TimeWarpSettings.Any()) ? 2 : 1, progressChangedCallback); progress.StartExport(); return(progress); }
public static GlobalExportProgress BuildFromRenderOptionsPreEffect(ICollection <VideoRenderOption> videoRenderOptions, Action <string, double, double, double> progressChangedCallback) { // по одной операции для вырезания каждого эпизода. var totalOperationsExpected = videoRenderOptions.Count; // по одной операции для каждого эпизода с текстом. totalOperationsExpected += videoRenderOptions.Count(v => v.OverlayTextTimeTable != null && v.OverlayTextTimeTable.Any()); // по одной операции для каждого эпизода со штрихами. totalOperationsExpected += videoRenderOptions.Count(v => v.ImagesTimeTable != null && v.ImagesTimeTable.Any()); // по одной операции для каждого эффекта времени. totalOperationsExpected += videoRenderOptions.SelectMany(v => v.TimeWarpSettings ?? new List <TimeWarpRecord>()).Count(); if (videoRenderOptions.Count > 1) { // один раз склеить и конвертировать эпизоды в конечный формат. totalOperationsExpected += 2; } var progress = new GlobalExportProgress(totalOperationsExpected, progressChangedCallback); progress.StartExport(); return(progress); }
public void StartRender(string outputFile, Size outputSize, ProcessPriorityClass processPriorityClass, Action <string, double, double, double> callbackAction = null, Action <double, Exception> finishAction = null) { var renderStart = DateTime.Now; // TODO: подкоректировать в соответствии с эксперементальными затратами на конвертацию. // Сейчас это вырезать эпизоды, нарисовать по ним текст+штрихи и в конце один раз все склеить. var globalExportProgress = GlobalExportProgress.BuildFromRenderOptionsSingleCommand(this.videoRenderOptions, callbackAction); try { try { if (File.Exists(outputFile)) { File.Delete(outputFile); } if (this.cancellationToken.IsCancellationRequested) { this.cancellationToken.ThrowIfCancellationRequested(); } var episodesRenderer = new EpisodesRendererAllFiltersInSingleCommandsTextAsImage(this.videoRenderOptions, outputFile, outputSize, processPriorityClass, globalExportProgress, this.cancellationToken); episodesRenderer.ProcessRenderOptions(); finishAction?.Invoke((DateTime.Now - renderStart).TotalMilliseconds, null); } catch (AggregateException aggregateException) { var isAggregateAndAllInnerAreCancelledExceptions = aggregateException.InnerExceptions.All(e => e is FFMpegCancelledException); if (isAggregateAndAllInnerAreCancelledExceptions) { var ffmpegOutputs = aggregateException.InnerExceptions.Cast <FFMpegCancelledException>().Select(v => v.AllFFMpegOutput); var aggregatedOutputs = ffmpegOutputs.Aggregate((t, c) => t + "\r\n" + c); throw new FFMpegCancelledException("Process was cancelled", $"Aggregated exceptions:\r\n{aggregatedOutputs}"); } throw; } catch (OperationCanceledException) { throw new FFMpegCancelledException("Process was cancelled", "No FFMPeg log available. Cancelled between FFMPeg calls."); } } catch (Exception ex) { if (File.Exists(outputFile)) { File.Delete(outputFile); } finishAction?.Invoke((DateTime.Now - renderStart).TotalMilliseconds, ex); } }