Arnaud Leyder
Arnaud Leyder

Reputation: 7002

Low power mode detection in JavaScript for iOS11?

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

Answers (5)

Antonio Da Silva
Antonio Da Silva

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

fuweichin
fuweichin

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:

[^1]: cumulative-delay means actual average interval is obviously greater than given interval

Upvotes: 3

Seb G
Seb G

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

nvassalo
nvassalo

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

Shakti
Shakti

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

Related Questions