feat: add analysis_image field to stream status for client-side verification

Add a boolean analysis_image field to the CMD_QUERY status response that
reports whether zms is actually sending analysis images (with motion zone
overlays) or regular capture images. This lets MonitorStream.js detect
when the stream state is out of sync with what the client requested and
re-send the CMD_ANALYZE_ON/OFF command to correct it.

The field is true only when frame_type is FRAME_ANALYSIS, shared memory
is valid, and the monitor has analysis enabled — matching the same
condition used to select the image in the streaming loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pull/4693/head
Isaac Connor 2026-03-08 15:44:49 -04:00
parent 7d78b722d0
commit 4df2bf4f0b
3 changed files with 18 additions and 3 deletions

View File

@ -255,6 +255,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
bool forced;
int score;
int analysing;
bool analysis_image;
} status_data;
status_data.id = monitor->Id();
@ -302,7 +303,10 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
status_data.delay = FPSeconds(now - last_frame_sent).count();
status_data.zoom = zoom;
status_data.scale = scale;
Debug(2, "viewing fps: %.2f capture_fps: %.2f analysis_fps: %.2f Buffer Level:%d, Delayed:%d, Paused:%d, Rate:%d, delay:%.3f, Zoom:%d, Enabled:%d Forced:%d score: %d",
status_data.analysis_image = (frame_type == FRAME_ANALYSIS) &&
monitor->ShmValid() &&
(monitor->Analysing() != Monitor::ANALYSING_NONE);
Debug(2, "viewing fps: %.2f capture_fps: %.2f analysis_fps: %.2f Buffer Level:%d, Delayed:%d, Paused:%d, Rate:%d, delay:%.3f, Zoom:%d, Enabled:%d Forced:%d score: %d analysis_image: %d",
status_data.fps,
status_data.capture_fps,
status_data.analysis_fps,
@ -314,7 +318,8 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
status_data.zoom,
status_data.enabled,
status_data.forced,
status_data.score
status_data.score,
status_data.analysis_image
);
DataMsg status_msg;

View File

@ -151,7 +151,7 @@ default :
$data = unpack('ltype', $msg);
switch ( $data['type'] ) {
case MSG_DATA_WATCH :
$data = unpack('ltype/imonitor/istate/dfps/dcapturefps/danalysisfps/ilevel/irate/ddelay/izoom/iscale/Cdelayed/Cpaused/Cenabled/Cforced/iscore/ianalysing', $msg);
$data = unpack('ltype/imonitor/istate/dfps/dcapturefps/danalysisfps/ilevel/irate/ddelay/izoom/iscale/Cdelayed/Cpaused/Cenabled/Cforced/iscore/ianalysing/Canalysisimage', $msg);
$data['fps'] = round( $data['fps'], 2 );
$data['capturefps'] = round( $data['capturefps'], 2 );
$data['analysisfps'] = round( $data['analysisfps'], 2 );

View File

@ -1337,6 +1337,16 @@ function MonitorStream(monitorData) {
}
} // end if canEdit.Monitors
// Verify analysis image state matches what we requested
if (streamStatus.analysisimage !== undefined) {
const want_analysis = this.analyse_frames && streamStatus.analysing != ANALYSING_NONE;
const got_analysis = !!streamStatus.analysisimage;
if (want_analysis != got_analysis) {
console.log('Analysis image mismatch: want=' + want_analysis + ' got=' + got_analysis + ', re-sending command');
this.streamCommand({command: this.analyse_frames ? CMD_ANALYZE_ON : CMD_ANALYZE_OFF});
}
}
if (this.status.auth) {
if (this.status.auth != auth_hash) {
// Don't reload the stream because it causes annoying flickering. Wait until the stream breaks.