diff --git a/README.md b/README.md index e032a04..6eafc28 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Create/edit `config/yt-playlist-config.json`: "playlists": [ { "url": "https://www.youtube.com/playlist?list=YOUR_PLAYLIST_ID", - "download_mode": "audio", + "download_mode": "video", "max_download_quality": "1080p", "save_path": "./downloads" } @@ -45,6 +45,12 @@ Create/edit `config/yt-playlist-config.json`: } ``` +Defaults: +- `ffmpeg_path`: `./bin/ffmpeg.exe` (Windows) or `./bin/ffmpeg` (Linux) +- `download_mode`: `video` +- `max_download_quality`: `1080p` +- `save_path`: `./downloads` + `max_download_quality`: - Limits yt-dlp download quality (e.g. `"1080p"`, `"720p"`, `"360p"`). This only affects the downloaded video format selection. diff --git a/config/yt-playlist-config.example.json b/config/yt-playlist-config.example.json index 61e1d76..05fd760 100644 --- a/config/yt-playlist-config.example.json +++ b/config/yt-playlist-config.example.json @@ -1,11 +1,11 @@ { + "ffmpeg_path": "./bin/ffmpeg.exe", "playlists": [ { "url": "https://www.youtube.com/playlist?list=YOUR_PLAYLIST_ID_HERE", - "download_mode": "audio", + "download_mode": "video", "max_download_quality": "1080p", "save_path": "./downloads" } - ], - "ffmpeg_path": "./ffmpeg" + ] } diff --git a/src/app/config/settings.py b/src/app/config/settings.py index d28bac0..724bd82 100644 --- a/src/app/config/settings.py +++ b/src/app/config/settings.py @@ -1,16 +1,23 @@ from __future__ import annotations import json +import os from pathlib import Path from typing import Any, Dict, List, Optional +def _default_ffmpeg_path() -> str: + if os.name == "nt": + return "./bin/ffmpeg.exe" + return "./bin/ffmpeg" + + DEFAULT_CONFIG: Dict[str, Any] = { "playlists": [], - "download_mode": "audio", + "download_mode": "video", "max_download_quality": "1080p", "save_path": "./downloads", - "ffmpeg_path": "ffmpeg", + "ffmpeg_path": _default_ffmpeg_path(), } @@ -40,12 +47,12 @@ class Settings: "playlists": [ { "url": "https://www.youtube.com/playlist?list=YOUR_PLAYLIST_ID", - "download_mode": "audio", + "download_mode": "video", "max_download_quality": "1080p", "save_path": "./downloads", } ], - "ffmpeg_path": "ffmpeg", + "ffmpeg_path": _default_ffmpeg_path(), } path.write_text(json.dumps(default_payload, indent=2) + "\n", encoding="utf-8") diff --git a/src/app/core/download/downloader.py b/src/app/core/download/downloader.py index a8593a0..b839f9f 100644 --- a/src/app/core/download/downloader.py +++ b/src/app/core/download/downloader.py @@ -19,12 +19,16 @@ class Downloader: def build_format(max_download_quality) -> str: def parse_height_cap(value) -> int | None: if value is None: - return None + return 1080 if isinstance(value, int): return value if value > 0 else None s = str(value).strip().lower() - if not s or s in {"best", "max", "auto", "none", "null"}: + if not s: + return 1080 + if s in {"best", "max", "auto"}: return None + if s in {"none", "null"}: + return 1080 digits = "".join(ch for ch in s if ch.isdigit()) if not digits: return None diff --git a/tests/test_download_quality_format.py b/tests/test_download_quality_format.py index ff75018..39f17df 100644 --- a/tests/test_download_quality_format.py +++ b/tests/test_download_quality_format.py @@ -5,8 +5,8 @@ from src.app.core.download.downloader import Downloader def test_build_format_defaults_to_best_mp4(): fmt = Downloader.build_format(None) - assert "height<=" not in fmt - assert "best[ext=mp4]" in fmt + assert "height<=1080" in fmt + assert fmt.endswith("/best[ext=mp4]") def test_build_format_applies_height_cap(): diff --git a/tests/test_settings_default_config.py b/tests/test_settings_default_config.py index 1a2f25a..5515081 100644 --- a/tests/test_settings_default_config.py +++ b/tests/test_settings_default_config.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import os from pathlib import Path from src.app.config.settings import Settings @@ -18,6 +19,10 @@ def test_settings_creates_root_config_if_missing(tmp_path, monkeypatch): data = json.loads(cfg_path.read_text(encoding="utf-8")) assert "playlists" in data + assert data.get("ffmpeg_path") == ("./bin/ffmpeg.exe" if os.name == "nt" else "./bin/ffmpeg") + assert data["playlists"][0].get("download_mode") == "video" + assert data["playlists"][0].get("max_download_quality") == "1080p" + assert data["playlists"][0].get("save_path") == "./downloads" def test_settings_reads_config_from_default_location(tmp_path, monkeypatch): @@ -25,8 +30,11 @@ def test_settings_reads_config_from_default_location(tmp_path, monkeypatch): cfg_path = tmp_path / "config" / "yt-playlist-config.json" cfg_path.parent.mkdir(parents=True, exist_ok=True) - cfg_path.write_text(json.dumps({"playlists": [{"url": "X", "save_path": "./downloads"}]}), encoding="utf-8") + cfg_path.write_text(json.dumps({"playlists": [{"url": "X"}]}), encoding="utf-8") settings = Settings() assert settings.path == cfg_path.resolve() assert settings.playlists and settings.playlists[0]["url"] == "X" + assert settings.playlists[0]["download_mode"] == "video" + assert settings.playlists[0]["max_download_quality"] == "1080p" + assert settings.playlists[0]["save_path"] == "./downloads"