I created and maintain a video stream site for my company. One of the features is the playing of live streams company-wide. For some time I'm receiving complaints from some users that the streams stops if they change tabs. After taking a very long time to reproduce the problem (see this question) I found that Chrome will stop the stream to save battery power no matter the energy/memory saving options.
I tested in a page with only the following HTML:
<html>
<body>
<video src="<source of the video stream>" controls autoplay></video>
</body>
</html>
And the problem persisted: If I change tabs after the video starts and don't return to the video tab, on Chrome, WITH THE AUDIO UNMUTED, the video will stop after around 1 minute with the following message:
Uncaught (in promise) DOMException: The play() request was interrupted because
video-only background media was paused to save power.
https://developer.chrome.com/blog/play-request-was-interrupted/
(the real url in the error is shortened, but SO doesn't allow shortened urls)
Yet this doesn't happen on Youtube. In youtube the videos continue playing far beyond that, no matter if the tab is hidden or not. So I examined a playing youtube video and see that they call every couple seconds a url like this:
So I thought the answer was calling the backend frequently. As my system also calls the backend frequently to save statistics, I though I just needed to update the frequency of the calls.
It didn´t work. Not even in with a 2s frequency on backend calls. The video continues to stop after around 1 minute.
So... what's Youtube secret ? why won't their video stop and mine stops after 1 minute ? What do I have to do to maintain the video playing and avoid that message ?
This is a Angular frontend/nodejs backend system.
I've found the problem. Some parts of the above message aren't true
After almost 1 month trying to figure this one out I realized that I was misled to think that a simple page with only tag in it also created the problem. This isn't true. I won't delete this question as it has drawn attention and probably people are getting the same error. So I'll just add an answer showing what the problem was. Maybe it may help someone.
I've found that the real problem was that as the stream was being played I made checks in the stream to see if it was still running.
In fact I use the following code in a timer to see if the stream has started:
export async function isWebmStreamActive(url: string, globals: any): Promise<boolean> {
if (!globals.checarStream) return;
globals.checarStream = false;
let result : any;
let obj : any;
let audio : any;
try {
obj = { audio : new Audio(url) };
audio = obj.audio;
audio.muted = true;
result = await (new Promise(res => {
audio.addEventListener('error', () => {
res(false);
});
audio.addEventListener('playing', () => {
res(true);
});
audio.play();
}));
audio.pause();
audio.src = '/assets/som/silencio.ogg';
audio.load();
audio.play();
audio.pause();
} finally {
delete obj.audio;
obj = undefined;
}
globals.checarStream = true;
return result;
}
So before the live stream starts I keep checking with the above code if it has started. If so I change the source and play it. But after starting I continued to check in background the same way to check if the stream has stopped and to create an "automated" play and stop experience to the user. This continued check after stream starts is what was generating the problem. As soon as I removed this check and relied only on the stop/pause/end events of the player the problem was fixed.
I guess the continuous background of streams creation and destruction probably confused the energy saving system to stop the real live stream. I think it probably mistaken one of the "check streams" for the real live stream.
This is somewhat specific to my situation. But I hope it helps someone.