feat(setup): fetch ffmpeg on first run instead of bundling it
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>
This commit is contained in:
@@ -28,6 +28,13 @@ import {
|
||||
import { PAGE_BACKGROUND } from '@shared/theme'
|
||||
import { getYtdlpVersion, updateYtdlp } from './ytdlp'
|
||||
import { getFfmpegVersions } from './ffmpeg'
|
||||
import {
|
||||
getFfmpegSetupStatus,
|
||||
downloadFfmpeg,
|
||||
cancelFfmpegDownload,
|
||||
locateFfmpegManually
|
||||
} from './ffmpegSetup'
|
||||
import { getAria2cPath } from './binaries'
|
||||
import { checkForAppUpdate, downloadAppUpdate, runAppUpdate, cancelAppUpdate } from './updater'
|
||||
import { probeMedia } from './probe'
|
||||
import { startDownload, cancelDownload, pauseDownload, previewCommand } from './download'
|
||||
@@ -114,6 +121,21 @@ export function registerIpcHandlers(getMainWindow: () => BrowserWindow | null):
|
||||
|
||||
ipcMain.handle(IpcChannels.ffmpegVersion, () => getFfmpegVersions())
|
||||
|
||||
// First-run ffmpeg/ffprobe acquisition (they're no longer bundled). Status gates the
|
||||
// setup screen; download streams the pinned archive to e.sender; locate is the offline
|
||||
// fallback (folder picker parented to the window, like chooseFolder).
|
||||
ipcMain.handle(IpcChannels.ffmpegSetupStatus, () => getFfmpegSetupStatus())
|
||||
ipcMain.handle(IpcChannels.ffmpegSetupDownload, (e) => downloadFfmpeg(e.sender))
|
||||
ipcMain.handle(IpcChannels.ffmpegSetupCancel, () => cancelFfmpegDownload())
|
||||
ipcMain.handle(IpcChannels.ffmpegSetupLocate, (e) =>
|
||||
locateFfmpegManually(BrowserWindow.fromWebContents(e.sender) ?? undefined)
|
||||
)
|
||||
|
||||
// Whether the optional aria2c external downloader shipped with this build, so the
|
||||
// Settings toggle can disable itself instead of silently doing nothing (the flag
|
||||
// is a no-op without the binary — see download.ts's existsSync gate).
|
||||
ipcMain.handle(IpcChannels.aria2cAvailable, () => existsSync(getAria2cPath()))
|
||||
|
||||
ipcMain.handle(IpcChannels.probe, (_e, url: string) => probeMedia(url))
|
||||
|
||||
ipcMain.handle(IpcChannels.downloadStart, async (e, opts: StartDownloadOptions) => {
|
||||
|
||||
Reference in New Issue
Block a user