Commit graph

8 commits

Author SHA1 Message Date
Zac
bab24e156a feat(recorders): probe sources + reflect real signal in main status
Two things that together stop bogus URLs from masquerading as a recording:

PROBE BUTTON in the New Recorder panel. Before you commit to record, hit Probe Source - the capture container runs ffprobe with a 10s timeout against the URL and returns the parsed streams. UI shows green Signal Detected with codec/resolution/fps/audio, or red No Signal Detected with the actual ffprobe error message. For SDI it lists DeckLink devices. Listener-mode sources cannot be probed standalone (would block waiting for a publisher) and the UI says so.

MAIN STATUS LABEL ON THE RECORDING CARD now mirrors the live signal instead of hardcoding Recording. So a recorder pointed at a dead URL goes Connecting... -> Connection error (red) instead of looking like everything is fine. When frames actually start arriving the label flips to Recording (blue) and the dot turns blue. If a previously-good stream drops the label switches to Signal lost (red).

API:
* capture: POST /capture/probe runs ffprobe and returns { ok, streams, format, error? }
* mam-api: POST /api/v1/recorders/probe proxies through to the capture sidecar with a 15s outer timeout
2026-05-17 18:39:21 -04:00
Zac
72545126c4 fix: delete asset actually deletes
Trash icon in the library was firing PATCH /assets/:id with {status:"deleted"}. The PATCH route only accepts display_name/tags/notes so it returned "No fields to update" and the asset stayed put.

* api.js: add deleteAsset(id, {hard}) helper hitting the real DELETE route.
* index.html: deleteAssetPrompt now calls deleteAsset (soft archive). Confirm dialog reworded to match.
* mam-api/routes/assets.js: list endpoint hides status=archived by default. Pass ?include_archived=true to see them in a future restore-from-trash view. Filtering by ?status=archived still works for power users.
* All HTML: bump api.js cache-buster v=4 -> v=5 so the new helper is fetched.
2026-05-17 12:55:55 -04:00
Zac
3ea896c368 fix(web-ui): bust JS cache so api.js fix actually reaches the browser
The api.js library-list fix from the previous commit never reached the browser because nginx served all .js with `Cache-Control: public, immutable; max-age=31536000`. The HTML referenced api.js with no version query, so the browser kept its year-cached buggy copy.

* nginx.conf: drop .js from the immutable long-cache block, add a no-cache must-revalidate block so future redeploys are picked up immediately.
* All HTML files: tag api.js refs with ?v=4 so already-running browsers fetch the new version on next page load.
2026-05-17 08:31:00 -04:00
Zac
ac1878452f fix: library + caller-only recorders + live signal indicator
Three problems blocked the end-to-end flow:

1) Library always rendered empty because /assets returns {assets,total} but
   index.html (and capture.html) assumed r.data was an array. Fixed in
   api.js by unwrapping r.data.assets centrally; total is kept on r.total.

2) SRT/RTMP caller mode pulled audio only. ffmpeg opened the network input
   before the H264 SPS arrived, marked the video stream as pix_fmt=none,
   and silently dropped it from the stream map. Added -probesize 32M
   -analyzeduration 10M -fflags +genpts and explicit -map 0✌️0?/0🅰️0? so
   each track survives independently of when it appears.

3) Hitting Record gave no feedback about whether a stream was actually
   arriving. capture-manager now parses ffmpeg progress lines (frame=...
   fps=...) and tracks framesReceived, currentFps, lastFrameAt, lastError.
   getStatus() returns a derived signal enum (connecting | receiving |
   lost | error | stopped). The recorder controller gives each spawned
   container a stable network alias `recorder-<id>` and the GET
   /recorders/:id/status endpoint proxies the live capture status through.
   recorders.html polls that every 2s and renders the badge under each
   active card with the running frame/fps counter or the ffmpeg error.

Also:
* recorders.html: dropped the listener-mode UI entirely. All new recorders
  are caller-mode (pull). The MAM is no longer offered as an RTMP/SRT
  server. Legacy listener records still render but read-only.
2026-05-17 07:39:58 -04:00
f7a96677ef feat: redesign recorders.html with new design system 2026-05-16 13:57:20 -04:00
0a5b4d6191 feat(ui): SRT/RTMP listener/caller mode UI in recorders
- SRT: mode selector (Listener / Caller)
  - Listener: listen_port field + live connection info banner
  - Caller: source URL field
- RTMP: mode selector (Listener / Caller)
  - Listener: listen_port + stream_key fields + live connection info banner
  - Caller: source URL field
- Connection info banners update live as port/key fields change
- handleCreateRecorder builds correct source_config per mode
- Card meta display handles listener config (shows port, not url)
- updateSrtModeFields / updateRtmpModeFields helpers for dynamic show/hide
2026-05-16 08:23:24 -04:00
ed52dfcafb Fix recorders.html: rename handlers to avoid api.js shadowing (infinite recursion), fix resolution→recording_resolution 2026-05-16 00:48:40 -04:00
3aee8c41f5 Phase 2: services/web-ui/public/recorders.html 2026-04-07 22:05:43 -04:00