fix: use ADTS for AAC transcoding, temporarily exclude AAC from transcode decisions (#5167)
* fix: use ADTS format for AAC transcoding to avoid silent output on ffmpeg 8.0+ The fragmented MP4 muxer (`-f ipod -movflags frag_keyframe+empty_moov`) produces corrupt/silent audio when ffmpeg pipes to stdout, confirmed on ffmpeg 8.0+. The moof atom offset values are zeroed out in pipe mode, causing AAC decoder errors. Switch to `-f adts` (raw AAC framing) which works reliably via pipe and is widely supported by clients including UPnP/Sonos devices. * fix: exclude AAC from transcode decision, as it is not working for Sonos. Signed-off-by: Deluan <deluan@navidrome.org> --------- Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
@@ -180,6 +180,29 @@ var _ = Describe("Transcode endpoints", func() {
|
||||
Expect(resp.TranscodeDecision.SourceStream.AudioBitrate).To(Equal(int32(320_000)))
|
||||
})
|
||||
|
||||
It("filters AAC from transcoding profiles", func() {
|
||||
mockMFRepo.SetData(model.MediaFiles{
|
||||
{ID: "song-1", Suffix: "opus", Codec: "opus", BitRate: 128, Channels: 2, SampleRate: 48000},
|
||||
})
|
||||
mockTD.decision = &stream.TranscodeDecision{MediaID: "song-1", CanDirectPlay: true}
|
||||
mockTD.token = "token"
|
||||
|
||||
body := `{
|
||||
"transcodingProfiles": [
|
||||
{"container": "aac", "audioCodec": "aac", "protocol": "http"},
|
||||
{"container": "mp3", "audioCodec": "mp3", "protocol": "http"},
|
||||
{"container": "m4a", "audioCodec": "aac", "protocol": "http"}
|
||||
]
|
||||
}`
|
||||
r := newJSONPostRequest("mediaId=song-1&mediaType=song", body)
|
||||
_, err := router.GetTranscodeDecision(w, r)
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(mockTD.capturedClient).ToNot(BeNil())
|
||||
Expect(mockTD.capturedClient.TranscodingProfiles).To(HaveLen(1))
|
||||
Expect(mockTD.capturedClient.TranscodingProfiles[0].AudioCodec).To(Equal("mp3"))
|
||||
})
|
||||
|
||||
It("includes transcode stream when transcoding", func() {
|
||||
mockMFRepo.SetData(model.MediaFiles{
|
||||
{ID: "song-2", Suffix: "flac", Codec: "FLAC", BitRate: 1000, Channels: 2, SampleRate: 96000, BitDepth: 24},
|
||||
@@ -354,14 +377,16 @@ func newJSONPostRequest(queryParams string, jsonBody string) *http.Request {
|
||||
|
||||
// mockTranscodeDecision is a test double for stream.TranscodeDecider
|
||||
type mockTranscodeDecision struct {
|
||||
decision *stream.TranscodeDecision
|
||||
token string
|
||||
tokenErr error
|
||||
resolvedReq stream.Request
|
||||
resolveErr error
|
||||
decision *stream.TranscodeDecision
|
||||
token string
|
||||
tokenErr error
|
||||
resolvedReq stream.Request
|
||||
resolveErr error
|
||||
capturedClient *stream.ClientInfo
|
||||
}
|
||||
|
||||
func (m *mockTranscodeDecision) MakeDecision(_ context.Context, _ *model.MediaFile, _ *stream.ClientInfo, _ stream.TranscodeOptions) (*stream.TranscodeDecision, error) {
|
||||
func (m *mockTranscodeDecision) MakeDecision(_ context.Context, _ *model.MediaFile, ci *stream.ClientInfo, _ stream.TranscodeOptions) (*stream.TranscodeDecision, error) {
|
||||
m.capturedClient = ci
|
||||
if m.decision != nil {
|
||||
return m.decision, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user