Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

An Electron wrapper that runs the regular Flux server on `127.0.0.1` and shows it in a window. No Node, Docker or setup needed for users. The server code is unchanged; the app only sets environment variables (`FLUX_LOCAL_MODE=1`, data in the OS app-data folder).

- The **media engine** is downloaded (checksum-verified) on first launch into the app-data folder and self-updates on later launches.
- The **media engine** is downloaded (checksum-verified) in the background on first launch into the app-data folder and self-updates on later launches. The app opens even when offline; downloads start working once the engine has arrived.
- **FFmpeg / FFprobe** are bundled through `ffmpeg-static` and `ffprobe-static`.
- **Local mode** (`FLUX_LOCAL_MODE=1`) treats the person running the app as signed in, so full-length downloads work without Google sign-in. It is ignored unless the server listens on `127.0.0.1`.

Expand Down
18 changes: 13 additions & 5 deletions desktop/ytdlp.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Keeps a standalone yt-dlp in the app's data folder: downloaded and verified on
// first launch, then self-updated in the background (sites change often).
import { mkdir, writeFile, chmod, access } from "node:fs/promises";
import { mkdir, writeFile, chmod, access, rename } from "node:fs/promises";
import { createHash } from "node:crypto";
import { spawn } from "node:child_process";
import path from "node:path";
Expand Down Expand Up @@ -59,11 +59,17 @@ async function download(target) {
createHash("sha256").update(bytes).digest("hex") !== expected.toLowerCase()
)
throw new Error("Checksum verification failed for yt-dlp.");
await writeFile(target, bytes);
if (process.platform !== "win32") await chmod(target, 0o755);
// Write to a temp name first so an interrupted download is never mistaken for a working binary.
const tmp = `${target}.part`;
await writeFile(tmp, bytes);
if (process.platform !== "win32") await chmod(tmp, 0o755);
await rename(tmp, target);
}

/** Returns the path to yt-dlp, downloading it on first run. Updates run in the background. */
/**
* Returns the path to yt-dlp right away. On first run the download happens in the background,
* so the app still opens when offline; downloads work once yt-dlp has arrived.
*/
export async function ensureYtDlp(binDir) {
await mkdir(binDir, { recursive: true });
const target = path.join(
Expand All @@ -75,7 +81,9 @@ export async function ensureYtDlp(binDir) {
() => false,
);
if (!exists) {
await download(target);
download(target).catch((error) =>
console.error(`Could not fetch yt-dlp yet: ${error.message}`),
);
return target;
}
// Best effort: the standalone binary can update itself in place.
Expand Down
Loading