portable-net-tv/README.md
Natalie d281580be5 chore: baseline before autonomous OSX-app task
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 21:55:46 -06:00

102 lines
3.2 KiB
Markdown

# portable-net-tv
Follows VLC playback, tracks every show you watch, and prefetches the next
few episodes of whatever's on into a local buffer.
One profile-less service handles all shows: it reads the currently-playing
file from VLC's HTTP interface, and that file's own directory *is* the show's
source — no per-show configuration.
## The `watch` service
```sh
portable-net-tv watch
```
Runs a daemon that, every 30 s:
1. Reads the currently-playing file from VLC's HTTP playlist.
2. Appends episode changes to the cross-show watch log.
3. Prefetches the next *N* episodes sitting in the playing file's directory
into the buffer dir (single rsync at a time; honors a disk floor).
4. Garbage-collects the buffer down to exactly that prefetch window.
Files with a sibling `<episode>.broken` marker are skipped at every step.
## `next`
```sh
portable-net-tv next
```
Reads the watch log and prints, per show, the episode watched through and the
next one. Only genuine `play`/`resume` events count toward progress — queued
-but-unwatched episodes do not.
## Watch log
Append-only JSONL at `~/.local/state/plum-control-mcp/watched.jsonl` (shared
with `plum-control-mcp`). One event per line: `ts, event, show, season,
episode, label, path`. The show name is parsed from the filename (everything
before the `SxxEyy` marker).
## Config
`~/.config/portable-net-tv/config.json`:
```json
{
"vlcHttp": { "host": "127.0.0.1", "port": 8080, "password": "<password>" },
"buffer": { "dir": "/Users/natalie/Movies/net-tv-buffer", "ahead": 3, "minFreeGB": 2 }
}
```
`buffer` is optional — it defaults to `~/Movies/net-tv-buffer`, `ahead` 3,
`minFreeGB` 2.
## VLC HTTP interface
The service reads VLC over HTTP (`requests/playlist.json`), not AppleScript —
so it works as a launchd background agent, where Apple Events to VLC are
blocked by macOS Automation (TCC). Enable it once:
```sh
defaults write org.videolan.vlc extraintf -string http
defaults write org.videolan.vlc http-host -string 127.0.0.1
defaults write org.videolan.vlc http-port -int 8080
defaults write org.videolan.vlc http-password -string <password>
```
If the interface or config is missing, the service treats VLC as unreachable
and idles rather than failing.
## Run at login
`launchd` keeps the service alive across reboots —
`~/Library/LaunchAgents/com.quinn.portable-net-tv.watch.plist`, `RunAtLoad` +
`KeepAlive`. Put Homebrew's `bin` first on the plist's `PATH`: the service
needs a modern `rsync` (`--append-verify`), not the ancient `/usr/bin/rsync`.
## Broken media
A corrupt source file is flagged by touching a sibling marker next to it:
```sh
touch "/path/to/Show.S01E07.broken"
```
The `watch` service excludes any episode with a `.broken` marker — it won't
prefetch it, and `episodesInDir` skips it. Mark a file whenever it refuses to
play (e.g. VLC opens it but the time stays frozen at 0:00).
## Constraints
- macOS only — reads VLC's macOS HTTP interface; paths assume the local media
mount.
- VLC is the only supported player, and must be running with HTTP enabled.
## Legacy
`keep`, `play`, `check`, and the per-show profiles under
`~/.config/portable-net-tv/profiles/` predate the unified `watch` service and
are being retired. New use should rely on `watch` + `next` only.