Reputation: 7002
Is there a JavaScript API to detect low power mode for iOS 11 Safari? I have not found any info on the subject yet.
Upvotes: 15
Views: 22934
Reputation: 91
Solution (UPDATE 2024)
1 - Add two elements to your DOM (video and img)
2 - Change CSS of elements, add style: block to your video and style: none to your image
3 - Add a javascript promise, check if onerror device is lower power mode, we remove the video and then change the img style display to block.
Working code bellow:
<video src="./public/assets/videos/particles.mp4" id="hero-video" autoplay="true" muted="muted" loop="" disablepictureinpicture="" playsinline=""></video>
<img id="hero-video-fallback" style="display: none;" src="./public/assets/videos/particles_fallback.jpg">
The javascript:
<script>
"use strict"
var videoElement = document.getElementById('hero-video');
var videoElementFallback = document.getElementById('hero-video-fallback');
var promise = videoElement.play();
if (promise !== undefined) {
promise
.catch(error => {
// Auto-play was prevented
// Show a UI element to let the user manually start playback
if (error.name === "NotAllowedError") {
console.log("Low Power Mode Active");
videoElement.remove();
videoElementFallback.style.display = "block";
}
})
.then(() => {
// if there is no error, then we play the video
videoElement.play();
});
}
</script>
You can also hide the video play button and controls completely just adding some CSS (not working if lower power mode ios, you still need to use javascript for that):
video::-webkit-media-controls {
display: none !important;
opacity: 0;
}
/* Could Use thise as well for Individual Controls */
video::-webkit-media-controls-play-button {
display: none;
}
video::-webkit-media-controls-panel {
display: none;
opacity: 1;
}
video::-webkit-media-controls-play-button {
display: none!;
appearance: none;
-webkit-appearance: none;
}
video::-webkit-media-controls-start-playback-button {
display: none ;
appearance: none;
-webkit-appearance: none;
}
video::-webkit-media-controls-overlay-play-button {
display: none;
appearance: none;
-webkit-appearance: none;
}
video::-webkit-media-controls-container{
display:none;
visibility: hidden;
opacity: 0 ;
-webkit-appearance: none ;
}
:host::shadow::-webkit-media-controls-container{
display: none;
}
Upvotes: 6
Reputation: 1920
For iOS 16 Safari, "Low Power Mode" (or say power saving mode) can be detected by checking actual interval of setInterval
, because cumulative delay [^1] effect happens in Low Power Mode.
For desktop Chromium 109, Energy Saver Mode (or say power saving mode) can be detected by checking frame rate of requestAnimationFrame
see online demo:
<iframe>
)[^1]: cumulative-delay means actual average interval is obviously greater than given interval
Upvotes: 3
Reputation: 87
.catch((error) => {
if (error.name === "NotAllowedError") {
//low power mode
}
I struggled with with same concept and one helpful link proved to be this browser check: https://video-dev.github.io/can-autoplay/
result: Video muted (Error "NotAllowedError": The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
So I now have a promise checking if the video is playing, if it is great. Otherwise I catch the NotAllowedError, seems to work ever time.
Upvotes: 7
Reputation: 69
Just like the "suspend" event suggestion, use a hidden video on the with autoplay loop muted
attrs, then listen to the play event when the video is mounted, like so:
testVideo
.play()
.then(() => {})
.catch((error) => {
//Do something like adding controls to allow user to manually play
});
});
This is the solution as of March 2022, since browsers aren't triggering the suspend event for autoplay cancellation.
Upvotes: 5
Reputation: 773
A workaround to get this done is:
Put a video (hidden) in the webpage with autoplay 'on', and then detect the 'suspend' event for that video. Whenever it is invoked, 'power mode is on'.
Here is the script:
const videoElement = document.getElementById('ID_of_video');
videoElement.addEventListener('suspend', () => {
// suspend invoked
// show play button
// iphone is in low power mode
});
videoElement.addEventListener('play', () => {
// video is played
// remove play button UI
// iphone is not in low power mode
});
You can also read the explanation here: Playing video when low power mode is on
Upvotes: 13