fix: honor HD minimum when falling back formats
Some checks failed
Build TubeSync image / container (push) Failing after 2m48s
Some checks failed
Build TubeSync image / container (push) Failing after 2m48s
This commit is contained in:
@@ -202,7 +202,13 @@ def get_best_video_format(media):
|
|||||||
if not media.source.can_fallback:
|
if not media.source.can_fallback:
|
||||||
# Can't fallback
|
# Can't fallback
|
||||||
return False, False
|
return False, False
|
||||||
# Find the next-best format matches by height
|
# Find the next-best format matches by height. If the source requires
|
||||||
|
# an HD fallback, exclude sub-HD candidates before preference ranking;
|
||||||
|
# otherwise a preferred-codec 360p stream can be selected and rejected
|
||||||
|
# later even when a valid 720p stream is available.
|
||||||
|
fallback_min_height = min_height
|
||||||
|
if media.source.fallback == Val(Fallback.REQUIRE_HD):
|
||||||
|
fallback_min_height = max(fallback_min_height, fallback_hd_cutoff)
|
||||||
for fmt in media.iter_formats():
|
for fmt in media.iter_formats():
|
||||||
# If the format has an audio stream, skip it
|
# If the format has an audio stream, skip it
|
||||||
if fmt['acodec'] is not None:
|
if fmt['acodec'] is not None:
|
||||||
@@ -212,7 +218,7 @@ def get_best_video_format(media):
|
|||||||
if '-sr' in fmt['id']:
|
if '-sr' in fmt['id']:
|
||||||
continue
|
continue
|
||||||
accept_height = (
|
accept_height = (
|
||||||
fmt['height'] >= min_height and
|
fmt['height'] >= fallback_min_height and
|
||||||
fmt['height'] <= source_resolution_height
|
fmt['height'] <= source_resolution_height
|
||||||
)
|
)
|
||||||
if accept_height:
|
if accept_height:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from sync.models import Source, Media
|
from sync.models import Source, Media
|
||||||
@@ -384,6 +385,36 @@ class FormatMatchingTestCase(TestCase):
|
|||||||
self.source.audio_track = Val(AudioTrack.DEFAULT)
|
self.source.audio_track = Val(AudioTrack.DEFAULT)
|
||||||
self.assertEqual(self.media.get_format_str(), '248+251-es')
|
self.assertEqual(self.media.get_format_str(), '248+251-es')
|
||||||
|
|
||||||
|
def test_require_hd_fallback_ignores_sub_hd_preferred_codec(self):
|
||||||
|
self.source.fallback = Val(Fallback.REQUIRE_HD)
|
||||||
|
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.source.prefer_60fps = True
|
||||||
|
self.source.prefer_hdr = False
|
||||||
|
self.media.metadata = json.dumps({
|
||||||
|
'formats': [
|
||||||
|
{
|
||||||
|
'format_id': '136', 'format_note': '720p', 'height': 720,
|
||||||
|
'fps': 24, 'vcodec': 'avc1.4d401f', 'acodec': 'none',
|
||||||
|
'tbr': 1000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'format_id': '243', 'format_note': '360p', 'height': 360,
|
||||||
|
'fps': 24, 'vcodec': 'vp9', 'acodec': 'none',
|
||||||
|
'tbr': 500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'format_id': '251', 'format_note': 'medium',
|
||||||
|
'vcodec': 'none', 'acodec': 'opus', 'tbr': 120,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
self.media.save()
|
||||||
|
|
||||||
|
self.assertEqual(self.media.get_best_video_format(), (False, '136'))
|
||||||
|
self.assertEqual(self.media.get_format_str(), '136+251')
|
||||||
|
|
||||||
def test_audio_track_preference_no_marker_is_noop(self):
|
def test_audio_track_preference_no_marker_is_noop(self):
|
||||||
# 'boring' metadata carries no (original)/(default) markers, so the
|
# 'boring' metadata carries no (original)/(default) markers, so the
|
||||||
# preference must not change what gets matched
|
# preference must not change what gets matched
|
||||||
|
|||||||
Reference in New Issue
Block a user