3 Commits

Author SHA1 Message Date
Isaac Connor
bf82278b6e feat: integrate EventStream into montagereview with zms recovery and fixes
- Integrate EventStream.js into montagereview.js for persistent MJPEG
  streaming in replay mode (speeds >= 1x), falling back to per-frame
  mode=single for speeds < 1x where zms lacks slow-motion support
- Add EventStream recovery logic: detect zms death via AJAX failures,
  img.onerror, and error responses; auto-restart with new connkey and
  exponential backoff (max 5 retries)
- Fix zms crash on bulk/interpolated frames: add stat() check in
  sendFrame() for SaveJPEGs & 1 path, fall through to ffmpeg_input
  when JPEG file doesn't exist on disk; send "No frame available"
  text frame instead of terminating when no source available
- Center monitor canvases: text-align in CSS for scale mode,
  horizontal offset calculation in maxfit2() for fit mode
- Reduce console noise: comment out high-frequency debug logs,
  convert error-path logs to console.warn/error
- Fix ESLint sourceType to "script" for traditional non-module JS
  files, resolving false-positive no-unused-vars on global functions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 19:14:06 -05:00
Isaac Connor
a12d9749eb fix: use DOM img element and rAF loop for MJPEG stream reception
A detached Image() object does not reliably decode multipart MJPEG
streams — browsers only update a DOM-attached <img> with each frame
from a multipart/x-mixed-replace response. Switch to creating a
hidden DOM <img> element and use requestAnimationFrame to copy
decoded frames to the canvas.

Also properly clean up the img element from the DOM in stop() and
switchEvent(), and guard drawFrame() against drawing before the
first frame has been decoded.

Tested: start, pause, play, seek, setRate, stop all verified
working against a live zms event stream.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 14:47:39 -05:00
Isaac Connor
516ff419a5 feat: add EventStream.js for persistent MJPEG event playback
Introduce EventStream constructor that manages a persistent zms MJPEG
connection for event playback, replacing the per-frame mode=single HTTP
request pattern. Frames arrive via a hidden Image element and are drawn
to a caller-supplied canvas on each onload.

Supports seek, pause, play, rate control, scale changes, and event
switching via the existing zms command-socket protocol. Follows the
same constructor-function pattern as MonitorStream.js.

Include the script in montagereview.php for upcoming integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 14:09:59 -05:00