Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.


    To learn more about how to use our BBCode feature, please click here.

    Thank you, Code Forum.

JavaScript Safari can't play videos with sound using IntersectionObserver

hebrerillo

Active Coder
Hello there!

I am having trouble playing videos with sound in Safari. The videos are not played by a click, but when they are visible on the screen by using an Intersection Observer.

In Firefox, once there has been some user interaction with the page, a click for example, I can do this:


Code:
document.querySelector('video').play();
And the video will be played with sound. But in Safari it will not be played and will raise a "NotAllowedError" exception.

The only way to play a video with sound in Safari, is to place the previous instruction in a click handler. For example, in the click event of a button:

Code:
button.addEventListener('click', () => document.querySelector('video').play());
Is there any other way to play a video with sound in Safari?

One more question. It will be also helpful if I can play the video with sound on load. For example, Youtube shorts can be played with sound on first page load in Safari. How??
 
Check to see if Safari has a preference set to not allow video to play w/o user interaction, i.e. a button clicked, etc. CHeck Auto-Play under the "Websites" tab.
 
Your description make me think that Safari perhaps does not (fully) support the Intersection Observer ? Not that I have any experience with either of these.
Yes, Safari does support the intersection observer.

If I set the 'video.play()' inside an event handler, the video is played, paused when out of the view port, and played again when it is inside the view port via an Intersection Observer
 
Check to see if Safari has a preference set to not allow video to play w/o user interaction, i.e. a button clicked, etc. CHeck Auto-Play under the "Websites" tab.
I checked if there was a setting like you mentioned but did not find anything.

I can only play videos with sound inside a click event handler, as it is considered a user interaction. If I try to play videos outside a click handler, the video play raises a NotAllowedError exception, even though there has been previous user interaction, like a click in the document.
 
Here I attach a good example of my problem:

Code:
<!DOCTYPE html>
<html lang="en">
    <body>
        <video playsinline>
            <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
        </video>
        <script>
            const video = document.querySelector('video');
            video.muted = false;
            window.addEventListener('click', () => {
                window.setTimeout(() => video.play(), 3000); //This is not playing the video with sound in Safari
                //video.play();//This line plays the video with sound in Safari
            });
        </script>
    </body>
</html>

If the video is played directly in the event handler, the video plays with sound. But if the video is played after three seconds in a timeout, the video raises an exception!
 
Here I attach a good example of my problem:

Code:
<!DOCTYPE html>
<html lang="en">
    <body>
        <video playsinline>
            <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
        </video>
        <script>
            const video = document.querySelector('video');
            video.muted = false;
            window.addEventListener('click', () => {
                window.setTimeout(() => video.play(), 3000); //This is not playing the video with sound in Safari
                //video.play();//This line plays the video with sound in Safari
            });
        </script>
    </body>
</html>

If the video is played directly in the event handler, the video plays with sound. But if the video is played after three seconds in a timeout, the video raises an exception!

I am assuming this is because script is trying to play the video, which isn't considered user interaction.

This is the settings I was referring to:
CleanShot 2024-05-22 at 14.41.59@2x.png
 
I am assuming this is because script is trying to play the video, which isn't considered user interaction.

This is the settings I was referring to:
View attachment 2658
Hello and thanks for your quick answer!

In my previous code, the script is trying to play the video inside a click event handler, which is considered user interaction.

I have the same settings, "Stop media with Sound", for all websites, so for example, I can open a Youtube video or Short and it plays with sound. Why is not happening the same in the example I provided?
 
Code:
<!DOCTYPE html>
<html lang="en">
    <body>
        <video playsinline>
            <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
        </video>
        <script>
            const video = document.querySelector('video');
            video.muted = false;
            window.addEventListener('click', () => {
                window.setTimeout(() => video.play(), 3000); //This is not playing the video with sound in Safari
                //video.play();//This line plays the video with sound in Safari
            });
        </script>
    </body>
</html>

If the video is played directly in the event handler, the video plays with sound. But if the video is played after three seconds in a timeout, the video raises an exception!
So, it does not have anything to do with the Intersection API, that is good to know.
I can confirm this code works on Windows 11 with Chrome and Firefox, but not on iOS with Safari. Actually, the video does not play for me at all even without the timeout. I had to change 'click' to 'touchend' as I don't know how to "click" on iOS. Now the handler is being executed, I verified that by inserting an alert() , but video.play() just does not do anything al all. My normal course of action would be to run the debugger and see what's up, but on iOS that is not possible unless you also own a Mac. F*ck you, Apple 😡

So unfortunately I cannot help any further....
 
Here I attach a good example of my problem:

Code:
<!DOCTYPE html>
<html lang="en">
    <body>
        <video playsinline>
            <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
        </video>
        <script>
            const video = document.querySelector('video');
            video.muted = false;
            window.addEventListener('click', () => {
                window.setTimeout(() => video.play(), 3000); //This is not playing the video with sound in Safari
                //video.play();//This line plays the video with sound in Safari
            });
        </script>
    </body>
</html>

If the video is played directly in the event handler, the video plays with sound. But if the video is played after three seconds in a timeout, the video raises an exception!

This code, as is, plays the video with sound, after a delay, after clicking the page in Safari 17.5
 
So, it does not have anything to do with the Intersection API, that is good to know.
I can confirm this code works on Windows 11 with Chrome and Firefox, but not on iOS with Safari. Actually, the video does not play for me at all even without the timeout. I had to change 'click' to 'touchend' as I don't know how to "click" on iOS. Now the handler is being executed, I verified that by inserting an alert() , but video.play() just does not do anything al all. My normal course of action would be to run the debugger and see what's up, but on iOS that is not possible unless you also own a Mac. F*ck you, Apple 😡

So unfortunately I cannot help any further....
It is OK! Your answers are always welcome.
 
Back
Top Bottom