简体   繁体   中英

HTML5 Audio object doesn't play in Safari

On my page , I dynamically create an HTML5 Audio element in JavaScript:

bell = new Audio("alarmclock.mp3");

Later on (in response to a jQuery Countdown object expiring), I play it:

bell.play();

Results:

  • Chrome (6.0.472.55) for Mac: The audio plays fine.
  • OmniWeb (5.10.2): The audio plays fine.
  • Safari (5.0.1) for Mac: I hear nothing. The audio plays fine. (I don't know why it didn't work earlier.)
  • MobileSafari (iOS 3.1.3—the latest version for my device): I hear nothing.

How would I go about troubleshooting this? I'd really like to have it working in MobileSafari so my web app can be portable.

About iPhone Safari: It seems play() work when launched by an onclick event. See http://groups.google.com/group/iphonewebdev/browse_thread/thread/91e31ba7ae25e6d4?hl=en

Good question with "How would I go about troubleshooting this?". Here would be my plan of attack...

  • Debug with Safari on Mac; if you get it working there, then go test with MobileSafari, since the latter is more of a pain.
  • Start over with a blank page. Insert HTML5 audio element with this MP3 file statically (not via JavaScript).
  • Keep working with your minimal page. Use jQuery's $(document).ready(function () { /* ... */ }) to load the audio on page load. Does it still work?
  • OK, now try to add your countdown logic to the demo page---as little of it as possible. Did that cause the problem?
  • If you've reached this point and it's still working on your demo page, you know that it's going to be something about all the other complicated things on your site, and not a problem with audio or even dynamically-loaded audio. In which case, good luck :-S. Either add things to your blank page, testing each time, or temporarily remove them from your original page, until it works. Then you'll know what caused the problem.

Good news everybody

I read somewhere that once you've played the sound once within a user interaction such as touch or click, you can then play it dynamically from your code.

So set volume to zero and play all loaded sounds in one go.

I had a listener on 'touchstart' with a single instantiated function that played all the sounds once the user touches the screen.

Here's how I did it in my REACT didMount()

componentDidMount() 
{
    
    let that = this;
    document.body.addEventListener('touchstart', function(evt) //First touch event on the screen will trigger this
        { 
            console.log("Audio Setup for iOS:", that.state.allow_sound);
            if(!that.state.allow_sound) //False on initial load
            {
                var Audio1 = document.getElementById("ping");
                Audio1.load();  
                Audio1.volume = 0;
                Audio1.play();          
                
                var Audio2 = document.getElementById("boom");
                Audio2.load();  
                Audio2.volume = 0;
                Audio2.play();  
                        
                var Audio3 = document.getElementById("splash");
                Audio3.load();  
                Audio3.volume = 0;
                Audio3.play();          
                
                var Audio4 = document.getElementById("hit");
                Audio4.load();  
                Audio4.volume = 0;
                Audio4.play();                          

                that.setState({allow_sound : true})
            }
    });
}

Then you can call these sounds dynamically from within the code.

Use

bell = new Audio("alarmclock.mp3");
/*** The magical line ***/
bell.load()

bell.play()

Its preferable to use the new Audio() and load() on page load and play() it in some function call. Because load() takes some time. So better to load() the audio on page load to reduce latency. Hope it works. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM