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)); } } }
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)); } } }); }
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); } }