Commit df500e9
committed
fix local Python setup for video gen on macOS Apple Silicon
End-to-end fix for the "configure local Python → install packages →
generate a video" flow on Apple Silicon. The previous flow hit five
distinct walls in sequence; each one looked like the user's fault but
was a real bug:
1. Video Gen's "Local Python not configured" warning only linked to the
Settings drawer. Now LocalSetupPanel renders inline below the status
pill so detect / install / Create-venv all happen in place; saving
a new pythonPath re-polls status so the pill flips green.
2. detectPython() preferred /opt/anaconda3/bin/python3 over
/opt/homebrew/bin/python3. On Apple Silicon, anaconda is often x86_64,
and `mlx` ships arm64-only wheels, so the install fails with
"No matching distribution found for mlx". The detector now probes
platform.machine() per candidate on darwin/arm64 and prefers a matching
interpreter; /api/image-gen/setup/check returns interpreterArch +
suggestedArm64Python so LocalSetupPanel can surface the warning and
offer a one-click "Switch to detected arm64 Python" affordance.
3. isExternallyManaged() false-positived on PortOS-owned venvs created
from PEP 668 Homebrew Python — sysconfig.get_path("stdlib") inside a
venv resolves to the base interpreter's stdlib, so the venv inherited
Homebrew's EXTERNALLY-MANAGED marker. Now also checks
sys.prefix != sys.base_prefix and short-circuits to false for venvs.
4. /api/video-gen/status returned `connected: !!pythonPath` — the pill
went green as soon as any pythonPath was saved, even when none of the
required packages were installed. Now probes the imports via
checkPackages and returns connected:false + missingPackages list when
anything is absent, which keeps the inline panel showing the install
button. LocalSetupPanel also notifies the parent on local check
transition to "all installed" so the pill flips without waiting on a
manual refresh.
5. The PyPI package literally named `mlx_video` is unrelated to the
`mlx_video.generate_av` CLI the LTX renderer shells into — that ships
in `mlx-video-with-audio`. Both publish an `import mlx_video`
namespace, so the missing-check passed against the wrong one and the
spawn died with ModuleNotFoundError. pipNameFor('mlx_video') now
returns 'mlx-video-with-audio>=0.1.35' on macOS; the import probe
checks `import mlx_video.generate_av` to distinguish them;
installPackages gained a pre-uninstall step driven by
PIP_PRE_UNINSTALL so the conflicting plain `mlx_video` is removed
before pip refuses to "downgrade" across the namespace collision.
Mirrors what scripts/setup-image-video.sh already did out-of-band.
Separately:
* The media job worker now re-resolves pythonPath from live settings at
dispatch time for every local-Python job, instead of using the
snapshot captured at enqueue time. Symptom this fixes: user switches
their Python in the UI, clicks Generate, and the worker still shells
out to the previous interpreter — because the in-memory queue and
data/media-jobs.json carried the old snapshot. Codex image jobs are
unaffected (they don't run a local Python).
* probePythonHealth() consolidates the three subprocesses /setup/check
used to fan out (checkPackages + isExternallyManaged + probePythonArch)
into one python invocation that returns everything as JSON.
isExternallyManaged becomes a thin wrapper; the standalone export was
unused after the consolidation and is removed.
* installPackages and installFlux2Venv shared a near-identical
spawn-and-stream-stdout helper; extracted to a single streamSpawn().
Tests: 8061 server + 602 client passing (incl. new coverage for
mediaJobQueue's live-pythonPath re-resolution and videoGen /status's
missing-packages branch). Test count grew by 4 since main.1 parent 3807aa8 commit df500e9
10 files changed
Lines changed: 351 additions & 87 deletions
File tree
- .changelog
- client/src
- components/settings
- pages
- server
- lib
- routes
- services/mediaJobQueue
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
38 | 44 | | |
39 | 45 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
15 | 21 | | |
16 | 22 | | |
17 | 23 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
49 | 60 | | |
50 | 61 | | |
51 | 62 | | |
| |||
167 | 178 | | |
168 | 179 | | |
169 | 180 | | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
170 | 201 | | |
171 | 202 | | |
172 | 203 | | |
| |||
0 commit comments