Issue
I'm using reactjs and for some reason, videos are not autoplaying on mobile. I'm using iOS 17, Safari Here is my code:
<div className="video" ref={videoRef} dangerouslySetInnerHTML={{
__html: `
<video
loop
muted
autoplay
playsinline
muted
defaultMuted
loop
>
<source src=${video} type="video/mp4" />
</video>
`}}>
On mobile, there is just a play button.
I also tried to play the video using javascript:
const videoRef = useRef(null)
useEffect(() => {
if (videoRef.current) {
const videoElement = videoRef.current.children[0];
videoElement.play();
}
})
However, I get the error: `The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission =.```
Edit: How I solved this issue:
Reason for the error: When on Low Power mode, Auto-play videos is off on Safari By Default
How I fixed it: If the video was not displaying, Simply we can add a postor attribute to video, which'll bring a play button for it to start playing, However, I used a img tag if video wasn't autoplaying as there is a play button then. Here is my code:
const [videoPlayed, setVideoPlayed] = useState(false)
useEffect(() => {
if (videoRef.current) {
const videoElement = videoRef.current.children[0];
videoElement.play().then(() => {
setVideoPlayed(true)
}).catch(err => { })
document.addEventListener("click", () => {
videoElement.play().then(() => setVideoPlayed(true)).catch(() => {})
document.removeEventListener("click", () => {})
})
}
return (
<>
{/* If video isn't played */}
<div className="image">
{!videoPlayed && <img src={thumbnail} alt="Alt" />}
</div>
<div className="video" ref={videoRef} style={{
display: videoPlayed ? "block" : "none"
}} dangerouslySetInnerHTML={{
__html: `
<video
loop
muted
autoplay
playsinline
muted
defaultMuted
loop
poster="${thumbnail}"
>
<source src=${video} type="video/mp4" alt="content" />
</video>
`}}>
</div>
)
In the above code, There'll be a placeholder image. If the video is able to autoplay, then video will be start playing. In some cases, the video still isn't played, also there is no error, So to fix that, I've added a event listener for click, which'll play the video.
Thanks @DarshShah, @JaromandaX, @MohamdImran For helping me solving this issue!
Solution
Autoplay policies on mobile browsers, especially Safari on iOS, can be quite challenging due to user experience and data consumption considerations. To address this, browsers typically require user interaction before allowing autoplay.
you're facing this issue due to autoplay is not allowed without user interaction on mobile devices. The attempt to play the video using JavaScript won't work unless a user interaction event triggered .so play method should be triggered in response to a user interaction, like a button click or so , something like
const handlePlay = () => {
const videoElement = videoRef.current.children[0];
videoElement.play();
};
<button onClick={handlePlay}>Play My Video</button>
another solution would be using the playsinline attribute due to Safari on iOS has a requirement that videos must be played inline. make sure that you included this attribute in your video tag
<video
loop
muted
autoPlay
playsInline
defaultMuted
loop>
<source src={video} type="video/mp4" />
</video>
Another solation if above didn't work for anyone , we can try to play the video component mounted via useEffect hook by passing an Empty dependency array to ensure that it runs only once on mount also I've combined timeout func to come around the browser restriction especially on mobile devices , I'll will explain Now By delaying the play() method with a timeout, you like creating a small window after the initial render during which the play() method is called. This is essentially simulating user interaction, allowing the video to start playing.
import React, { useRef, useEffect } from 'react';
const VideoPlayer = ({ video }) => {
const videoRef = useRef(null);
useEffect(() => {
const playVideo = () => {
if (videoRef.current) {
setTimeout(() => {
videoRef.current.play().catch(error => console.error('Autoplay error:', error));
}, 500); // Adjust the delay as needed
}
};
// Play the video on page load
playVideo();
}, []); // Empty dependency array ensures the effect runs only once on mount
return (
<div>
<video ref={videoRef} loop muted playsInline defaultMuted>
<source src={video} type="video/mp4" />
</video>
</div>
);
};
export default VideoPlayer;
Answered By - Mohamd Imran
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.