Commit graph

17 commits

Author SHA1 Message Date
f4a83eedc4 capture-manager: dynamic ffmpeg args from per-recorder codec config
Adds a VIDEO_CODECS / AUDIO_CODECS / CONTAINER catalogue and a
buildEncodeArgs() that composes -c:v / -c:a / -b:v / -b:a / -r / -ac / -f
from the recorder's saved settings. Master and proxy each get their own
codec stack, both honour the container format chosen in the UI, and the
S3 keys now use the actual container extension instead of hardcoded mov/mp4.
2026-05-21 00:19:00 -04:00
485af25d4a capture bootstrap: forward every codec env var to captureManager.start 2026-05-21 00:16:03 -04:00
a9c16d9509 fix(capture): wire bootstrapAutoStart() + add missing captureManager/MAM_API_URL/server (regression from earlier conflict resolution) 2026-05-18 09:25:55 -04:00
d8229e6f3f feat(probe): pre-flight reachability + actionable SRT/RTMP error messages 2026-05-18 07:57:48 -04:00
7d76f9c549 feat(growing-files): Phase 1 - live HLS preview during recording
While a recorder is running, the capture container tees an HLS
stream into /live/<assetId>/ alongside the ProRes master upload.
The asset row is pre-created at recorder start with status='live'
so the clip appears in the library immediately. /api/v1/assets/:id/stream
returns the HLS playlist URL until recording stops, then proxy.

* docker-compose: shared wild-dragon-live mount on api/capture/web-ui
* migration 001-add-live-status: idempotent ALTER TYPE for asset_status
* mam-api: runMigrations() on boot; recorders.js pre-creates live asset
  + passes ASSET_ID; assets.js POST upserts on existing live row instead
  of inserting a duplicate, and stream route returns HLS for live assets
* capture: parallel HLS ffmpeg into /live/<assetId>/; ASSET_ID env
* web-ui: nginx serves /live/, preview.js loads hls.js, LIVE badge added
2026-05-18 07:29:50 -04:00
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
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
55fec605c6 feat(capture): accept SRT/RTMP source params in POST /start
- Accept source_type, source_url, listen, listen_port, stream_key
- Validate: SDI requires device; SRT/RTMP caller requires source_url
- Pass all params through to captureManager.start()
- On stop: if proxyKey is null (network source), include needsProxy flag
  in MAM API registration so worker can generate proxy asynchronously
2026-05-16 08:20:10 -04:00
ea48e98465 feat(capture): add SRT/RTMP source type support
- Add _buildInputArgs() to build FFmpeg input args per source type
- SRT caller: srt://host:port?mode=caller
- SRT listener: srt://0.0.0.0:PORT?mode=listener
- RTMP caller: -i rtmp://host/app/key
- RTMP listener: -listen 1 -i rtmp://0.0.0.0:PORT/live/key
- Network sources spawn hires-only FFmpeg process (can't open stream twice)
- proxyKey is null for network sources; proxy generated by worker post-stop
- SDI keeps existing dual-process behavior unchanged
2026-05-16 08:19:41 -04:00
f9c680cc22 fix(routes+ui): capture route bin optional, jobs Redis URL, recorders S3_REGION+stop codes, api.js full rewrite, upload.html multipart fix, capture.html bin guard: capture.js 2026-05-16 00:30:25 -04:00
bb069760fe fix(infra+workers): S3 creds, ffprobe, BullMQ awaits, thumbnail seek, bin optional, docker-compose vars, jobs Redis, recorders stop codes: client.js 2026-05-16 00:29:47 -04:00
7c7fcd2b0d add services/capture/src/routes/capture.js 2026-04-07 21:58:30 -04:00
dfffca879a add services/capture/src/s3/client.js 2026-04-07 21:58:30 -04:00
75ef8a4ed8 add services/capture/src/capture-manager.js 2026-04-07 21:58:29 -04:00
febf394a81 add services/capture/src/index.js 2026-04-07 21:58:29 -04:00
e0902acbb6 add services/capture/package.json 2026-04-07 21:58:29 -04:00
63a8415cee add services/capture/Dockerfile 2026-04-07 21:58:28 -04:00