Pause video streams when browser not visible

I found that when I turn off my tablet screen, mjpg streams in the dashboards continue to play. I’ve also found that on the PC, when my dashboard webpage is not visible, the streams also continue to play.

I’m expecting that with a few dashboard tablets around the house, and occasional views on phones and PC can result in 20 streams that no one is looking at, creating a massive load on my Blue Iris PC.

Is there a way to get the streams to pause when they are not visible? Perhaps by using an embedded player that can respond to browser visibilitychanged events?

1 Like

Hey @RedDeadFred welcome to the community and thanks for posting. I’ve moved this post into the Feature Requests category so it can be voted on and renamed the thread title accordingly.

That is an interesting idea on the Page Visibility API. Out of curiosity, what browser are you using for displaying the dashboards on your tablets?

2 Likes

Hi @josh, thanks for moving it.

I’m using Fully Kiosk on the tablets, and chrome on the mobiles and PC. I tried the Fully Kiosk “Pause Webview while in Background (experimental)” option but it didn’t stop the streams.

BTW, I was impressed with how easy it was to get a dashboard up in SharpTools - after my experiences with SmartThings, ActionTiles, and Tasker I was expecting a long and painful process, but SharpTools was easy and just worked right from the start. My only obstacle was trying to figure out how to get the android app to display the web dashboards, as it wasn’t clear that they are separate, especially as the web version is sometimes called “The App”.

Thanks for considering this feature. The load on my Blue Iris PC is the only thing stopping me from wall mounting the tablets and letting others use it.

2 Likes

Be sure to scroll up to the top and cast a vote! :grinning:

Oh I’m so hurt that I’m the only one who has voted for this so far. :sob:

And I’m a bit perplexed why this isn’t a problem for anyone else.

I’ve done some testing and found that Chrome and Fully Kiosk on Android will stop the stream after 5 minutes. When the screen is turned back on, the stream sometimes resumes, sometimes shows the last frame, and sometimes shows a grey box or broken image icon. It’s a problem for my parents in their 70’s that don’t know about pulling down the page to reload it, and even worse, if the last frame is shown they may not realize that the stream has stopped.

With Chrome on Windows 10, the stream does eventually stop after a much longer period - something like 30 minutes or longer. The resume behaviour is similar to Android - unreliable.

I’ve created a HTML wrapper which I dropped into my Blue Iris web server directory, and in my testing so far it works very well:

	<!DOCTYPE html>
	<html lang="en">
		<head>
			<meta charset="UTF-8">
			<title>Streaming</title>
		</head>
		<body>
			<script type="text/javascript">
				var pathParts = window.location.pathname.split('/');
				if (pathParts.length < 3) {
					console.log("Error: path malformed, try: /mjpg.html/{camera short name}/video.mjpg");
					document.write("<p>Error: path malformed, try: /mjpg.html/{camera short name}/video.mjpg</p>");
				} else {
					var streamPathAndQuery = "/mjpg/" + pathParts.slice(2).join('/') + window.location.search;
					document.write("<img id='streamImg' src='" + streamPathAndQuery + "'</img>");
					
					// Set the name of the hidden property and the change event for visibility
					var hidden, visibilityChange;
					if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
						hidden = "hidden";
						visibilityChange = "visibilitychange";
					} else if (typeof document.msHidden !== "undefined") {
						hidden = "msHidden";
						visibilityChange = "msvisibilitychange";
					} else if (typeof document.webkitHidden !== "undefined") {
						hidden = "webkitHidden";
						visibilityChange = "webkitvisibilitychange";
					}

					function handleVisibilityChange() {
						var imgElement = document.getElementById("streamImg");
							console.log("imgElement: " + imgElement);
						if (imgElement == null) {
							return;
						}
						if (document[hidden]) {
							imgElement.src = "";
							document.title = "Not streaming";
						} else {
							imgElement.src = streamPathAndQuery;
							document.title = "Streaming";
						}
					}
					
					if (typeof document.addEventListener === "undefined" || hidden === undefined) {
						console.log("Disabling the stream when not visible requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
						document.write("<p>Disabling the stream when not visible requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.</p>");
					} else {
						document.addEventListener(visibilityChange, handleVisibilityChange, false);
					}
				}
			</script>
		</body>
	</html>

To use it: http://server/mjpg.html/{camera_short_name}/video.mjpg

My problem now is getting HTML or an iframe into a dashboard tile - any suggestions?

Thanks for the additional details and sharing the full example. I think it’s likely not a problem for most people because the impact is fairly low… likely for a few reasons.

  • When switching to another dashboard (without media), the streaming stops
    • Some people keep their streams on a child dashboard and just have image snapshots or navigation buttons on their main dashboards
  • Most people are streaming from cameras on their LAN, so there’s not really a functional impact
    • In your case, it sounds like the concern is load on your Blue Iris server (see the last point)
  • For people who keep their dashboards displayed (eg. on a tablet), they usually expect the streams to be immediately accessible
  • For systems like Blue Iris, there’s a bunch of URL parameters you can use or alternative approaches you can take (eg. image snapshots)

That being said, it sounds like you have some sort of reliability issues that are causing more of a headache. You could use the ‘autorefresh’ feature of the Media Tiles to have the media streams attempt to autorestart themselves periodically… but then you’ll probably be back to your core issue of wanting the streams to stop when the browser loses visibility. :confused:

1 Like

Thanks josh for explaining other people’s use-cases. I feel like bit of a noisy trouble-maker. :sweat_smile:

Yeah as I learnt more about this the reliability issue has become a bigger problem for me. I initially thought that each device would add more load to Blue Iris, but if they’re all displaying the same streams then the load is capped. It’s still a big load, but it’s manageable (5 streams = 20% CPU on my 5.0GHz 8-core shared system).

I’ve just discovered that Fully Kiosk supports user script injection, so I have a path forward for the wall-mounted tablets. Mobile phones and PCs are still a problem as I don’t have control of those browsers.

I’m really hoping that more people vote for Embed Web page from 3rd-party site into dashboard (iframe or otherwise) which would also solve my problems.

PS: this is what the reliability issue looks like when the screen has been off for >30m (>5m for Android). This is on my PC, but same thing happens on Android. In this case it’s obvious that you need to pull down on the screen to reload the dashboard, but if it’s daytime, and they’re frozen on a daytime frame, then it’s impossible for my elderly parents to know if it’s live or not. When the doorbell rings and the tablets turn on, I want my parents to be able to glance at the tablet before opening the door, not checking timestamps or swaying trees to figure out if the streams are working or not.

Got it working well with user script injection. Streams come back within 1 second when turning on the screen, and so far no stalled streams. Can also see an immediate CPU drop on the Blue Iris PC.

Just in case someone else needs it (unlikely), here’s the code:

	// Set the name of the hidden property and the change event for visibility
	var hidden, visibilityChange;
	if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
		hidden = "hidden";
		visibilityChange = "visibilitychange";
	} else if (typeof document.msHidden !== "undefined") {
		hidden = "msHidden";
		visibilityChange = "msvisibilitychange";
	} else if (typeof document.webkitHidden !== "undefined") {
		hidden = "webkitHidden";
		visibilityChange = "webkitvisibilitychange";
	}

	var streamingImgs = [];
	var img;

	function handleVisibilityChange() {
		if (streamingImgs.length == 0) {
			// find all imgs with mjpg streams
			var imgs = document.getElementsByTagName("img");
			for (img of imgs) {
				if (img.src != undefined && img.src.includes(".mjpg")) {
					streamingImgs.push(img);
					img.setAttribute("srcBackup", img.getAttribute("src"));
				}
			}
			console.log("found streaming imgs: " + streamingImgs.length);
		}


		if (document[hidden]) {
			for (img of streamingImgs) {
				img.src = "";
			}
		} else {
			for (img of streamingImgs) {
				img.setAttribute("src", img.getAttribute("srcBackup"));
			}
		}
	}


	if (typeof document.addEventListener === "undefined" || hidden === undefined) {
		console.log("Disabling the stream when not visible requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
	} else {
		document.addEventListener(visibilityChange, handleVisibilityChange, false);
	}
2 Likes