Skip to content

Commit bad8583

Browse files
mdzclaude
andauthored
Bring untracked local design/setup docs into the repo (#165)
## Summary Several design and setup docs were sitting in a gitignored `ldocs/` directory outside the repo. Reviewed them all and moved the ones that are still accurate/useful into `docs/`, fixing them up along the way; the rest were left out (stale planning artifacts, scratch notes, or personal deploy scripts hardcoded to specific hosts/IPs). - **`docs/development/guest-identity.md`** and **`guest-identity-implementation.md`** — the guest identity design docs. Turned out to be load-bearing: `kbox/identity.py`, `merge_users.py`, `user.py`, `database/users.py`, and `web/server.py` all cite `ldocs/GUEST_IDENTITY_CONTINUITY.md` / `ldocs/GUEST_IDENTITY_TECHNICAL_DESIGN.md` by path as their design rationale — a dead link for anyone cloning the repo. Repointed every one of those in-code references to the new tracked paths. - **`docs/development/relay-proposal.md`** — the cloud-relay proposal these docs reference as future context. - **`docs/setup/youtube-api.md`** (new directory, for operator-facing setup guides as distinct from developer guidance) — API key setup walkthrough, with the stale "configure via a script that no longer exists" step replaced by the actual web UI config-screen flow. Linked from both Quick Start sections in README. - **`docs/development/macos-setup.md`** — macOS dev environment setup, trimmed of a `run_kbox.sh` wrapper script reference that doesn't exist in the repo. - Folded the dual-HDMI-display `kmssink` investigation into `gstreamer-pipeline.md`'s existing "Traps" section as a new entry, rather than keeping it as a standalone file. Left out: an old pre-implementation architecture doc (superseded by the actual code), scratch notes, an empty test-plan file, a karaoke party-lifecycle reference doc (vision doc, not useful to future contributors), onboarding notes built around scripts that no longer exist, and two personal deploy scripts hardcoded to specific hosts. ## Test plan - [x] `uv run ruff check .` / `mypy` / pre-commit hooks all pass (ran automatically on commit) - [ ] Skim the new/moved docs for accuracy against current behavior 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
1 parent d405173 commit bad8583

15 files changed

Lines changed: 1480 additions & 15 deletions

File tree

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ All settings are managed through the web UI with a schema-driven settings panel:
5050
- [YouTube IFrame Player API](https://developers.google.com/youtube/iframe_api_reference) for the display page
5151
- [YouTube Data API v3](https://developers.google.com/youtube/v3) for search
5252
- [LiteLLM](https://github.com/BerriAI/litellm) for AI suggestions and metadata extraction
53+
- `signalsmithpitch` — a native GStreamer element (`native/gst-signalsmith-pitch/`) for real-time pitch shifting, built on [signalsmith-stretch](https://github.com/Signalsmith-Audio/signalsmith-stretch)
5354

5455
## Quick Start (Docker)
5556

@@ -58,7 +59,7 @@ docker-compose build
5859
docker-compose up
5960
```
6061

61-
Then open `http://localhost:8000` in your browser and configure your YouTube API key in Settings.
62+
Then open `http://localhost:8000` in your browser and configure your YouTube API key in Settings (see `docs/setup/youtube-api.md` if you need help getting one).
6263

6364
## Quick Start (Native)
6465

@@ -67,7 +68,15 @@ uv sync
6768
uv run python -m kbox.main
6869
```
6970

70-
Open `http://localhost:8000` on your phone to queue songs, and `http://localhost:8000/display` on your TV/monitor for the fullscreen karaoke display. Configure your YouTube API key in Settings.
71+
Open `http://localhost:8000` on your phone to queue songs, and `http://localhost:8000/display` on your TV/monitor for the fullscreen karaoke display. Configure your YouTube API key in Settings (see `docs/setup/youtube-api.md` if you need help getting one).
72+
73+
Pitch shifting requires the native `signalsmithpitch` GStreamer plugin, which the Docker image builds automatically but a native install does not — without it kbox falls back to no pitch shifting. Build it once with:
74+
75+
```bash
76+
native/gst-signalsmith-pitch/build.sh
77+
```
78+
79+
See `native/gst-signalsmith-pitch/README.md` for build requirements.
7180

7281
## Platform Support
7382

docs/development/gstreamer-pipeline.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,32 @@ fixing, not its resolution.
347347
Useful when investigating: `GST_DEBUG=kmssink:7` prints the plane rectangle it
348348
actually programs, which beats guessing from what the screen looks like.
349349

350+
### `kmssink` cannot run two instances against one DRM device
351+
352+
The Pi 5 has two micro-HDMI ports and the hardware fully supports driving
353+
both independently — the DRM connectors enumerate fine in `/sys/class/drm/`,
354+
each at its own connector ID. It is tempting to route a `tee` into two
355+
`kmssink`s, one per `connector-id`, to show different overlays on each
356+
display. This fails:
357+
358+
```
359+
drmModeSetPlane failed: Permission denied (13)
360+
```
361+
362+
or a "failed to configure video mode" error, depending on the exact
363+
combination of properties tried. Each `kmssink` instance tries to become DRM
364+
master, and they conflict — this held across privileged Docker mode, adding
365+
the `video`/`render` groups, and toggling `force-modesetting`, so it is not a
366+
permissions issue to work around.
367+
368+
Two real options if independent per-display overlays are ever needed: switch
369+
to a Wayland/Weston compositor and `waylandsink` (significant pipeline
370+
changes), or drive both outputs with identical content via OS-level display
371+
mirroring (`wlr-randr`/`xrandr`), which needs no pipeline changes at all. For
372+
same-content-on-both-screens (the common karaoke case), a plain HDMI
373+
splitter downstream of a single `kmssink` sidesteps the problem entirely and
374+
is what kbox uses today.
375+
350376
### `textoverlay` already scales its own font
351377

352378
`auto-resize` is on by default and scales the font relative to a 640-pixel-wide

docs/development/guest-identity-implementation.md

Lines changed: 393 additions & 0 deletions
Large diffs are not rendered by default.

docs/development/guest-identity.md

Lines changed: 360 additions & 0 deletions
Large diffs are not rendered by default.

docs/development/macos-setup.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# macOS Setup Guide
2+
3+
## Prerequisites
4+
5+
1. **Install Homebrew** (if not already installed):
6+
```bash
7+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
8+
```
9+
10+
2. **Install GStreamer and dependencies**:
11+
```bash
12+
brew install gstreamer glib pygobject3
13+
```
14+
15+
3. **Install Python dependencies**:
16+
```bash
17+
uv pip install pygobject pycairo
18+
```
19+
20+
## Running kbox
21+
22+
Due to macOS's library path restrictions, GStreamer needs a few environment
23+
variables set before it will load:
24+
25+
```bash
26+
export DYLD_LIBRARY_PATH="$(brew --prefix glib)/lib:$(brew --prefix gstreamer)/lib:$DYLD_LIBRARY_PATH"
27+
export GI_TYPELIB_PATH="$(brew --prefix gstreamer)/share/gir-1.0:$GI_TYPELIB_PATH"
28+
export GST_PLUGIN_PATH="$(brew --prefix gstreamer)/lib/gstreamer-1.0:$GST_PLUGIN_PATH"
29+
30+
uv run python -m kbox.main
31+
```
32+
33+
## Troubleshooting
34+
35+
### "No module named 'gi'"
36+
- Install pygobject: `uv pip install pygobject`
37+
38+
### "Failed to load shared library 'libglib-2.0.0.dylib'"
39+
- Set `DYLD_LIBRARY_PATH` as shown above.
40+
41+
### "Could not locate g_option_error_quark"
42+
- This is a library path issue. Set the environment variables above.
43+
44+
## Note on Python Version
45+
46+
The project uses Python 3.9.6 by default (from Xcode). For better compatibility, consider using Python 3.10+ via Homebrew:
47+
48+
```bash
49+
brew install python@3.12
50+
uv python install 3.12
51+
```
52+
53+
Then use: `uv run --python 3.12 python -m kbox.main`

0 commit comments

Comments
 (0)