I'm working on a page that, on my client's request, loads playing a background soundtrack.
Of course it's just for those users who are not navigating with audio autoplay disabled.
So the simple piece of code used to start playing the music is something like the following:
<audio autoplay id="background-soundtrack">
<source src="mytrack.mp3" type="audio/mpeg">
</audio>
I'd like to make music stop (even better: make it fade out in a matter of a few seconds) as soon as the user clicks anywhere on the page -- it should work tapping on mobile devices too.
Can you please suggesitng me a smart way to achieve my goal?
It doesn't matter if it's pure JavaScript or jQuery.
Thanks!
try this jquery:
$('document').on('click','body',function(){
if ($('#background-soundtrack').paused == false){
$('#background-soundtrack').animate({volume: 0}, 1500,
//1500 duration time
function(){
$('#background-soundtrack').pause()
});
}
});
The HTML5 audio elements has the pause method, that you can use at "onClick" (work in touch too) event on body, document, window...
Like this (I delete the "-" in id):
document.onclick = function(e){
backgroundsoundtrack.pause();
}
<audio autoplay id="backgroundsoundtrack">
<source src="mytrack.mp3" type="audio/mpeg">
</audio>
I'm getting the error message..
Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.
..when trying to play video on desktop using Chrome version 66.
I did find an ad that began playback automatically on a website however using the following HTML:
<video
title="Advertisement"
webkit-playsinline="true"
playsinline="true"
style="background-color: rgb(0, 0, 0); position: absolute; width: 640px; height: 360px;"
src="http://ds.serving-sys.com/BurstingRes/Site-2500/Type-16/1ff26f6a-aa27-4b30-a264-df2173c79623.mp4"
autoplay=""></video>
So is by-passing Chrome v66's autoplay blocker really as easy as just adding the webkit-playsinline="true", playsinline="true", and autoplay="" attributes to the <video> element? Are there any negative consequences to this?
To make the autoplay on html 5 elements work after the chrome 66 update you just need to add the muted property to the video element.
So your current video HTML
<video
title="Advertisement"
webkit-playsinline="true"
playsinline="true"
style="background-color: rgb(0, 0, 0); position: absolute; width: 640px; height: 360px;"
src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
autoplay=""></video>
Just needs muted="muted"
<video
title="Advertisement"
style="background-color: rgb(0, 0, 0); position: absolute; width: 640px; height: 360px;"
src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
autoplay="true"
muted="muted"></video>
I believe the chrome 66 update is trying to stop tabs creating random noise on the users tabs. That's why the muted property make the autoplay work again.
For me (in Angular project) this code helped:
In HTML you should add autoplay muted
In JS/TS
playVideo() {
const media = this.videoplayer.nativeElement;
media.muted = true; // without this line it's not working although I have "muted" in HTML
media.play();
}
Try to use mousemove event listener
var audio = document.createElement("AUDIO")
document.body.appendChild(audio);
audio.src = "./audio/rain.m4a"
document.body.addEventListener("mousemove", function () {
audio.play()
})
The best solution i found out is to mute the video
HTML
<video loop muted autoplay id="videomain">
<source src="videoname.mp4" type="video/mp4">
</video>
Answering the question at hand...
No it's not enough to have these attributes, to be able to autoplay a media with audio you need to have an user-gesture registered on your document.
But, this limitation is very weak: if you did receive this user-gesture on the parent document, and your video got loaded from an iframe, then you could play it...
So take for instance this fiddle, which is only
<video src="myvidwithsound.webm" autoplay=""></video>
At first load, and if you don't click anywhere, it will not run, because we don't have any event registered yet.
But once you click the "Run" button, then the parent document (jsfiddle.net) did receive an user-gesture, and now the video plays, even though it is technically loaded in a different document.
But the following snippet, since it requires you to actually click the Run code snippet button, will autoplay.
<video src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" autoplay=""></video>
This means that your ad was probably able to play because you did provide an user-gesture to the main page.
Now, note that Safari and Mobile Chrome have stricter rules than that, and will require you to actually trigger at least once the play() method programmatically on the <video> or <audio> element from the user-event handler itself.
btn.onclick = e => {
// mark our MediaElement as user-approved
vid.play().then(()=>vid.pause());
// now we can do whatever we want at any time with this MediaElement
setTimeout(()=> vid.play(), 3000);
};
<button id="btn">play in 3s</button>
<video
src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" id="vid"></video>
And if you don't need the audio, then simply don't attach it to your media, a video with only a video track is also allowed to autoplay, and will reduce your user's bandwidth usage.
Extend the DOM Element, Handle the Error, and Degrade Gracefully
Below I use the prototype function to wrap the native DOM play function, grab its promise, and then degrade to a play button if the browser throws an exception. This extension addresses the shortcoming of the browser and is plug-n-play in any page with knowledge of the target element(s).
// JavaScript
// Wrap the native DOM audio element play function and handle any autoplay errors
Audio.prototype.play = (function(play) {
return function () {
var audio = this,
args = arguments,
promise = play.apply(audio, args);
if (promise !== undefined) {
promise.catch(_ => {
// Autoplay was prevented. This is optional, but add a button to start playing.
var el = document.createElement("button");
el.innerHTML = "Play";
el.addEventListener("click", function(){play.apply(audio, args);});
this.parentNode.insertBefore(el, this.nextSibling)
});
}
};
})(Audio.prototype.play);
// Try automatically playing our audio via script. This would normally trigger and error.
document.getElementById('MyAudioElement').play()
<!-- HTML -->
<audio id="MyAudioElement" autoplay>
<source src="https://www.w3schools.com/html/horse.ogg" type="audio/ogg">
<source src="https://www.w3schools.com/html/horse.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
I got this error
Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.
And here's what I did in my Angular Project
Key Point: Don't ever assume a video will play, and don't show a pause button when the video is not actually playing.
You should always look at the Promise returned by the play function to see if it was rejected:
ngOnInit(): void{
this.ensureVideoPlays();
}
private ensureVideoPlays(): void{
const video = document.querySelector("video");
if(!video) return;
const promise = video.play();
if(promise !== undefined){
promise.then(() => {
// Autoplay started
}).catch(error => {
// Autoplay was prevented.
video.muted = true;
video.play();
});
}
}
Source: Autoplay policy
In my case, I had to do this
// Initialization in the dom
// Consider the muted attribute
<audio id="notification" src="path/to/sound.mp3" muted></audio>
// in the js code unmute the audio once the event happened
document.getElementById('notification').muted = false;
document.getElementById('notification').play();
According to the new browser policy, the user must interact with DOM first before playing the Audio element.
If you want to play the media on page load then you can simply add autoplay property to audio element in HTML like this
<video id="video" src="./music.mp4" autoplay>
or if you don't want to do autoplay then you can handle this using Javascript. Since the autoplay property is set to true, media will be played, we can simply mute the media.
document.getElementById('video').autoplay = true;
document.getElementById('video').muted = true;
Imp: Now Whenever you play the media don't forget to turn the muted property to false. Like this
document.getElementById('video').muted = false;
document.getElementById('video').play();
Or you can also show a simple popup where the user will click the allow button in the modal. So he interacts with DOM first, then you don't need anything to do
I had a similar problem, I need to play the video without muting it. The way i did this, wait for a second then triggered the event by button. Here is my code
if (playVideo == '1') {
setTimeout(function() {
$("#watch_video_btn").trigger('click');
}, 1000);
}
Chrome needs a user interaction for the video to be autoplayed or played via js (video.play()).
But the interaction can be of any kind, in any moment.
If you just click random on the page, the video will autoplay.
I resolved then, adding a button (only on chrome browsers) that says "enable video autoplay". The button does nothing, but just clicking it, is the required user interaction for any further video.
I changed my UI to have the user press a button to load the website (and when the website loads after they click the button, the audio plays)
Since they interact with the DOM, then the audio plays!!!
In my case it's just a click sound which is automatically invoked at the start (which I don't mind if it's silenced). So I use:
const clickSound = new Audio('click.wav');
clickSound.play().catch(function (error) {
console.log("Chrome cannot play sound without user interaction first")});
to get rid of the error.
I had some issues playing on Android Phone.
After few tries I found out that when Data Saver is on there is no auto play:
There is no autoplay if Data Saver mode is enabled. If Data Saver mode is enabled, autoplay is disabled in Media settings.
Source
I encountered a similar error with while attempting to play an audio file. At first, it was working, then it stopped working when I started using ChangeDetector's markForCheck method in the same function to trigger a re-render when a promise resolves (I had an issue with view rendering).
When I changed the markForCheck to detectChanges it started working again. I really can't explain what happened, I just thought of dropping this here, perhaps it would help someone.
You should have added muted attribute inside your videoElement for your code work as expected. Look bellow ..
<video id="IPcamerastream" muted="muted" autoplay src="videoplayback%20(1).mp4" width="960" height="540"></video>
Don' t forget to add a valid video link as source
Open chrome://settings/content/sound
Setting No user gesture is required
Relaunch Chrome
Audio Autoplay property does not work in MS Edge
Type Chrome://flags in the address-bar
Search: Autoplay
Autoplay Policy
Policy used when deciding if audio or video is allowed
to autoplay.
– Mac, Windows, Linux, Chrome OS, Android
Set this to "No user gesture is required"
Relaunch Chrome and you don't have to change any code
Thanks in advance for any help you're able to give. The issue I'm having is that the following code is in a javascript function when a button is clicked. The desired behavior is that on button click, a video fades in, plays for 10 seconds, and fades back out. Then when the button is clicked again, this behavior repeats.
Issue is, the second time the button is clicked, the video fades in but is already at the end of the video and then fades out after 10 seconds. Any idea why the vid.currentTime is not properly resetting the video?
var webm = document.getElementById('src');
webm.src = "src.webm";
var vid = document.getElementById('video');
vid.currentTime = 0;
vid.play();
vid.fadeToggle(1000);
setTimeout(function() {
vid.fadeToggle(1000);
}, 10000);
and this is where the video file is imported
<video id="video" width="100%" Style="Display:none">
<source id="src" src="src.webm" type="video/webm" />
</video>
Additional info has come to light. This only happens in Chrome, and doesn't happen even in Chrome when it's opened locally, only when the html page is served statically via express.
Try
vid.load(); instead of vid.currentTime = 0;
Maybe you can try to add autplay to the video attribute, but I think the video will start looping.
<video id="video" width="100%" Style="Display:none" autoplay>
OR you can add this function or javascript line to your button function.
vid.load();
source: http://www.w3schools.com/tags/av_met_load.asp
Figured out that this was only an issue in chrome and seems to have to do with this question:
can't seek html5 video or audio in chrome
I'm having trouble with audio in Firefox. I have an .ogg audio clip in an <audio> tag, and Firefox does not start playing the file when the play button is fisrt pressed. However, if the play button is pressed and then a time is selected from the timeline, the audio will start playing from the time selected. The file will also start playing if the play button is pressed repeatedly (e.g. play/pause/play).
I'm also using the web audio API to run the audio through an AnalyserNode. The issue, however, does not seem to relate to the analyser specifically, as this can be removed without affecting this issue. It seems to have something to do with createMediaElementSource. If I remove the JavaScript code related to this, the issue disappears.
The audio file is being served from the same origin, so I'm fairly certain this is not a CORS issue (as described here). As I said, the audio will play, but only if a time is selected on the timeline.
I'm including the simplest example of the issue below. This would likely need to be run from an HTTP server (python -m http.server, python -m SimpleHTTPServer or whatever) in order to avoid any CORS issues. For this reason, I don't think I can include a JSFiddle demonstration of this issue here.
This issue appears to be Firefox only. It definitely does not affect Chrome, but I haven't actually tested any other browsers yet.
<audio id="audio" controls>
<source src="piano-sonata-no13.ogg" type="audio/ogg" />
</audio>
<script>
var audio_node = document.getElementById('audio');
var audioctx = new (window.AudioContext || window.webkitAudioContext)();
var analyser = audioctx.createAnalyser();
window.addEventListener('load', function(e) {
var source = audioctx.createMediaElementSource(audio_node);
source.connect(analyser);
source.connect(audioctx.destination);
}, false);
</script>
Edit: An example of this issue can be found here: http://mdn.github.io/media-source-buffer/
Try replacing the window "load" event listener with this:
audio_node.addEventListener('canplay', function(e) {
var source = audioctx.createMediaElementSource(audio_node);
source.connect(analyser);
source.connect(audioctx.destination);
}, false);
This issue appears to be related to a Firefox bug.
The gist of it is, it appears as if createMediaElementSource is currently somewhat broken in Firefox, and you can't use the audio API with createMediaStreamSource and have it work as expected.
I found a workaround here (WARNING: page autoplays audio), but as far as I can tell, it only works when autoplay is set to true. Quick testing suggests that setting audio.autoplay to true, and immediately calling audio.pause() may be an acceptable workaround to this issue. One downside to this method is that when the play button is pressed, the audio does not start at the very beginning of the file.
This solution would look something like this:
<audio id="audio" controls>
<source src="piano-sonata-no13.ogg" type="audio/ogg" />
</audio>
<script>
var audio_node = document.getElementById('audio');
audio_node.autoplay = true;
// Alternatively, the autoplay attribute can be set on the <audio> tag
var audioctx = new (window.AudioContext || window.webkitAudioContext)();
var analyser = audioctx.createAnalyser();
window.addEventListener('load', function(e) {
var source = audioctx.createMediaElementSource(audio_node);
source.connect(analyser);
source.connect(audioctx.destination);
audio_node.pause();
}, false);
</script>
I'm trying to play a sound when i click or hover over my play button? Here's what i have so far. I have a button, if i hover over it it changes the Image, now i also want it to play an mp3.
play a {
position:relative;
float:left;
width:155px;
height:134px;
background-image:url(../images/Goodsound_PLAY_UP.png);
}
play a:hover {
background-image:url(../images/Goodsound_PLAY_P.png);
I want to play a sound here
}
Im sorry for asking such an easy question. I'm an html noob, started last week.
It's not that easy to play a sound in HTML. In fact, it wasn't until the html5 audio was there ! Even if html5 is not supported everywhere, it's now a little bit easier to play a sound in the browser.
My advice is to use mediaelementJS, a javascript library that fills the gap between old browser and html5 audio (and video) spec. Do not use the player (that comes with a full control bar), but use only the mediaelementjs component. To use it, simply include the library in the head of your page
<script src="js/libs/mediaelement.min.js"></script>
First, you have to put an audio tag in your html :
<audio id="mySound" src="my_audio_file.mp3" type="audio/mpeg"></audio>
Then, call the Mediaelement library
var mySound = new MediaElement('mySound');
Finally, play it on your click or over event (here I use jQuery)
$('.play a').mouseover(function(){ mySound.play() });
You can use this:
JavaScript
var audio = $("#audio");
$("play a").mouseenter( function() {
audio.play();
}
where audio is an <audio> element, and play a is element which is hover.
Using jQuery:
$("object_element_id") .on ('mouseover', function(e){
// audio play code here
});
$("object_element_id") .on ('mouseout', function(e){
// audio pause/stop code here
});
Why "on"? Just imagine a "AJAX page refresh". For remove it:
$("object_element_id") .off ('mouseenter');
Why "mouseover" and "mouseout"? Maybe you want to add extra functions for each status, like change IMG SRC of the button, make some effects... feel free. And why the "e" element? The E element is the object who fired the event - the image, the link etc. Do everything with it (or just remove it).
For audio play, you can use HTML5 tags. It's easy and are supported by the major browsers (you didn't asked "retrocompatibility") You can cache the element (like Mateusz' answer) and use it:
var $audio = $("#audio_element_id"); //for cache the element
$audio.setAttribute('src', url_link); //for change the URL file (ir can be MP3, OGG...)
$audio.play(); //for the mouseover
$audio.stop(); //for the mouseout
Then, the final code:
var $audio = $("audio_element"); //caching
$("object_element_id") .on ('mouseover', function(e){
$audio.play();
});
$("object_element_id") .on ('mouseout', function(e){
$audio.stop();
});
You might also find this code useful (I think it is fairly modern, so it might not work with old browsers; I use it with Firefox 32).
<audio controls> <source src="song.mp3" type="audio/mpeg"> </audio>
There is a similar one for video, too:
<video width="320" height="240" controls> <source src="clip.mp4" type="video/mp4"> </video>