fix: Fixed suffix when quality is 'best'

This commit is contained in:
TonyBlur 2026-05-06 14:03:05 +08:00
parent de11f5c638
commit 8723ab0afe
3 changed files with 132 additions and 45 deletions

View file

@ -58,8 +58,6 @@ jobs:
needs: quality-checks
if: github.event_name == 'push'
runs-on: ubuntu-latest
outputs:
ghcr_repo: ${{ steps.ghcr-repo.outputs.ghcr_repo }}
steps:
-
name: Get current date
@ -175,11 +173,12 @@ jobs:
id: release_body
env:
DOCKERHUB_REPO: ${{ secrets.DOCKERHUB_REPOSITORY }}
GHCR_REPO: ${{ needs.dockerhub-build-push.outputs.ghcr_repo }}
GHCR_REPO_RAW: ghcr.io/${{ github.repository }}
DATE: ${{ steps.date.outputs.date }}
HAS_COMMITS: ${{ steps.commits.outputs.has_commits }}
COMMITS: ${{ steps.commits.outputs.commits }}
run: |
GHCR_REPO=$(echo "$GHCR_REPO_RAW" | tr '[:upper:]' '[:lower:]')
{
echo '## Docker Images'
echo ''

View file

@ -38,8 +38,10 @@ sys.modules.setdefault("yt_dlp.utils", fake_utils)
from ytdl import (
DownloadInfo,
_codec_suffix_value,
_compact_persisted_entry,
_convert_srt_to_txt_file,
_quality_suffix_value,
_resolve_outtmpl_fields,
_sanitize_entry_for_pickle,
_sanitize_path_component,
@ -181,6 +183,74 @@ Second line
self.assertIn("Second line", content)
class QualitySuffixValueTests(unittest.TestCase):
def _download_info(self, **kwargs):
info = DownloadInfo(
id="id1",
title="t",
url="http://example.com/v",
quality=kwargs.pop("quality", "best"),
download_type=kwargs.pop("download_type", "video"),
codec=kwargs.pop("codec", "auto"),
format=kwargs.pop("format", "any"),
folder="",
custom_name_prefix="",
error=None,
entry=None,
playlist_item_limit=0,
split_by_chapters=False,
chapter_template="",
)
for key, value in kwargs.items():
setattr(info, key, value)
return info
def test_video_best_uses_actual_height_template(self):
self.assertEqual(_quality_suffix_value(self._download_info()), "%(height)sp")
def test_video_numeric_quality_gets_p_suffix(self):
self.assertEqual(_quality_suffix_value(self._download_info(quality="2160")), "2160p")
def test_audio_best_stays_best(self):
info = self._download_info(download_type="audio", quality="best")
self.assertEqual(_quality_suffix_value(info), "best")
class CodecSuffixValueTests(unittest.TestCase):
def _download_info(self, **kwargs):
return DownloadInfo(
id="id1",
title="t",
url="http://example.com/v",
quality="best",
download_type="video",
codec=kwargs.pop("codec", "auto"),
format="any",
folder="",
custom_name_prefix="",
error=None,
entry=kwargs.pop("entry", None),
playlist_item_limit=0,
split_by_chapters=False,
chapter_template="",
)
def test_explicit_codec_passes_through(self):
self.assertEqual(_codec_suffix_value(self._download_info(codec="h265")), "h265")
def test_auto_codec_uses_entry_vcodec(self):
info = self._download_info(entry={"vcodec": "avc1.640028"})
self.assertEqual(_codec_suffix_value(info), "h264")
def test_auto_codec_uses_requested_formats(self):
info = self._download_info(entry={"requested_formats": [{"vcodec": "vp09.00.51.08"}]})
self.assertEqual(_codec_suffix_value(info), "vp9")
def test_unknown_auto_codec_is_sanitized(self):
info = self._download_info(entry={"vcodec": "some codec/name"})
self.assertEqual(_codec_suffix_value(info), "some_codec_name")
class DownloadInfoSetstateTests(unittest.TestCase):
def _base_state(self, **kwargs):
base = {

View file

@ -374,6 +374,60 @@ def _download_info_from_record(record: dict[str, Any]) -> DownloadInfo:
info.error = None
return info
def _quality_suffix_value(dl: DownloadInfo) -> str:
quality = str(getattr(dl, 'quality', '') or '')
if getattr(dl, 'download_type', '') == 'video':
if quality == 'best':
return '%(height)sp'
if re.fullmatch(r'\d+', quality):
return f'{quality}p'
return quality
def _codec_suffix_value(dl: DownloadInfo) -> str:
codec_value = str(getattr(dl, 'codec', '') or '')
if codec_value.lower() != 'auto':
return codec_value
entry = getattr(dl, 'entry', None) or {}
resolved = None
if isinstance(entry, dict):
vc = entry.get('vcodec')
ac = entry.get('acodec')
if vc:
resolved = vc
elif ac:
resolved = ac
else:
for fld in ('requested_formats', 'formats'):
lst = entry.get(fld) or []
if isinstance(lst, list):
for it in lst:
if isinstance(it, dict):
if it.get('vcodec'):
resolved = it.get('vcodec')
break
if it.get('acodec'):
resolved = it.get('acodec')
break
if resolved:
break
if not resolved:
return codec_value
resolved_value = str(resolved).lower()
if 'avc' in resolved_value or 'h264' in resolved_value:
return 'h264'
if 'hevc' in resolved_value or 'h265' in resolved_value or 'h.265' in resolved_value:
return 'h265'
if 'av01' in resolved_value or 'av1' in resolved_value:
return 'av1'
if 'vp9' in resolved_value or 'vp09' in resolved_value:
return 'vp9'
return re.sub(r'[^0-9a-zA-Z]+', '_', resolved_value)
class Download:
manager = None
@ -922,48 +976,12 @@ class DownloadQueue:
suffix = None
if not getattr(dl, 'custom_name_prefix', None):
parts = []
if getattr(dl, 'quality', ''):
parts.append(str(dl.quality))
codec_value = getattr(dl, 'codec', '')
if str(codec_value).lower() == 'auto':
entry = getattr(dl, 'entry', None) or {}
resolved = None
if isinstance(entry, dict):
vc = entry.get('vcodec')
ac = entry.get('acodec')
if vc:
resolved = vc
elif ac:
resolved = ac
else:
for fld in ('requested_formats', 'formats'):
lst = entry.get(fld) or []
if isinstance(lst, list):
for it in lst:
if isinstance(it, dict):
if it.get('vcodec'):
resolved = it.get('vcodec')
break
if it.get('acodec'):
resolved = it.get('acodec')
break
if resolved:
break
if resolved:
s = str(resolved).lower()
if 'avc' in s or 'h264' in s:
codec_value = 'h264'
elif 'hevc' in s or 'h265' in s or 'h.265' in s:
codec_value = 'h265'
elif 'av01' in s or 'av1' in s:
codec_value = 'av1'
elif 'vp9' in s or 'vp09' in s:
codec_value = 'vp9'
else:
codec_value = re.sub(r'[^0-9a-zA-Z]+', '_', s)
if codec_value:
parts.append(str(codec_value))
quality_suffix = _quality_suffix_value(dl)
if quality_suffix:
parts.append(quality_suffix)
codec_suffix = _codec_suffix_value(dl)
if codec_suffix:
parts.append(codec_suffix)
if parts:
suffix = '_'.join(_sanitize_path_component(p) for p in parts if p)