fix bug with unsupported aac channel layouts (#893)
* fix bug with unsupported aac channel layouts * update dependencies
This commit is contained in:
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
## [Unreleased]
|
||||
### Fixed
|
||||
- Fix subtitle stream selection when subtitle language is different than audio language
|
||||
- Fix bug with unsupported AAC channel layouts
|
||||
|
||||
## [0.6.3-beta] - 2022-07-04
|
||||
### Fixed
|
||||
|
||||
@@ -148,14 +148,11 @@ public class FFmpegPlaybackSettingsCalculator
|
||||
result.AudioBitrate = ffmpegProfile.AudioBitrate;
|
||||
result.AudioBufferSize = ffmpegProfile.AudioBufferSize;
|
||||
|
||||
audioStream.IfSome(
|
||||
stream =>
|
||||
{
|
||||
if (stream.Channels != ffmpegProfile.AudioChannels)
|
||||
foreach (MediaStream _ in audioStream)
|
||||
{
|
||||
// this can be optimized out later, depending on the audio codec
|
||||
result.AudioChannels = ffmpegProfile.AudioChannels;
|
||||
}
|
||||
});
|
||||
|
||||
result.AudioSampleRate = ffmpegProfile.AudioSampleRate;
|
||||
result.AudioDuration = outPoint - inPoint;
|
||||
|
||||
@@ -86,7 +86,77 @@ public class PipelineGeneratorTests
|
||||
|
||||
string command = PrintCommand(videoInputFile, audioInputFile, None, None, result);
|
||||
command.Should().Be(
|
||||
"-threads 1 -nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -ss 00:00:01 -c:v h264 -re -i /tmp/whatever.mkv -map 0:1 -map 0:0 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -video_track_timescale 90000 -b:v 2000k -maxrate:v 2000k -bufsize:v 4000k -c:a aac -ac 2 -b:a 320k -maxrate:a 320k -bufsize:a 640k -ar 48k -c:v libx265 -tag:v hvc1 -x265-params log-level=error -f mpegts -mpegts_flags +initial_discontinuity pipe:1");
|
||||
"-threads 1 -nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -ss 00:00:01 -c:v h264 -re -i /tmp/whatever.mkv -map 0:1 -map 0:0 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -video_track_timescale 90000 -b:v 2000k -maxrate:v 2000k -bufsize:v 4000k -c:a aac -b:a 320k -maxrate:a 320k -bufsize:a 640k -ar 48k -c:v libx265 -tag:v hvc1 -x265-params log-level=error -f mpegts -mpegts_flags +initial_discontinuity pipe:1");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Aac_6_Channel_Should_Specify_Audio_Channels()
|
||||
{
|
||||
var videoInputFile = new VideoInputFile(
|
||||
"/tmp/whatever.mkv",
|
||||
new List<VideoStream>
|
||||
{ new(0, VideoFormat.H264, new PixelFormatYuv420P(), new FrameSize(1920, 1080), "24", false) });
|
||||
|
||||
var audioInputFile = new AudioInputFile(
|
||||
"/tmp/whatever.mkv",
|
||||
new List<AudioStream> { new(1, AudioFormat.Aac, 6) },
|
||||
new AudioState(
|
||||
AudioFormat.Aac,
|
||||
6,
|
||||
320,
|
||||
640,
|
||||
48,
|
||||
Option<TimeSpan>.None,
|
||||
false));
|
||||
|
||||
var desiredState = new FrameState(
|
||||
true,
|
||||
false,
|
||||
VideoFormat.Hevc,
|
||||
new PixelFormatYuv420P(),
|
||||
new FrameSize(1920, 1080),
|
||||
new FrameSize(1920, 1080),
|
||||
Option<int>.None,
|
||||
2000,
|
||||
4000,
|
||||
90_000,
|
||||
false);
|
||||
|
||||
var ffmpegState = new FFmpegState(
|
||||
false,
|
||||
HardwareAccelerationMode.None,
|
||||
HardwareAccelerationMode.None,
|
||||
Option<string>.None,
|
||||
Option<string>.None,
|
||||
TimeSpan.FromSeconds(1),
|
||||
Option<TimeSpan>.None,
|
||||
false,
|
||||
Option<string>.None,
|
||||
Option<string>.None,
|
||||
Option<string>.None,
|
||||
OutputFormatKind.MpegTs,
|
||||
Option<string>.None,
|
||||
Option<string>.None,
|
||||
0,
|
||||
Option<int>.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 EncoderLibx265);
|
||||
|
||||
string command = PrintCommand(videoInputFile, audioInputFile, None, None, result);
|
||||
command.Should().Be(
|
||||
"-threads 1 -nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -ss 00:00:01 -c:v h264 -re -i /tmp/whatever.mkv -map 0:1 -map 0:0 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -video_track_timescale 90000 -b:v 2000k -maxrate:v 2000k -bufsize:v 4000k -c:a aac -ac 6 -b:a 320k -maxrate:a 320k -bufsize:a 640k -ar 48k -c:v libx265 -tag:v hvc1 -x265-params log-level=error -f mpegts -mpegts_flags +initial_discontinuity pipe:1");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
namespace ErsatzTV.FFmpeg.Option;
|
||||
using ErsatzTV.FFmpeg.Format;
|
||||
|
||||
namespace ErsatzTV.FFmpeg.Option;
|
||||
|
||||
public class AudioChannelsOutputOption : OutputOption
|
||||
{
|
||||
private readonly int _channels;
|
||||
private readonly Option<string> _audioFormat;
|
||||
private readonly int _desiredChannels;
|
||||
private readonly int _sourceChannels;
|
||||
|
||||
public AudioChannelsOutputOption(int channels) => _channels = channels;
|
||||
|
||||
public override IList<string> OutputOptions => new List<string> { "-ac", _channels.ToString() };
|
||||
public AudioChannelsOutputOption(Option<string> audioFormat, int sourceChannels, int desiredChannels)
|
||||
{
|
||||
_audioFormat = audioFormat;
|
||||
_sourceChannels = sourceChannels;
|
||||
_desiredChannels = desiredChannels;
|
||||
}
|
||||
|
||||
public override IList<string> OutputOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_sourceChannels != _desiredChannels || _audioFormat == Some(AudioFormat.Aac) && _desiredChannels > 2)
|
||||
{
|
||||
return new List<string>
|
||||
{
|
||||
"-ac", _desiredChannels.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,9 +538,16 @@ public class PipelineBuilder
|
||||
_pipelineSteps.Add(step);
|
||||
}
|
||||
|
||||
foreach (AudioStream audioStream in audioInputFile.AudioStreams.HeadOrNone())
|
||||
{
|
||||
foreach (int desiredAudioChannels in audioInputFile.DesiredState.AudioChannels)
|
||||
{
|
||||
_pipelineSteps.Add(new AudioChannelsOutputOption(desiredAudioChannels));
|
||||
_pipelineSteps.Add(
|
||||
new AudioChannelsOutputOption(
|
||||
audioInputFile.DesiredState.AudioFormat,
|
||||
audioStream.Channels,
|
||||
desiredAudioChannels));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (int desiredBitrate in audioInputFile.DesiredState.AudioBitrate)
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
<PackageReference Include="Lucene.Net" Version="4.8.0-beta00016" />
|
||||
<PackageReference Include="Lucene.Net.Analysis.Common" Version="4.8.0-beta00016" />
|
||||
<PackageReference Include="Lucene.Net.QueryParser" Version="4.8.0-beta00016" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.6">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.2.32">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -57,14 +57,14 @@
|
||||
<PackageReference Include="Bugsnag.AspNet.Core" Version="3.1.0" />
|
||||
<PackageReference Include="FluentValidation" Version="11.1.0" />
|
||||
<PackageReference Include="FluentValidation.AspNetCore" Version="11.1.2" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="7.1.512" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="7.1.542" />
|
||||
<PackageReference Include="LanguageExt.Core" Version="4.2.9" />
|
||||
<PackageReference Include="Markdig" Version="0.30.2" />
|
||||
<PackageReference Include="MediatR.Courier.DependencyInjection" Version="5.0.0" />
|
||||
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.6" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.6">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
Reference in New Issue
Block a user