예제 #1
0
        public void GenerateDash_WithLiveStreamingProfile_ProducesCorrectDashEncodeResult()
        {
            string outputFilename = "outputlive";

            var options = new H264EncodeOptions
            {
                AdditionalMP4BoxFlags = new List <string>()
                {
                    "-profile \"dashavc264:live\"",
                    "-bs-switching no"
                }
            };

            Encoder    encoder = new Encoder(ffmpegPath, ffprobePath, mp4boxPath);
            DashConfig config  = new DashConfig("testfile.ogg", RunPath, SubtitleQualities, outputFilename)
            {
                Options = options
            };

            try
            {
                encodeResult = encoder.GenerateDash(config, encoder.ProbeFile(config.InputFilePath, out _));

                Assert.NotNull(encodeResult.DashFilePath);
                Assert.NotNull(encodeResult.DashFileContent);
            }
            finally
            {
                foreach (var file in Directory.EnumerateFiles(RunPath, $"{outputFilename}_*"))
                {
                    File.Delete(Path.Combine(RunPath, file));
                }
            }
        }
예제 #2
0
        public void TestMP4BoxLiveProfile()
        {
            TestCleanup((results) =>
            {
                string runPath  = Path.Combine(Environment.CurrentDirectory, @"..\..\..\");
                string filename = "outputlive";
                try
                {
                    IEnumerable <EncodeStageProgress> progress = null;
                    var options = new H264EncodeOptions
                    {
                        AdditionalMP4BoxFlags = new List <string>()
                        {
                            "-profile \"dashavc264:live\"",
                            "-bs-switching no"
                        }
                    };

                    Encoder c          = new Encoder();
                    DashEncodeResult s = c.GenerateDash(
                        options: options,
                        inFile: Path.Combine(runPath, "testfile.ogg"),
                        outFilename: filename,
                        framerate: 30,
                        keyframeInterval: 90,
                        qualities: new List <Quality>
                    {
                        new Quality(1280, 720, 1280, "fast"),
                        new Quality(640, 480, 768, "fast"),
                    },
                        outDirectory: runPath,
                        progress: new NaiveProgress <IEnumerable <EncodeStageProgress> >(x => { progress = x; }));
                    results.Add(s);

                    Assert.NotNull(s.DashFilePath);
                    Assert.NotNull(s.DashFileContent);
                    Assert.Equal(1.0, progress.Where(x => x.Name == "Encode").Select(y => y.Progress).Single());
                    Assert.Equal(1.0, progress.Where(x => x.Name == "DASHify").Select(y => y.Progress).Single());
                    Assert.Equal(1.0, progress.Where(x => x.Name == "Post Process").Select(y => y.Progress).Single());
                }
                finally
                {
                    foreach (var file in Directory.EnumerateFiles(runPath, $"{filename}_*"))
                    {
                        File.Delete(Path.Combine(runPath, file));
                    }
                }
            });
        }
예제 #3
0
        protected override void Process(IConversionItem item)
        {
            if (item.CancellationToken.IsCancellationRequested)
            {
                HandleCancel(item);
                return;
            }

            var options = new H264EncodeOptions();

            switch (item.Tune)
            {
            case Tune.Film:
                options.AdditionalVideoFlags.Add("-tune film");
                break;

            case Tune.Grain:
                options.AdditionalVideoFlags.Add("-tune grain");
                break;

            case Tune.Animation:
                options.AdditionalVideoFlags.Add("-tune animation");
                break;
            }

            log.LogInformation($"Processing item {item.SourcePath}");

            try
            {
                var probeData  = encoder.ProbeFile(item.SourcePath, out _);
                var dashConfig = new DashConfig(item.SourcePath, item.OutputPath, item.Quality, item.OutputBaseFilename)
                {
                    EnableStreamCopying = true,
                    Framerate           = item.Framerate,
                    Options             = options
                };
                if (item.DownmixAudio)
                {
                    dashConfig.AudioConfig = new AudioConfig()
                    {
                        DownmixMode = DownmixMode.Default
                    };
                }

                var dashResult = encoder.GenerateDash(dashConfig, probeData,
                                                      progress: new NaiveProgress <double>((x) =>
                {
                    item.Progress = new[] { new DescribedProgress("Conversion", x) };
                }),
                                                      cancel: item.CancellationToken.Token);

                if (dashResult == null)
                {
                    throw new Exception("Failed to convert item. Got null from generator. Check the ffmpeg/mp4box log.");
                }

                item.CompletionAction.Invoke(item, dashResult);

                completeItems.Add(item);
            }
            catch (FFMpegFailedException ex) when(ex is FFMpegFailedException || ex is Mp4boxFailedException || ex is DashManifestNotCreatedException)
            {
                if (ex.InnerException is OperationCanceledException)
                {
                    log.LogInformation($"Task Cancelled: {item.SourcePath}");
                    HandleCancel(item);
                    return;
                }

                var logItems = new List <string>()
                {
                    $"Failed to convert {item.SourcePath}",
                    $"ffmpeg command: {ex.FFmpegCommand?.RenderedCommand ?? "Unavailable"}"
                };
                string failureStage = "Unknown";

                switch (ex)
                {
                case DashManifestNotCreatedException dex:
                    failureStage = "Manifest generation";
                    break;

                case Mp4boxFailedException mpex:
                    failureStage = "DASHing/MP4Box";
                    logItems.Add($"MP4Box command: {mpex.MP4BoxCommand.RenderedCommand}");
                    break;

                case FFMpegFailedException ffex:
                    failureStage = "Encoding/ffmpeg";
                    break;

                default:
                    break;
                }

                logItems.Add($"Stack trace: {ex}");
                if (ex.Log != null && ex.Log.Length > 0)
                {
                    logItems.Add($"Process log: {ex.Log}");
                }

                string fullLog = string.Join('\n', logItems);

                log.LogWarning(fullLog);

                item.ErrorReason = $"Failed at step: {failureStage}. Message: {ex.Message}";
                item.ErrorDetail = fullLog;
                completeItems.Add(item);
            }
            catch (OperationCanceledException)
            {
                log.LogInformation($"Task Cancelled: {item.SourcePath}");
                HandleCancel(item);
            }
        }