web: audiobook player — stitched-file playback with chapter seek

Adds GET /stories/{id}/listen: one <audio> element over a story's
stitched audiobook file plus a clickable chapter list. Clicking a
chapter seeks; the chapter under the playhead highlights as it
plays. Chapter offsets are summed from each chapter's latest
succeeded narration_run duration — the same order the file was
stitched. One small inline script, the web UI's first JS.

New stories.audiobook_path column (migration 0009) holds the
served path; the story page shows a "listen" action when set.
This commit is contained in:
Sulkta 2026-05-15 07:30:56 -07:00
parent 61f1bdd40a
commit f70cfe1f0b
2 changed files with 221 additions and 1 deletions

View file

@ -0,0 +1,7 @@
-- A story can have a single stitched audiobook — all its chapter
-- renders concatenated into one chaptered file (see the m4b built
-- from per-chapter narration_runs). audiobook_path is the path the
-- web server serves it from (e.g. /audio/The-Coast-Down.m4b); NULL
-- means no audiobook has been stitched yet.
ALTER TABLE stories
ADD COLUMN IF NOT EXISTS audiobook_path text;