Ship a smaller installer that no longer carries ffmpeg.exe/ffprobe.exe
(the bulk of its size). On first run they are downloaded from a pinned
upstream archive (gyan 8.1.2), verified against a pinned SHA-256, and
unpacked with the OS tar.exe into the managed userData/bin dir -- the
same place as the self-updating yt-dlp, so they survive app updates and
portable re-extraction. A hard onboarding gate blocks the app until they
are present, with a "locate existing ffmpeg" folder-picker fallback for
offline machines and a Repair action in Settings > About.
The updater's streaming/checksum/redirect/idle-timeout download loop is
extracted to lib/verifiedDownload.streamVerifiedFile and shared by both
the app-installer download and the ffmpeg fetch; the updater's public
behaviour and error strings are unchanged (its boundary tests still pass).
No new npm dependency: extraction uses the System32 bsdtar resolved by
absolute path (audit F3).
Note: this commit also carries pre-existing, in-progress aria2c/network
and updater-token work that was already uncommitted in the working tree
and is entangled with the above in shared files (updater.ts, ipc.ts,
preload/index.ts, mockApi.ts, shared/ipc.ts, plus the settings/network
files and aria2c.exe). It was not cleanly separable by path, so it is
included here rather than split out.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A live smoke test of buildArgs' argv against the bundled yt-dlp + ffmpeg found
that ffprobe.exe was never bundled (resources/bin/ shipped only ffmpeg.exe).
yt-dlp resolves both from --ffmpeg-location, so duration-aware post-processing
failed at runtime for every user with "ffprobe not found": --sponsorblock-remove,
--force-keyframes-at-cuts, and --split-chapters (CODE-AUDIT C1).
- Bundle ffprobe.exe (matching n8.1.2 LGPL build, sha256-verified against the
already-bundled ffmpeg.exe) and document it in resources/bin/README.md as a
required binary; correct the stale "not committed to git" note.
- Guard startDownload against a missing ffmpeg.exe/ffprobe.exe up front so the
failure is a clear AeroFetch error, not a cryptic yt-dlp postprocessing one
(new getFfprobePath() in binaries.ts).
- Expand test/real-download.integration.test.ts from 2 to 8 live cases: crop,
sponsorblock-remove, audio opus re-encode, mkv+vp9 merge, subtitle+chapter
embed, restrict-filenames, download-archive skip, and Phase C extra-args.
All 8 pass against live yt-dlp + ffmpeg.
- ROADMAP: mark the Phase A/B/C smoke-test caveats done. CODE-AUDIT: add C1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the remaining Phase B (Access & networking) items from
ROADMAP.md: cookie sources (browser cookie-store import, or a built-in
sign-in window that exports a Netscape cookie file via a persisted Electron
session partition), the aria2c external downloader, proxy/rate-limit,
restrict-filenames, and a download-archive to skip repeats.
Wires download.ts to the buildArgs() module added in the previous commit
(it wasn't hooked up yet) and renames its options param
NetworkOptions -> AccessOptions to reflect the wider scope now that cookies
and filename/archive flags joined proxy/rate-limit/aria2c.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Electron + React (Fluent UI) desktop frontend for yt-dlp:
- Download queue with live progress, concurrency cap, cancel/retry
- Format/quality picker via yt-dlp probe; audio extraction to MP3
- Settings + history persistence (electron-store / JSON)
- Clipboard link auto-detect; persisted light/dark theme
- NSIS + portable packaging (binaries bundled at build time, not in git)
UI: "Studio" sidebar layout with a toffee-brown theme (light + neutral dark).
Dropdowns use a native <select> and tooltips a CSS-only Hint, to avoid a
dev-machine GPU overlay flicker/blank issue.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>