- Format table: a missing acodec was treated as "has audio", skipping
the +bestaudio merge and producing silent videos for extractors that
omit the field.
- Progress bar: separate video/audio stream downloads each reported
0-100%, making the bar jump backwards; per-phase scaling now maps the
two streams onto 0-50/50-100.
- Custom commands: parse with shlex (quoted arguments with spaces were
shredded by str.split), keep POSIX mode off on Windows so backslash
paths survive, hide the console window like every other call site,
close the stdout pipe, and support cancellation of a running command.
- Settings dialog: _("settings", "error_saving", ...) passed two
positional args to the i18n helper, raising TypeError inside the
except handler instead of showing the intended error dialog.
- ffmpeg on Windows: Path(os.getenv("LOCALAPPDATA")) crashed with
TypeError when the variable is unset; fall back to the standard
AppData/Local location.
- Version cache: cached path (str) was compared against a Path, so the
cache never hit and every version query spawned a subprocess.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- get_yt_dlp_path() no longer implicitly executes a bare "yt-dlp" from
PATH (on Windows that lookup includes the CWD, so a planted binary
in a writable directory could be run). A system yt-dlp is used only
behind the explicit advanced.allow_system_ytdlp config opt-in, and
then always as a which()-resolved absolute path. Analysis and
download refuse to exec the not-installed sentinel.
- Analysis subprocesses now run in their own session and the whole
process group is killed on timeout, so deno grandchildren no longer
leak; partial stderr is preserved and logged, and output decoding is
pinned to utf-8 with replacement (Windows locale codecs crashed on
non-UTF8 titles).
- Flat-playlist entries are filtered for None (private/deleted first
video no longer breaks analysis).
- update_yt_dlp() normalizes the sentinel to Path, unbreaking the pip
fallback path that crashed on str.exists().
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three gaps allowed an unverified binary to reach a trusted location:
- The ffmpeg ZIP fallback logged a warning on checksum mismatch and
installed anyway (the 7z path already aborted). Abort instead.
- The yt-dlp auto-update path downloaded and renamed the binary over
the verified one with no checksum at all. Verify against the official
SHA2-256SUMS like the first-install path, and use atomic os.replace.
- The yt-dlp first install streamed the download directly to the
trusted path and only verified afterwards; a crash in between left an
unverified executable to be run on next launch. Download to .part and
os.replace only after verification.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Normalize path input to string, ensure parent directories are created (mkdir with parents=True), and check writability using the normalized path. Replace manual JSON file write with ConfigManager.set("download_path", ...) and add import for ConfigManager. Adjust logging to use logger.error for failures and replace logger.exception where appropriate. These changes improve robustness when saving the download path and centralize config persistence.
When downloading playlists, add --ignore-errors and --no-abort-on-error so a single failure won't stop the entire playlist download. Also normalize values stored in the version cache: coerce version_info to a string (or empty string) and path to a string or None to ensure consistent types when reading/writing cached tool metadata.
Introduce a "generic_mode" option to allow validating/downloading from non-YouTube sites and wire it through the UI, config, and validation logic. Key changes:
- Add generic_mode default to ConfigManager and persist setting from DownloadSettingsDialog (checkbox + help text).
- Extend validate_video_url to accept a generic_mode flag and allow any http/https URL with a domain when enabled; pass this flag from Analysis and Download flows.
- Update YTSageApp to load/save generic_mode, update URL placeholder and settings tooltip behavior, and refresh tooltip when settings change.
- Improve robustness in FormatTableMixin: handle None/incorrect types for format_note, abr, resolution, ext, and codec values to avoid type errors and ensure consistent display.
- Add localization entries for generic mode, placeholder, and related help text across multiple language files and update the in-app default localization strings.
These changes enable broader site support via yt-dlp while hardening UI format handling and keeping user settings persistent.
Renamed 'src/core' to 'ytsage/core' and updated all internal imports to use relative paths. This improves package structure and ensures correct module resolution after the directory move.