Esempio n. 1
0
        private void CutAndDrawTextAndDrawImageAndApplyTimeWarp(
            FFMpeg ffMpeg,
            FFMpegCutOptions cutOptions,
            TemporaryFilesStorage temporaryFilesStorage)
        {
            EnsureFileDoesNotExist(cutOptions.OutputFile);
            var extensionForResultFile = Path.GetExtension(cutOptions.OutputFile);
            var imagesExist            = cutOptions.ImagesTimeTable != null && cutOptions.ImagesTimeTable.Any();
            var timeWarpExists         = cutOptions.TimeWarps != null && cutOptions.TimeWarps.Any();

            if (!cutOptions.OverlayText.Any() && !imagesExist && !timeWarpExists)
            {
                ffMpeg.Cut(cutOptions);
                return;
            }
            var intermediateFile1 = temporaryFilesStorage.GetIntermediateFile(extensionForResultFile);

            ffMpeg.Cut(cutOptions.CloneWithOtherOutput(intermediateFile1));

            if (cutOptions.OverlayText.Any())
            {
                var intermediateFile2 = (imagesExist || timeWarpExists) ? temporaryFilesStorage.GetIntermediateFile(extensionForResultFile) : cutOptions.OutputFile;
                ffMpeg.DrawText(intermediateFile1, cutOptions.OverlayText, intermediateFile2, cutOptions.GlobalExportProgress);
                File.Delete(intermediateFile1);
                intermediateFile1 = intermediateFile2;
            }
            if (imagesExist)
            {
                var intermediateFile3 = timeWarpExists ? temporaryFilesStorage.GetIntermediateFile(extensionForResultFile) : cutOptions.OutputFile;
                ffMpeg.DrawImage(intermediateFile1, cutOptions.ImagesTimeTable, intermediateFile3, cutOptions.GlobalExportProgress);
                File.Delete(intermediateFile1);
                intermediateFile1 = intermediateFile3;
            }
            if (timeWarpExists)
            {
                ffMpeg.ApplyTimeWarp(intermediateFile1, cutOptions.TimeWarps, cutOptions.OutputFile, this.globalExportProgress);
                File.Delete(intermediateFile1);
            }
        }
Esempio n. 2
0
        protected virtual void CutAndConcatAndRenderTextAndImageAndTimeWarps(List <FFMpegCutInfo> cutInfos, FFMpeg ffMpeg, TemporaryFilesStorage temporaryFilesStorage)
        {
            var textTimeTableForConcatenatedEpisodeGroups   = new List <TextTimeRecord>();
            var imagesTimeTableForConcatenatedEpisodeGroups = new List <DrawImageTimeRecord>();
            var timeWarpForConcatenatedEpisodeGroups        = new List <TimeWarpRecord>();
            var currentPosition = 0.0;

            foreach (var videoRenderOption in this.VideoRenderOptions)
            {
                if (videoRenderOption.OverlayTextTimeTable != null && videoRenderOption.OverlayTextTimeTable.Any())
                {
                    textTimeTableForConcatenatedEpisodeGroups.AddRange(
                        videoRenderOption.OverlayTextTimeTable.Select(v => new TextTimeRecord(v.Lines,
                                                                                              v.StartSecond + currentPosition,
                                                                                              v.EndSecond + currentPosition)));
                }
                if (videoRenderOption.ImagesTimeTable != null && videoRenderOption.ImagesTimeTable.Any())
                {
                    imagesTimeTableForConcatenatedEpisodeGroups.AddRange(
                        videoRenderOption.ImagesTimeTable.Select(v => new DrawImageTimeRecord(v.ImageData,
                                                                                              v.LeftOffset,
                                                                                              v.TopOffset,
                                                                                              v.ImageStartSecond + currentPosition,
                                                                                              v.ImageEndSecond + currentPosition)));
                }
                if (videoRenderOption.TimeWarpSettings != null && videoRenderOption.TimeWarpSettings.Any())
                {
                    timeWarpForConcatenatedEpisodeGroups.AddRange(
                        videoRenderOption.TimeWarpSettings.Select(v =>
                                                                  new TimeWarpRecord(v.StartSecond + currentPosition, v.EndSecond + currentPosition, v.Coefficient)));
                }
                currentPosition += videoRenderOption.DurationSeconds;
            }

            var pathForConcatenatedEpisodes = timeWarpForConcatenatedEpisodeGroups.Any()
                    ? temporaryFilesStorage.GetIntermediateFile(Path.GetExtension(this.outputFile))
                    : this.outputFile;

            ffMpeg.CutAndConcatAndDrawImagesAndText(
                cutInfos,
                imagesTimeTableForConcatenatedEpisodeGroups,
                textTimeTableForConcatenatedEpisodeGroups,
                this.OutputSize,
                pathForConcatenatedEpisodes,
                this.globalExportProgress);

            if (timeWarpForConcatenatedEpisodeGroups.Any())
            {
                ffMpeg.ApplyTimeWarp(pathForConcatenatedEpisodes, timeWarpForConcatenatedEpisodeGroups, this.outputFile, this.globalExportProgress);
            }
        }
Esempio n. 3
0
        public void ProcessRenderOptions()
        {
            using (var temporaryFilesStorage = new TemporaryFilesStorage())
            {
                var subject = new Subject <double>();

                // ReSharper disable once ImpureMethodCallOnReadonlyValueField
                // Внутри происходит регистрация через ссылку на родительский CancellationTokenSource.
                this.cancellationToken.Register(() => subject.OnNext(0));
                using (var ffMpeg = new FFMpeg(temporaryFilesStorage, this.rendererProcessPriorityClass, subject.AsObservable()))
                {
                    ffMpeg.LogMessage($"Started rendering of {this.outputFile}", string.Empty);

                    var cutOptionsBuilder = new CutOptionsBuilder(this.videoRenderOptions, this.outputSize, this.globalExportProgress, temporaryFilesStorage, false);

                    Parallel.ForEach(
                        cutOptionsBuilder.CutOptions,
                        cutOptions =>
                    {
                        if (this.cancellationToken.IsCancellationRequested)
                        {
                            this.cancellationToken.ThrowIfCancellationRequested();
                        }

                        // ReSharper disable once AccessToDisposedClosure
                        // выполнение замыкания всегда будет происходить до Dispose.
                        this.CutAndDrawTextAndDrawImageAndApplyTimeWarp(ffMpeg, cutOptions, temporaryFilesStorage);
                    });
                    if (cutOptionsBuilder.FilesToConcat.Count == 1)
                    {
                        File.Move(cutOptionsBuilder.FilesToConcat.Single(), this.outputFile);
                    }
                    else
                    {
                        if (this.cancellationToken.IsCancellationRequested)
                        {
                            this.cancellationToken.ThrowIfCancellationRequested();
                        }

                        var tempFileForConcat = temporaryFilesStorage.GetIntermediateFile(cutOptionsBuilder.OutputExtension);
                        ffMpeg.Concat(tempFileForConcat, this.outputSize, "copy", "copy", this.globalExportProgress, cutOptionsBuilder.FilesToConcat.ToArray());
                        ffMpeg.Convert(tempFileForConcat, this.outputFile, this.globalExportProgress);
                    }
                }
            }
        }