From 7aff65f07b1dfaffaeed813518d02cf8c972f479 Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Thu, 18 Aug 2022 14:23:51 -0500 Subject: [PATCH] explicitly copy all audio streams with hls direct (#933) * ensure audio streams are always copied with hls direct * update changelog --- CHANGELOG.md | 3 + ErsatzTV.FFmpeg.Tests/PipelineBuilderTests.cs | 63 +++++++++++++++++++ ErsatzTV.FFmpeg/PipelineBuilder.cs | 10 +++ ErsatzTV.FFmpeg/State/AudioState.cs | 13 +++- 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdbb0c7b6..14dc85682 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Fixed +- When all audio streams are selected with `HLS Direct`, explicitly copy them without transcoding + - This only happens when the channel does not have a `Preferred Audio Language` ## [0.6.6-beta] - 2022-08-17 ### Fixed diff --git a/ErsatzTV.FFmpeg.Tests/PipelineBuilderTests.cs b/ErsatzTV.FFmpeg.Tests/PipelineBuilderTests.cs index 4ff22dfa3..fea8f86b1 100644 --- a/ErsatzTV.FFmpeg.Tests/PipelineBuilderTests.cs +++ b/ErsatzTV.FFmpeg.Tests/PipelineBuilderTests.cs @@ -251,6 +251,69 @@ public class PipelineGeneratorTests "-nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -i /tmp/whatever.mkv -map 0:1 -map 0:0 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -c:v copy -c:a copy -f mpegts -mpegts_flags +initial_discontinuity pipe:1"); } + [Test] + public void HlsDirect_Test_All_Audio_Streams() + { + var videoInputFile = new VideoInputFile( + "/tmp/whatever.mkv", + new List + { new(0, VideoFormat.H264, new PixelFormatYuv420P(), new FrameSize(1920, 1080), "16:9", "24", false) }); + + Option audioInputFile = Option.None; + + var desiredState = new FrameState( + true, + false, + VideoFormat.Copy, + new PixelFormatYuv420P(), + new FrameSize(1920, 1080), + new FrameSize(1920, 1080), + "16:9", + Option.None, + 2000, + 4000, + 90_000, + false); + + var ffmpegState = new FFmpegState( + false, + HardwareAccelerationMode.None, + HardwareAccelerationMode.None, + Option.None, + Option.None, + Option.None, + Option.None, + false, + Option.None, + Option.None, + Option.None, + OutputFormatKind.MpegTs, + Option.None, + Option.None, + 0, + Option.None); + + var builder = new PipelineBuilder( + new DefaultHardwareCapabilities(), + videoInputFile, + audioInputFile, + None, + None, + "", + "", + _logger); + FFmpegPipeline result = builder.Build(ffmpegState, desiredState); + + result.PipelineSteps.Should().HaveCountGreaterThan(0); + result.PipelineSteps.Should().Contain(ps => ps is EncoderCopyVideo); + result.PipelineSteps.Should().Contain(ps => ps is EncoderCopyAudio); + + string command = PrintCommand(videoInputFile, audioInputFile, None, None, result); + + command.Should().Be( + "-nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -i /tmp/whatever.mkv -map 0:a -map 0:0 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -c:v copy -c:a copy -f mpegts -mpegts_flags +initial_discontinuity pipe:1"); + } + [Test] public void Resize_Image_Test() { diff --git a/ErsatzTV.FFmpeg/PipelineBuilder.cs b/ErsatzTV.FFmpeg/PipelineBuilder.cs index 5b995b2d5..4d42bbaf3 100644 --- a/ErsatzTV.FFmpeg/PipelineBuilder.cs +++ b/ErsatzTV.FFmpeg/PipelineBuilder.cs @@ -539,6 +539,16 @@ public class PipelineBuilder // TODO: if all video filters are software, use software pixel format for hwaccel output // might be able to skip scale_cuda=format=whatever,hwdownload,format=whatever + if (_audioInputFile.IsNone) + { + // always need to specify audio codec so ffmpeg doesn't default to a codec we don't want + foreach (IEncoder step in AvailableEncoders.ForAudioFormat(AudioState.Copy, _logger)) + { + currentState = step.NextState(currentState); + _pipelineSteps.Add(step); + } + } + foreach (AudioInputFile audioInputFile in _audioInputFile) { // always need to specify audio codec so ffmpeg doesn't default to a codec we don't want diff --git a/ErsatzTV.FFmpeg/State/AudioState.cs b/ErsatzTV.FFmpeg/State/AudioState.cs index 215f49128..28265b771 100644 --- a/ErsatzTV.FFmpeg/State/AudioState.cs +++ b/ErsatzTV.FFmpeg/State/AudioState.cs @@ -7,4 +7,15 @@ public record AudioState( Option AudioBufferSize, Option AudioSampleRate, Option AudioDuration, - bool NormalizeLoudness); + bool NormalizeLoudness) +{ + public static readonly AudioState Copy = new( + Format.AudioFormat.Copy, + Option.None, + Option.None, + Option.None, + Option.None, + Option.None, + false + ); +}