Specify duration using the audio html element - javascript

I am using the audio HTML element to play audio in a webpage, it looks like this:
<audio src="http://www.mydomain/someaudio.mp3" preload="none" />
This causes the problem that the length of the audio track is 00:00 until the user clicks the play button.
Unfortunately I can't use the metadata preload value because the server the file is being
served from does not support it.
Is it possible to specify the length of the audio track in the HTML instead or via JavaScript?

Please try this
<script>
function myOnCanPlayFunction() {
console.log('Can play');
alert(document.getElementById('myaudio').duration);
}
function myOnCanPlayThroughFunction() {
console.log('Can play through');
alert(document.getElementById('myaudio').duration);
}
You check event occur in oncanplay or oncanplaythrough and duration property is length of the audio in seconds
Hope this help!

Related

How to handle "Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first." on Desktop with Chrome 66?

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

HTML5 autoplay once

The following javascript function serves and autoplays a audio file (via a HTML 5 audio tag), cuts the mp3 playback at 6 seconds and loops + autoplays the audio from the beginning.
javascript:
function updateaudio() {
var a_str = '<audio autoplay source src="audio/coolsound.mp3" type="audio/mpeg"></audio>';
document.getElementById('audio_span').innerHTML = a_str;
}
setInterval(updateaudio, 6000)
html:
<div><span id="audio_span"></span><script src="js/audio.js"></script></div>
Is there any using the html5 audio attribute to set autoplay playback to once off i.e. non-looping? Alternatively, is there another way to achieve this (via either javascript or html5)? Upon the audio event ending, I would like to set a flag and stop any playback.
Don't use setInterval() if you don't want a loop.
If you simply want to pause the playback after six seconds do:
setTimeout( function () {
document.getElementById('audio_span').pause();
}, 6000)):

Change firefox playback bar into a onclick button for audio

SAME ISSUE! As we all know firefox and audio is a problem because of patents and such. I found this little code on the internet to play my sounfile.
I would like to play multiple files instead of just one while having the display bar not show up in the browser
you can change the player width to 0 but than the user can not click the play button :P
Is there a way of possibly having the sound play on click of a link or button.
Please note. Do not give me codes that have no compatibility outside chrome and ie.
HTML
<audio id="audioplayer" preload controls loop style="width:400px;">
<source src="sounds/sound1.mp3">
<source src="sounds/sound1.caf">
</audio>
Javascript
<script type="text/javascript">
var audioTag = document.createElement('audio');
if (!(!!(audioTag.canPlayType) && ("no" != audioTag.canPlayType("audio/mpeg")) && ("" != audioTag.canPlayType("audio/mpeg")))) {
AudioPlayer.embed("audioplayer", {soundFile: "sounds/sound1.mp3"});
}
</script>
RECAP:
Have the sound play on a button or link click.
Have multiple sounds available to play (not just one)
Compatibility with firefox
non visible soundbar.
Still learning myself. But this is a button, with a script to play an audio file. (part of my own solution) Plays only 1 sound at a time, but doesn't show anything about it.
You could also make a funtion like this, without setting the src, using the pause() command.
currenttime is used to change the part where the audio file was.
Sound play button<br>
<script>
sound = new Audio();
function playSnd(soundSrc) {
sound.src = soundSrc;
sound.play();
}
</script>

Listen for when an HTML5 Audio element stops playing

I need to call a function when an HTML5 audio element stops playing. Specifically the function will reset the seek bar and change the pause icon to a play icon.
Here's my JavaScript:
var audio = document.getElementById('audio');
audio.addEventListener('ended', stopAudio);
function stopAudio() {
audio.stop();
$('.play-pause .play').show();
$('.play-pause .pause').hide();
}
.. only the code inside is not executing once called. The audio is playing successfully and ending successfully, it's just not calling my function. What am I missing?
It is because you are using getElementById and passing audio when I think you mean to use getElementsByTagName, either that or you have the wrong id for the audio element.
I needed:
audio.stop;
Instead of...
audio.stop();
Which fixed it :)
The HTML Audio Element has no method stop(). The reason your event handler isn't "working" is because the line audio.stop(); throws an error and nothing below it will execute.
Your code should look like below in order to detect if your audio has ended. There is no way to detect if it has been stopped but you can detect if it has ended or been paused. If you are looking for the code for when it's paused you replace the "ended" with "pause"
document.getElementById('audio').addEventListener("ended",function() {
$('.play-pause .play').show();
$('.play-pause .pause').hide();
}

Start HTML5 video at a particular position when loading?

I need HTML5 video to start at certain point. Let's say at time 50 seconds onward.
I tried but its not working as expected. is there something i am doing wrong?
Here is the code:
<video id="vid1" width="640" height="360">
<source src="file.webm" type="video/webm" />
Your browser does not support the video tag.
</video>
<script>
document.getElementById('vid1').currentTime = 50;
</script>
When the page loads, it just starts playing from beginning.
However if I call this during playback like after some time, it works fine.
Is there anything I am missing?
You have to wait until the browser knows the duration of the video before you can seek to a particular time. So, I think you want to wait for the 'loadedmetadata' event something like this:
document.getElementById('vid1').addEventListener('loadedmetadata', function() {
this.currentTime = 50;
}, false);
WITHOUT USING JAVASCRIPT
Just add #t=[(start_time), (end_time)] to the end of your media URL. The only setback (if you want to see it that way) is you'll need to know how long your video is to indicate the end time.
Example:
<video>
<source src="splash.mp4#t=10,20" type="video/mp4">
</video>
Notes: Not supported in IE
You can link directly with Media Fragments URI, just change the filename to file.webm#t=50
Here's an example
This is pretty cool, you can do all sorts of things. But I don't know the current state of browser support.
adjust video start and end time when using the video tag in html5;
http://www.yoursite.com/yourfolder/yourfile.mp4#t=5,15
where left of comma is start time in seconds, right of comma is end time in seconds.
drop the comma and end time to effect the start time only.
On Safari Mac for an HLS source, I needed to use the loadeddata event instead of the metadata event.

Categories