Reputation: 75
Chrome blocks auto-playing audio/video. I've found solutions for auto-playing video, but my use case requires auto-playing audio. Here is my code:
let audio = new Audio('music/test.mp3'); audio.play(); audio.loop = true;
This results in an "Uncaught (in promise) DOMException" on Chromium browsers because of new policies.
Upvotes: 7
Views: 19504
Reputation: 775
I've had to deal with this issue as well, it's quite annoying when you want to trigger all exceptions in the browser, and it triggers the audio one.
So, the best solution that I found in pure javascript:
let has_clicked;
window.addEventListener('click', () => {has_clicked = true;});
window.addEventListener('touchstart', () => {has_clicked = true;});
function playSound() {
if (!has_clicked)
return;
// insert the play code, for ex yours:
let audio = new Audio('music/test.mp3'); audio.play(); audio.loop = true;
}
Upvotes: 0
Reputation: 1450
The browser requires the user to explicitly start media playback by clicking a "play" button. Code below solves your problem.
<!DOCTYPE html>
<html>
<head>
<title>Play MP3 music on web</title>
<script>
function playMusic(){
var promise = document.querySelector('audio').play();
if (promise !== undefined) {
promise.then(_ => {
// Autoplay started!
}).catch(error => {
// Autoplay was prevented. Show a "Play" button so that user can start playback.
});
}
}
</script>
</head>
<body>
<p>Play MP3</p>
<input type="button" value="play music" onClick="playMusic();">
<audio loop id="sound">
<source src="audio/audio.mp3" type="audio/mpeg">
<p>Browser doesn't support html5</p>
</audio>
</body>
</html>
Upvotes: 1
Reputation: 84
This code may help. It will fire the autoplay (and loop) with a first user's interaction with the DOM.
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
</head>
<style>html,body{height:100%}</style>
<body>
<!-- SOUND -->
<audio loop id="sound">
<source src="sound.mp3" type="audio/mpeg">
<p>Browser doesn't support html5</p>
</audio>
<!-- CONTENT -->
<button onClick="audio_manager.play()">Play sound</button>
<button onClick="document.querySelector('body').style.backgroundColor = '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6);">Do something else</button>
<ol id="text"><li>Autoplay will be start on user first interaction with body (click anywhere to test)</li></ol>
<!-- JS SCRIPT -->
<script>
var audio_manager = {
// Variables
user_has_interacted: false,
detection_is_active: false,
/**
* Init function
*
* Detect first user's interaction
*/
init: function(){
// If already detecting => return
if( audio_manager.detection_is_active){
return false;
}
// Detection active
audio_manager.detection_is_active = true;
// Set up eventListener for user's first interaction
document.querySelector('body').addEventListener('click', audio_manager.detect_first_interaction, true);
},
detect_first_interaction: function(e) {
// Set user_has_interacted to true
audio_manager.user_has_interacted = true;
// Remove listener
document.querySelector('body').removeEventListener(e.type, audio_manager.detect_first_interaction, true);
// Play media (= Autoplay)
audio_manager.play();
// Log first detection
document.getElementById('text').innerHTML += "<li>Autoplay, first interaction detected on " + e.type + " on " + e.target.nodeName + "</li>";
},
/**
* Play function
*
* Play "sound" or init first user's detection
*/
play: function(){
// If user interaction, play media
if(audio_manager.user_has_interacted){
document.getElementById('sound').play();
return true;
}
// Init detection
audio_manager.init();
}
};
// Load autoplay
audio_manager.play();
// Uncomment next line to test autoplay on load without workaround => throw error "Uncaught (in promise) DOMException" or "NotAllowedError: The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission."
//document.getElementById('sound').play();
</script>
</body>
</html>
Not a perfect workaround, but useful in some case.
Upvotes: 0
Reputation: 2417
You're receiving an uncaught exception because you aren't handling an error.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play
Audio is an HTMLMediaElement
object, and the play()
method returns a promise. Therefore I recommend handling the error.
var promise = audio.play();
if (promise) {
//Older browsers may not return a promise, according to the MDN website
promise.catch(function(error) { console.error(error); });
}
One of two errors are possible:
NotSupportedError
This means that the audio source is not supported by the browser (probably due to audio format)
NotAllowedError
This is the one I suspect you are triggering. This means the user needs to explicitly trigger the audio.play()
, so the method is only usable if it is in response to a user generated event such as a click event.
Docs:
The user agent (browser) or operating system doesn't allow playback of media in the current context or situation. This may happen, for example, if the browser requires the user to explicitly start media playback by clicking a "play" button.
Upvotes: 13