@@ -88,13 +88,59 @@ $(function () {
8888 zoomSpeed : parseInt ( localStorage . getItem ( 'zoomSpeed' ) ) || 3 ,
8989 useAuth : localStorage . getItem ( 'ptz_use_auth' ) === 'true' ,
9090 authUsername : localStorage . getItem ( 'ptz_auth_username' ) || '' ,
91- authPassword : localStorage . getItem ( 'ptz_auth_password' ) || ''
91+ authPassword : localStorage . getItem ( 'ptz_auth_password' ) || '' ,
92+ // Inference speed optimization settings
93+ maxDimension : parseInt ( localStorage . getItem ( 'ptz_maxDimension' ) ) || 640 ,
94+ jpegQuality : parseFloat ( localStorage . getItem ( 'ptz_jpegQuality' ) ) || 0.6 ,
95+ adaptiveQuality : localStorage . getItem ( 'ptz_adaptiveQuality' ) !== 'false' // default true
9296 } ;
9397
9498 let availableCameras = [ ] ;
9599
96100 let prevTime ;
97101 let pastFrameTimes = [ ] ;
102+
103+ // Adaptive quality tracking
104+ let consecutiveDetections = 0 ;
105+ let lastDetectionTime = 0 ;
106+
107+ /**
108+ * Create detector with current optimization settings
109+ */
110+ function createDetector ( apiKey ) {
111+ return new MoondreamDetector ( apiKey , {
112+ maxDimension : settings . maxDimension ,
113+ jpegQuality : settings . jpegQuality ,
114+ maxPendingRequests : 2
115+ } ) ;
116+ }
117+
118+ /**
119+ * Get adaptive quality based on tracking state
120+ * When tracking is stable (consecutive detections), use lower quality
121+ */
122+ function getAdaptiveQuality ( ) {
123+ if ( ! settings . adaptiveQuality ) {
124+ return settings . jpegQuality ;
125+ }
126+ // If we have 5+ consecutive detections, drop quality further
127+ if ( consecutiveDetections >= 5 ) {
128+ return Math . max ( 0.4 , settings . jpegQuality - 0.1 ) ;
129+ }
130+ return settings . jpegQuality ;
131+ }
132+
133+ /**
134+ * Update detector quality based on adaptive mode
135+ */
136+ function updateDetectorQuality ( ) {
137+ if ( detector ) {
138+ detector . setPerformanceOptions ( {
139+ jpegQuality : getAdaptiveQuality ( ) ,
140+ maxDimension : settings . maxDimension
141+ } ) ;
142+ }
143+ }
98144
99145 async function enumerateCameras ( ) {
100146 try {
@@ -136,7 +182,7 @@ $(function () {
136182 onKeysChanged : ( keys ) => {
137183 if ( keys . moondream ) {
138184 settings . moondreamApiKey = keys . moondream ;
139- detector = new MoondreamDetector ( keys . moondream ) ;
185+ detector = createDetector ( keys . moondream ) ;
140186 window . reasoningConsole . logInfo ( 'Moondream API key configured' ) ;
141187 }
142188 }
@@ -146,12 +192,11 @@ $(function () {
146192
147193 if ( window . apiKeyManager . hasMoondreamKey ( ) ) {
148194 settings . moondreamApiKey = window . apiKeyManager . getMoondreamKey ( ) ;
149- detector = new MoondreamDetector ( settings . moondreamApiKey ) ;
195+ detector = createDetector ( settings . moondreamApiKey ) ;
150196 window . reasoningConsole . logInfo ( 'Loaded saved Moondream API key' ) ;
151197 } else {
152- detector = new MoondreamDetector ( settings . moondreamApiKey ) ;
198+ detector = createDetector ( settings . moondreamApiKey ) ;
153199 }
154-
155200 $ ( '#cameraIP' ) . val ( settings . cameraIP ) ;
156201 $ ( '#targetObject' ) . val ( settings . targetObject ) ;
157202 $ ( '#operationStyle' ) . val ( settings . operationStyle ) ;
@@ -188,6 +233,13 @@ $(function () {
188233 $ ( '#zoomSpeed' ) . val ( settings . zoomSpeed ) ;
189234 $ ( '#zoomSpeedValue' ) . text ( settings . zoomSpeed ) ;
190235
236+ // Inference speed optimization settings
237+ $ ( '#adaptiveQuality' ) . prop ( 'checked' , settings . adaptiveQuality ) ;
238+ $ ( '#maxDimension' ) . val ( settings . maxDimension ) ;
239+ $ ( '#maxDimensionValue' ) . text ( settings . maxDimension ) ;
240+ $ ( '#jpegQuality' ) . val ( settings . jpegQuality ) ;
241+ $ ( '#jpegQualityValue' ) . text ( settings . jpegQuality . toFixed ( 1 ) ) ;
242+
191243 ptzController = new PTZController ( settings . cameraIP , {
192244 useAuth : settings . useAuth ,
193245 username : settings . authUsername ,
@@ -399,6 +451,30 @@ $(function () {
399451 ptzController . setSpeed ( { zoom : val } ) ;
400452 } ) ;
401453
454+ // Inference speed optimization settings
455+ $ ( '#adaptiveQuality' ) . on ( 'change' , function ( ) {
456+ settings . adaptiveQuality = $ ( this ) . is ( ':checked' ) ;
457+ localStorage . setItem ( 'ptz_adaptiveQuality' , settings . adaptiveQuality . toString ( ) ) ;
458+ updateDetectorQuality ( ) ;
459+ window . reasoningConsole . logInfo ( `Adaptive quality ${ settings . adaptiveQuality ? 'enabled' : 'disabled' } ` ) ;
460+ } ) ;
461+
462+ $ ( '#maxDimension' ) . on ( 'input' , function ( ) {
463+ const val = parseInt ( $ ( this ) . val ( ) ) ;
464+ settings . maxDimension = val ;
465+ $ ( '#maxDimensionValue' ) . text ( val ) ;
466+ localStorage . setItem ( 'ptz_maxDimension' , val . toString ( ) ) ;
467+ updateDetectorQuality ( ) ;
468+ } ) ;
469+
470+ $ ( '#jpegQuality' ) . on ( 'input' , function ( ) {
471+ const val = parseFloat ( $ ( this ) . val ( ) ) ;
472+ settings . jpegQuality = val ;
473+ $ ( '#jpegQualityValue' ) . text ( val . toFixed ( 1 ) ) ;
474+ localStorage . setItem ( 'ptz_jpegQuality' , val . toString ( ) ) ;
475+ updateDetectorQuality ( ) ;
476+ } ) ;
477+
402478 $ ( '#toggleAdvanced' ) . on ( 'click' , function ( ) {
403479 $ ( '#advancedSettings' ) . slideToggle ( 300 ) ;
404480 } ) ;
@@ -647,7 +723,15 @@ $(function () {
647723 async function detectionLoop ( ) {
648724 if ( ! isTracking ) return ;
649725
726+ // Skip if previous request still in flight (pipelining)
727+ if ( detector && ! detector . canPipeline ( ) ) {
728+ return ;
729+ }
730+
650731 try {
732+ // Update adaptive quality based on tracking state
733+ updateDetectorQuality ( ) ;
734+
651735 const startTime = Date . now ( ) ;
652736 const detections = await detector . detectInVideo ( video , settings . targetObject ) ;
653737 const detectionTime = Date . now ( ) - startTime ;
@@ -658,6 +742,13 @@ $(function () {
658742
659743 currentDetection = detections . length > 0 ? detections [ 0 ] : null ;
660744
745+ // Adaptive quality tracking
746+ if ( currentDetection ) {
747+ consecutiveDetections ++ ;
748+ } else {
749+ consecutiveDetections = 0 ;
750+ }
751+
661752 renderDetection ( currentDetection ) ;
662753
663754 if ( ! isTracking ) return ;
@@ -682,6 +773,7 @@ $(function () {
682773 console . error ( 'Detection loop error:' , error ) ;
683774 updateStatus ( 'Error: ' + error . message , true ) ;
684775 window . reasoningConsole . logError ( 'Detection error: ' + error . message ) ;
776+ consecutiveDetections = 0 ; // Reset on error
685777 }
686778 }
687779
0 commit comments