test(matching): cover original vs default audio-track selection

New metadata_multi_audio fixture (English original + Spanish default
tracks) drives tests for get_best_audio_format, get_best_combined_format
and the video+audio split path under both preference values, plus a
regression guard that marker-free metadata is unaffected and a unit test
for the new parse_media_format flags.

Refs #1468
This commit is contained in:
masterdot
2026-09-07 20:10:33 +02:00
parent a7dc72d9aa
commit 6bcd1891de
4 changed files with 270 additions and 1 deletions

View File

@@ -0,0 +1,174 @@
{
"id": "multiaudio",
"channel_id": "testchannelid",
"title": "multi audio track title",
"upload_date": "20260101",
"duration": 300.0,
"uploader": "test uploader",
"playlist_title": "test playlist",
"thumbnail": "https://example.com/maxresdefault.webp",
"subtitles": {},
"automatic_captions": {},
"formats": [
{
"format_id": "251-en",
"ext": "webm",
"vcodec": "none",
"acodec": "opus",
"abr": 160,
"asr": 48000,
"fps": null,
"height": null,
"width": null,
"tbr": 156.0,
"language": "en",
"format_note": "English original, medium (original)",
"format": "251-en - audio only (English original, medium) (original)",
"protocol": "https"
},
{
"format_id": "251-es",
"ext": "webm",
"vcodec": "none",
"acodec": "opus",
"abr": 160,
"asr": 48000,
"fps": null,
"height": null,
"width": null,
"tbr": 155.0,
"language": "es",
"format_note": "Spanish (Spain) (default), medium (default)",
"format": "251-es - audio only (Spanish (Spain) (default), medium) (default)",
"protocol": "https"
},
{
"format_id": "140-en",
"ext": "m4a",
"vcodec": "none",
"acodec": "mp4a.40.2",
"abr": 128,
"asr": 44100,
"fps": null,
"height": null,
"width": null,
"tbr": 128.0,
"language": "en",
"format_note": "English original, low (original)",
"format": "140-en - audio only (English original, low) (original)",
"protocol": "https"
},
{
"format_id": "140-es",
"ext": "m4a",
"vcodec": "none",
"acodec": "mp4a.40.2",
"abr": 128,
"asr": 44100,
"fps": null,
"height": null,
"width": null,
"tbr": 127.0,
"language": "es",
"format_note": "Spanish (Spain) (default), low (default)",
"format": "140-es - audio only (Spanish (Spain) (default), low) (default)",
"protocol": "https"
},
{
"format_id": "18-en",
"ext": "mp4",
"vcodec": "avc1.42001E",
"acodec": "mp4a.40.2",
"abr": 96,
"asr": 44100,
"fps": 30,
"height": 360,
"width": 640,
"tbr": 620.0,
"language": "en",
"format_note": "English original, 360p (original)",
"format": "18-en - 640x360 (360p) (original)",
"protocol": "https"
},
{
"format_id": "18-es",
"ext": "mp4",
"vcodec": "avc1.42001E",
"acodec": "mp4a.40.2",
"abr": 96,
"asr": 44100,
"fps": 30,
"height": 360,
"width": 640,
"tbr": 618.0,
"language": "es",
"format_note": "Spanish (Spain) (default), 360p (default)",
"format": "18-es - 640x360 (360p) (default)",
"protocol": "https"
},
{
"format_id": "22-en",
"ext": "mp4",
"vcodec": "avc1.64001F",
"acodec": "mp4a.40.2",
"abr": 192,
"asr": 44100,
"fps": 30,
"height": 720,
"width": 1280,
"tbr": 2100.0,
"language": "en",
"format_note": "English original, 720p (original)",
"format": "22-en - 1280x720 (720p) (original)",
"protocol": "https"
},
{
"format_id": "22-es",
"ext": "mp4",
"vcodec": "avc1.64001F",
"acodec": "mp4a.40.2",
"abr": 192,
"asr": 44100,
"fps": 30,
"height": 720,
"width": 1280,
"tbr": 2098.0,
"language": "es",
"format_note": "Spanish (Spain) (default), 720p (default)",
"format": "22-es - 1280x720 (720p) (default)",
"protocol": "https"
},
{
"format_id": "137",
"ext": "mp4",
"vcodec": "avc1.640028",
"acodec": "none",
"abr": null,
"asr": null,
"fps": 30,
"height": 1080,
"width": 1920,
"tbr": 4000.0,
"language": null,
"format_note": "1080p",
"format": "137 - 1920x1080 (1080p)",
"protocol": "https"
},
{
"format_id": "248",
"ext": "webm",
"vcodec": "vp9",
"acodec": "none",
"abr": null,
"asr": null,
"fps": 30,
"height": 1080,
"width": 1920,
"tbr": 3000.0,
"language": null,
"format_note": "1080p",
"format": "248 - 1920x1080 (1080p)",
"protocol": "https"
}
]
}

View File

@@ -16,6 +16,7 @@ _TESTDATA_FILES = {
"60fps": "metadata_60fps.json",
"60fps+hdr": "metadata_60fps_hdr.json",
"20230629": "metadata_2023-06-29.json",
"multi_audio": "metadata_multi_audio.json",
"issue499_1080p50": "metadata_issue_499_1080p50.json",
"issue499_premium": "metadata_issue_499_premium.json",
"expected_nfo": "expected_nfo.xml",

View File

@@ -2,10 +2,11 @@ import logging
from django.test import TestCase
from sync.models import Source, Media
from sync.choices import (
Val, Fallback, SourceResolution,
Val, AudioTrack, Fallback, SourceResolution,
YouTube_AudioCodec, YouTube_VideoCodec,
YouTube_SourceType,
)
from sync.utils import parse_media_format
from .fixtures import all_test_metadata
@@ -313,6 +314,96 @@ class FormatMatchingTestCase(TestCase):
self.assertEqual(format_code, expected_format_code)
self.assertEqual(match_type, expected_match_type)
def test_parse_media_format_original_default_flags(self):
original = parse_media_format({
'format_id': 'a', 'format_note': 'English original, medium (original)',
'vcodec': 'none', 'acodec': 'opus',
})
default = parse_media_format({
'format_id': 'b', 'format_note': 'Spanish (Spain) (default), medium (default)',
'vcodec': 'none', 'acodec': 'opus',
})
plain = parse_media_format({
'format_id': 'c', 'format_note': 'medium',
'vcodec': 'none', 'acodec': 'opus',
})
self.assertEqual((original['is_original'], original['is_default']), (True, False))
self.assertEqual((default['is_original'], default['is_default']), (False, True))
self.assertEqual((plain['is_original'], plain['is_default']), (False, False))
def test_audio_track_preference_audio_only(self):
self.source.fallback = Val(Fallback.FAIL)
self.source.source_resolution = Val(SourceResolution.AUDIO)
self.media.metadata = all_test_metadata['multi_audio']
self.media.save()
expected_matches = {
# (acodec, prefer_audio_track): (match_type, code)
(Val(YouTube_AudioCodec.OPUS), Val(AudioTrack.ORIGINAL)): (True, '251-en'),
(Val(YouTube_AudioCodec.OPUS), Val(AudioTrack.DEFAULT)): (True, '251-es'),
(Val(YouTube_AudioCodec.MP4A), Val(AudioTrack.ORIGINAL)): (True, '140-en'),
(Val(YouTube_AudioCodec.MP4A), Val(AudioTrack.DEFAULT)): (True, '140-es'),
}
for params, expected in expected_matches.items():
acodec, prefer_audio_track = params
self.source.source_acodec = acodec
self.source.prefer_audio_track = prefer_audio_track
self.assertEqual(self.media.get_best_audio_format(), expected,
msg=f'{acodec} / {prefer_audio_track}')
def test_audio_track_preference_combined(self):
self.source.fallback = Val(Fallback.FAIL)
self.source.source_vcodec = Val(YouTube_VideoCodec.AVC1)
self.source.source_acodec = Val(YouTube_AudioCodec.MP4A)
self.source.prefer_60fps = False
self.source.prefer_hdr = False
self.media.metadata = all_test_metadata['multi_audio']
self.media.save()
expected_matches = {
# (resolution, prefer_audio_track): (match_type, code)
('360p', Val(AudioTrack.ORIGINAL)): (True, '18-en'),
('360p', Val(AudioTrack.DEFAULT)): (True, '18-es'),
('720p', Val(AudioTrack.ORIGINAL)): (True, '22-en'),
('720p', Val(AudioTrack.DEFAULT)): (True, '22-es'),
}
for params, expected in expected_matches.items():
resolution, prefer_audio_track = params
self.source.source_resolution = resolution
self.source.prefer_audio_track = prefer_audio_track
self.assertEqual(self.media.get_best_combined_format(), expected,
msg=f'{resolution} / {prefer_audio_track}')
def test_audio_track_preference_split_video_plus_audio(self):
self.source.fallback = Val(Fallback.NEXT_BEST_RESOLUTION)
self.source.source_resolution = Val(SourceResolution.VIDEO_1080P)
self.source.source_vcodec = Val(YouTube_VideoCodec.VP9)
self.source.source_acodec = Val(YouTube_AudioCodec.OPUS)
self.media.metadata = all_test_metadata['multi_audio']
self.media.save()
self.source.prefer_audio_track = Val(AudioTrack.ORIGINAL)
self.assertEqual(self.media.get_format_str(), '248+251-en')
self.source.prefer_audio_track = Val(AudioTrack.DEFAULT)
self.assertEqual(self.media.get_format_str(), '248+251-es')
def test_audio_track_preference_no_marker_is_noop(self):
# 'boring' metadata carries no (original)/(default) markers, so the
# preference must not change what gets matched
self.source.fallback = Val(Fallback.FAIL)
self.media.metadata = all_test_metadata['boring']
self.media.save()
for prefer in (Val(AudioTrack.ORIGINAL), Val(AudioTrack.DEFAULT)):
self.source.prefer_audio_track = prefer
self.source.source_resolution = Val(SourceResolution.AUDIO)
self.source.source_acodec = Val(YouTube_AudioCodec.OPUS)
self.assertEqual(self.media.get_best_audio_format(), (True, '251'), msg=prefer)
self.source.source_acodec = Val(YouTube_AudioCodec.MP4A)
self.assertEqual(self.media.get_best_audio_format(), (True, '140'), msg=prefer)
self.source.source_resolution = Val(SourceResolution.VIDEO_720P)
self.source.source_vcodec = Val(YouTube_VideoCodec.AVC1)
self.source.source_acodec = Val(YouTube_AudioCodec.MP4A)
self.source.prefer_60fps = False
self.source.prefer_hdr = False
self.assertEqual(self.media.get_best_combined_format(), (True, '22'), msg=prefer)
def test_video_exact_format_matching(self):
self.source.fallback = Val(Fallback.FAIL)
# Test no 60fps, no HDR metadata

View File

@@ -185,6 +185,7 @@ class FrontEndTestCase(TestCase):
'source_acodec': 'OPUS',
'prefer_60fps': False,
'prefer_hdr': False,
'prefer_audio_track': 'original',
'fallback': 'f',
'sponsorblock_categories': data_categories,
'sub_langs': 'en',
@@ -246,6 +247,7 @@ class FrontEndTestCase(TestCase):
'source_acodec': Val(YouTube_AudioCodec.OPUS),
'prefer_60fps': False,
'prefer_hdr': False,
'prefer_audio_track': 'original',
'fallback': Val(Fallback.FAIL),
'sponsorblock_categories': data_categories,
'sub_langs': 'en',
@@ -283,6 +285,7 @@ class FrontEndTestCase(TestCase):
'source_acodec': Val(YouTube_AudioCodec.OPUS),
'prefer_60fps': False,
'prefer_hdr': False,
'prefer_audio_track': 'original',
'fallback': Val(Fallback.FAIL),
'sponsorblock_categories': data_categories,
'sub_langs': 'en',