From 0508dc45d0b20999016732adce8dd43372bcb61c Mon Sep 17 00:00:00 2001 From: Vithorio Polten Date: Mon, 22 Jun 2026 13:12:01 -0300 Subject: [PATCH 01/27] chore: ignore worktrees --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 21907de2..1363d74c 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ crates/client-web/dist/ # dev temp files .dev/ +.worktrees From ade362a4dcfad4c1bfee445d0960e7e060678e56 Mon Sep 17 00:00:00 2001 From: Vithorio Polten Date: Thu, 18 Jun 2026 19:17:22 -0300 Subject: [PATCH 02/27] Add design spec: transcode ffmpeg resolution & player error surfacing --- ...peg-resolution-and-player-errors-design.md | 256 ++++++++++++++++++ ...026-06-18-transcode-lifecycle-discovery.md | 83 ++++++ .../2026-06-18-transcode-lifecycle-plan.md | 116 ++++++++ 3 files changed, 455 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-18-transcode-ffmpeg-resolution-and-player-errors-design.md create mode 100644 docs/superpowers/specs/2026-06-18-transcode-lifecycle-discovery.md create mode 100644 docs/superpowers/specs/2026-06-18-transcode-lifecycle-plan.md diff --git a/docs/superpowers/specs/2026-06-18-transcode-ffmpeg-resolution-and-player-errors-design.md b/docs/superpowers/specs/2026-06-18-transcode-ffmpeg-resolution-and-player-errors-design.md new file mode 100644 index 00000000..3e34469d --- /dev/null +++ b/docs/superpowers/specs/2026-06-18-transcode-ffmpeg-resolution-and-player-errors-design.md @@ -0,0 +1,256 @@ +# Transcode: FFmpeg Resolution & Player Error Surfacing — Design + +- **Date:** 2026-06-18 +- **Status:** Approved (design), pending implementation plan +- **Scope:** A focused, timer-free fix for two reported failures plus adjacent robustness gaps. Lifecycle/mid-stream handling is deliberately deferred (drafted in the appendix). + +## 1. Background & Root Cause + +Two failures were reported when playing an HEVC (transcode-required) item: + +1. **"Failed to spawn transcode: No such file or directory (os error 2)"** — transcoding never starts. +2. **Web player stays on a black screen with the "Transcoding" badge/spinner** — no error surfaced. + +### 1.1 Root cause of issue 1 (the "spaces in path" framing is a red herring) + +FFmpeg arguments are built into a `Vec` and passed via `tokio::process::Command::args(&args)` (`crates/server/src/transcode.rs:227-229`). This bypasses the shell entirely — each vector element is handed directly to the OS `exec` as a discrete argv entry. A source path containing spaces or brackets (e.g. `/Users/.../Witch Hat Atelier ....mkv`) is passed to ffmpeg verbatim. The unquoted appearance in the server log is purely cosmetic: it comes from `args.join(" ")` at `transcode.rs:222-225`, not from what is executed. + +`No such file or directory (os error 2)` returned by **`spawn()` itself** (not by ffmpeg later) is, on Unix, `ENOENT` from the exec layer. When spawning the *command* fails with `ENOENT`, it means **the executable was not found** — i.e. `ffmpeg` is not resolvable from the server process's environment. + +The decisive context: `ffmpeg_path` defaults to a bare `"ffmpeg"` (`crates/server/src/config.rs:141`). On macOS, applications launched as GUI `.app` bundles (the recent DMG packaging work, commits `d8a5ea3` / `ea83ef9`) **do not inherit the user's shell `PATH`**. So even though ffmpeg is installed at `/opt/homebrew/bin/ffmpeg` and works from a terminal, it is invisible to a bare `ffmpeg` lookup from the server process. The same resolution is used for capability detection at `crates/server/src/media.rs:5997` (`detect_binary`). + +Note: a *missing media file* would not produce `ENOENT` at spawn. ffmpeg would start, fail to open its input, and emit the error on stderr (which the code already captures). The fact that the process dies at spawn points squarely at executable resolution. + +### 1.2 Root cause of issue 2 (no player feedback on HTTP failure) + +When `/api/v1/sessions//stream` returns `500`, the `