fix: Fixed suffix when quality is 'best'
This commit is contained in:
parent
de11f5c638
commit
8723ab0afe
3 changed files with 132 additions and 45 deletions
5
.github/workflows/main.yml
vendored
5
.github/workflows/main.yml
vendored
|
|
@ -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 ''
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
102
app/ytdl.py
102
app/ytdl.py
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue