Detect if webcamstream is running (js help needed)

Hi there,

in the GetHelp Section I came across this topic:https://discourse.octoprint.org/t/webcam-activates-leds/3361 and it made me think about implementing an energy saving feature in my lightslider plugin. So it only activates the led_strip when the webcamstream is viewed and turns it off if not.

As @supertaz mentioned in the discussion

I want to modify the components outside of the octoprint as little as possible (keep things simple so even a not so tech savvy person can use the plugin).
So I looked into the way octoprint pauses the webcam stream when the tab is not focused.

I found the js function which starts and stops the mjpg_stream.
From the looks of it, with reading the value of webcamImage.attr("src"); or the return of the webcamLoaded() function it should be possible to detect if the stream is running or stopped.

My Problem is, I'm not so deep into javascript/webdesign.
Can another plugin (which already places some buttons/slider on the control tab) read the mentioned value or call the function?
Better yet, can this plugin be notified when the value or return value of the function changes?

kind regards
Steffen

Maybe you could do a knockout computed function to the webcamLoaded() function you mention. If you do that though, wouldn't you probably also want to check to see if you are capturing timelapse stills in order for the light to be on or not. That could be embedded in the knockout computed function as well.

I actually just looked at the OctoPrint code and the function you mentioned here is actually already a knockout observable true/false in the control view model. So all you would have to do in your code would be to check against self.control.webcamLoaded()...ie

if self.control.webcamLoaded() { 
   //do something here
} else {
  // do something else here
}

or alternately if you just want to act when the condition is false...

if !self.control.webcamLoaded() { 
   //do something here
}

Thanks for taking the time @jneilliii .
I inserted the following into the lightslider.js code:

if self.control.webcamLoaded() {
console.log('webcamLoaded function returned stream_enabled!\n');
} else {
// do something else here
console.log('webcamLoaded function returned stream_disabled!');
}

But when I inspect the generated webpage with chrome, in the DevTools Console an error is reported "unexpected identifier" pointing to the line where the variable should be used:

I guess this means it does not know the variable / can not access it.
The plugin is also not loaded any further after that error...

Try wrapping the call in parenthesis maybe? And/ Or move the if then code block into a function, i.e. inside your purecomputed function just below that?

1 Like

The parenthesis were missing, that fixed the error.

But even though that fixed the error, it got me thinking. Even if I put the if-then-block in a function, it would need to be called by something...

So I took a look at how the disable/enable functions are actually called by octoprint. And found this nice onTabChange and onBrowserTabVisibilityChange functions which call the enable/disable functions.
With these in the lightslider.js I do not need to bother with reading the variable but can use them directly for turning on/off the light. Nice!

Yes that's next on my todo list :grin:

So far thanks for your help @jneilliii

I will post a link in the old thread to this solution if someone is still interested in doing something similar.

No problem. I think utilizing those functions you found in your plugin will definitely work triggering on/off but you would definitely need to include another check against running timelapse/printing or not but don't know if there is a hook for that directly like the webcam one you found. You could check against settings to see if timelapse is enabled and there are event hooks for when printing is starting/ending/etc. that can flag a boolean like this.

self.onEventPrinterStateChanged = function(payload) {
	if (payload.state_id == "PRINTING" || payload.state_id == "PAUSED"){
		self.isPrinting(true);
	} else {
		self.isPrinting(false);
	}
}

or to check state on the python side for example and process the state

self._printer.get_state_id()

Yes already thinking about that, currently I am looking into a more generic approach (since I also got the nifty telegram plugin running which for example, takes pictures on start/end of a printjob)...

From what I could gather, the procedure to take a picture with octoprint is by sending a request to a defined mjpg_streamer url (usually http://127.0.0.1:8080/?action=snapshot ).
This url is also stored as a variable in octoprint (can bee seen in gui, or code below)

My Idea would be to either listen for the request to the above mentioned url (did some digging, might be a little performance hungry doing so in python and therefore not suitable).
Or to use a proxy (replacing the default url to the one of the proxy) and thereby detecting the request for a picture, switching the leds on, wait 1-2sec for the whitebalance of the camera (may need some time to adjust), take the picture by issuing the request to mjpg_streamer and turn the leds off afterwards.

So far for my ideas, I am currently evaluating how much effort it would be to realize one or the other...

If anybody got another way to get around this, please let me know :wink:

If you are interested in not only detecting the camera, but the current server type, take a look at this python code.

This is the request handler for the above function.

Here is a python function for testing the the camera snapshot . This could be modified to detect a stream pretty easily.

Here is the request handler for the camera snapshot detection.

All of the above would reqire some modification for your purpose, but I think it might be helpful to see an example.

Good luck!