HTML 5 <audio> - Play file at certain time point - javascript

I have a simple auto playing snippet that plays the audio file however I was wondering either in JavaScript or as an attribute play that file at a certain time (ex. 3:26).
<script type="text/javascript">
var myAudio=document.getElementById('audio2')
myAudio.oncanplaythrough=function(){this.play();}
</script>
<audio id="audio2"
preload="auto"
src="file.mp3"
oncanplaythrough="this.play();">
</audio>
Any help would be great. Thanks in advance :)

The best way to do this is to use the Media Fragment URI specification. Using your example, suppose you want to load the audio starting at 3:26 in.
<audio id="audio2"
preload="auto"
src="file.mp3#t=00:03:26"
oncanplaythrough="this.play();">
</audio>
Alternatively, we could just use the number of seconds, like file.mp3#t=206.
You can also set an end time by separating the start from the end times with a comma. file.mp3#t=206,300.5
This method is better than the JavaScript method, as you're hinting to the browser that you only want to load from a certain timestamp. Depending on the file format and server support for ranged requests, it's possible for the browser to download only the data required for playback.
See also:
MDN Documentation - Specifying playback range
W3C Media Fragments URI

A few things... your script will first need to be after the audio tag.
Also you don't need the oncanplaythough attribute on the audio tag since you're using JavaScript to handle this.
Moreover, oncanplaythrough is an event, not a method. Let's add a listener for it, which will instead use canplaythough. Take a look at this:
<audio id="audio2"
preload="auto"
src="http://upload.wikimedia.org/wikipedia/commons/a/a9/Tromboon-sample.ogg" >
<p>Your browser does not support the audio element</p>
</audio>
<script>
myAudio=document.getElementById('audio2');
myAudio.addEventListener('canplaythrough', function() {
this.currentTime = 12;
this.play();
});
</script>
And finally, to start the song at a specific point, simply set currentTime before you actually play the file. Here I have it set to 12 seconds so it will be audible in this example, for 3:26 you would use 206 (seconds).
Check out the live demo: http://jsfiddle.net/mNPCP/4/
EDIT: It appears that currentTime may improperly be implemented in browsers other than Firefox. According to resolution of this filed W3C bug, when currentTime is set it should then fire the canplay and canplaythrough events. This means in our example, Firefox would play the first second or so of the audio track indefinitely, never continuing playback. I came up with this quick workaround, let's change
this.currentTime = 12;
to test to see if it has already been set, and hence preventing the canplaythrough to get called repeatedly:
if(this.currentTime < 12){this.currentTime = 12;}
This interpretation of the spec is still currently being disputed, but for now this implementation should work on most modern browsers with support for HTML5 audio.
The updated jsFiddle: http://jsfiddle.net/mNPCP/5/

I have a simple answer that will work for all
1- create a button that when clicked it plays the audio/video
2- test that audio playing when you click the button if it works to hide the button and
3- click button when page loads
window.onload =function(){
document.getElementById("btn").click();
}

Related

Correct way to play <audio> + <video> from Javascript

I'm getting different results i Firefox and Chrome when using <audio> and <video> with preload="none" and then trying to play from Javascript.
Let's say i was using preload="auto" or preload="metadata" :
audio.src = "filename";
audio.play();
That seems to work fine in both Firefox and Chrome but i want to use preload="none" and then Chrome dossent play.
So i'm trying this code with preload="none" :
audio.src = url;
audio.load();
audio.addEventListener('canplay', function(e) {
audio.play(); // For some reason this dossent work in Firefox
}, false);
audio.play(); // Added this so Firefox would play
I don't know if that's the correct way to do it.
I'm using :
Firefox 20.0.1
Chrome 25.0.1364.172 m
I made a demo : http://netkoder.dk/test/test0217.html
Edit :
In the 2nd audio player (on the demo page) it seems that when using preload="none" you have to use load().
But is it correct to just use play() right after load() or is the correct way to use an event to wait for the file to load before playing it ?
In the 3rd audio player it seems Firefox 20.0.1 dossent support the canplay event correctly when used with addEventListener() because it dossent trigger after load(), it triggers after play() and also triggers when scrubbing though the sound which dossent seem to be the way the canplay should work.
Using .oncanplay does work.
So the following code seems to work :
function afspil2(url) {
afspiller2.src = url;
afspiller2.load(); // use load() when <audio> has preload="none"
afspiller2.play();
}
function afspil3(url) {
afspiller3.src = url;
afspiller3.load(); // use load() when <audio> has preload="none"
//afspiller3.addEventListener('canplay', function() { // For some reason this dossent work correctly in Firefox 20.0.1, its triggers after load() and when scrubbing
// afspiller3.play();
//}, false);
afspiller3.oncanplay = afspiller3.play(); // Works in Firefox 20.0.1
}
I updated the demo to include the changes : http://netkoder.dk/test/test0217.html
My way of adding addEventListener inside the afspil3() function dossent seem good because the first time the function is called the code inside addEventListener is called 1 time. The second time the function is called the code inside addEventListener is called 2 time and then 3 times and so on.
It's because your audio tags are missing the required src attribute, or <source> tags. When I added them in your demo, all 3 players immediately began working in both Chrome and FF.
Also, I recently discovered that src cannot be an empty string and subsequently changed with JS. If there's a reason you can't set the src in the HTML, your best alternative, IMO, is to create the audio elements with Javascript:
var audio = new Audio();
audio.src = url;
audio.controls = true;
audio.preload = false;
// and so on
Edit: Ok. It seems that in Chrome, when the HTML is preload="none" it is necessary to call load() before playing when the src is changed. Your second audio doesn't preload, so your function needs to be this:
function afspil2(url) {
afspiller2.src = url;
afspiller2.load(); // add load call
afspiller2.play();
}
Then, it seems that in Firefox, it is necessary to set preload="auto"; when attaching an event to the canplay event, like in the 3rd function.
function afspil3(url) {
afspiller3.src = url;
afspiller3.preload = "auto";
afspiller3.load();
afspiller3.addEventListener('canplay', function(e) {
this.play(); // For some reason this dossent work in Firefox
}, false);
}
That just seems very strange, but I tested it multiple times, and each time it would play if preload="auto" is called, but would not play if it isn't called. Note that it wasn't necessary for the 2nd player, which was also preload="none" in the HTML tag.
Finally, Chrome has some odd behaviors if there are multiple <audio> elements on the page. For all three players, reloading the page and clicking "the big electron" link would play correctly.
Reloading and then clicking "Yoda" on the 2nd or 3rd player won't do anything, but it WILL play for the first player. But, if the top player is played first by any means - play button or either link - then the other two "Yoda" links will suddenly work.
Also, if you click a 2nd or 3rd "Yoda" link first after reload, and then click the top player, the previously clicked "Yoda" (that didn't previously play) will begin to play on its own after the top player stops.
Suffice it to say they have some bugs to work out.
The correct way in my opinion would mean using an existing solution, like http://mediaelementjs.com/
If your really interested in the details on the best way to play audio and video with js then look at the source:
https://github.com/johndyer/mediaelement/tree/master/src/js
https://github.com/johndyer/mediaelement/blob/master/src/js/me-mediaelements.js

seek to a point in html5 video

Is it possible to seek to a particular point in html5 video displayed in a web page? I mean ,can I input a particular time value (say 01:20:30:045 ) and have the player control (slider) move to that point and play from that point onwards?
In older version of mozilla vlcplugin I think this is possible by seek(seconds,is_relative) method..but I would like to know if this is possible in html video.
Edit:
I created the page with video and added javascript as below.When I click on the link ,it displays the time of click..but it doesn't increment the play location..but continues to play normally.
Shouldn't the video play location get changed?
html
<video id="vid" width="640" height="360" controls>
<source src="/myvid/test.mp4" type="video/mp4" />
</video>
<a id="gettime" href="#">time</a>
<p>
you clicked at:<span id="showtime"> </span>
</p>
javascript
$(document).ready(function(){
var player = $('#vid').get(0);
$('#gettime').click(function(){
if(player){
current_time=player.currentTime;
$('#showtime').html(current_time+" seconds");
player.currentTime=current_time+10;
}
});
}
);
You can use v.currentTime = seconds; to seek to a given position.
Reference: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/currentTime
Unfortunately it seems with some movie elements it behaves differently than others. For instance with an amazon video_element, it seems you must call pause before you can seek anywhere, then call play. However, if you call play "too quickly" after setting the currentTime then it won't stick. Odd.
Here is my current work around:
function seekToTime(ts) {
// try and avoid pauses after seeking
video_element.pause();
video_element.currentTime = ts; // if this is far enough away from current, it implies a "play" call as well...oddly. I mean seriously that is junk.
// however if it close enough, then we need to call play manually
// some shenanigans to try and work around this:
var timer = setInterval(function() {
if (video_element.paused && video_element.readyState ==4 || !video_element.paused) {
video_element.play();
clearInterval(timer);
}
}, 50);
}
Top answer is outdated.
You can still use:
this.video.currentTime = 10 // seconds
But now you also have:
this.video.faskSeek(10) // seconds
The docs provide the following warnings regarding the fastSeek method:
Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.
The HTMLMediaElement.fastSeek() method quickly seeks the media to the new time with precision tradeoff.
If you need to seek with precision, you should set HTMLMediaElement.currentTime instead.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/fastSeek
Based on the above I guess the following is best if cross browser compatibility and performance are your top priority:
const seek = secs => {
if (this.video.fastSeek) {
this.video.fastSeek(secs)
} else {
this.video.currentTime = secs
}
}
seek(10)
If you prefer accuracy over performance then stick with:
this.video.currentTime = secs
At the time of writing faskSeek is only rolled out to Safari and Firefox but expect this to change. Check the compatibility table at the above link for the latest info on browser compatibility.

Dynamically using the first frame as poster in HTML5 video?

I'm wondering if there's any straightforward way to achieve this effect, without needing backend code to extract a frame, save it as a jpg and database it somewhere.
An effect whereby the first frame of the video just shows up as the poster when the video loads would be so helpful (it would only work if the browser can play back the video obviously, which might be a little different from how poster traditionally works, but that is not a concern.
Did you try the following?
just append time in seconds #t={seconds} to source URL:
<video controls width="360">
<source src="https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/1080/Big_Buck_Bunny_1080_10s_1MB.mp4#t=0.1" type="video/mp4" />
</video>
I have chosen a fraction of second (0.1) to keep number of frames small, because I have the suspect that if you put 1 second, it would "preload" the first 1 second of video (i.e. 24 frames or more ....). Just in case ...
Works fine on Chrome and Firefox on desktop :)
Works not on Android mobile, though :(
I did not test on iOS, iPhone, IE yet ??
Edit May 2021:
I realized that many modern browsers now show automatically a poster of first frame.
Seems like they heard us :-)
To make it simple you can just add preload="metadata" to your video tag and the second of the first frame #t=0.5 to your video source:
<video width="400" controls="controls" preload="metadata">
<source src="https://www.w3schools.com/html/mov_bbb.mp4#t=0.5" type="video/mp4">
</video>
Best of luck!
There is a Popcorn.js plugin called Popcorn.capture which will allow you to create posters from any frame of your HTML5 video.
There is a limitation that is imposed by the browser that prohibits reading pixel data of resources requested across domains (using the canvas API to record the current value of a frame). The source video must be hosted on the same domain as the script and html page that is requesting it for this approach to work.
The code to create poster using this plugin is quite simple:
// This block of code must be run _after_ the DOM is ready
// This will capture the frame at the 10th second and create a poster
var video = Popcorn( "#video-id" );
// Once the video has loaded into memory, we can capture the poster
video.listen( "canplayall", function() {
this.currentTime( 10 ).capture();
});
I recently did this for a recent project that works on desktop and mobile. The trick was getting it to work on iPhone.
Setting preload=metadata works on desktop and android devices but not iPhone.
For iPhones I had to set it to autoplay so the poster image automatically appears on initial load. iPhones will prevent the video from auto playing, but the poster image appears as the result.
I had to do a check for iPhone using Pavan's answer found here. Detect iPhone Browser. Then use the proper video tag with or without autoplay depending on the device.
var agent = navigator.userAgent;
var isIphone = ((agent.indexOf('iPhone') != -1) || (agent.indexOf('iPod') != -1)) ;
$videoTag = "";
if(isIphone()) {
$videoTag = '<video controls autoplay preload="metadata">';
} else {
$videoTag = '<video controls preload="metadata">';
}
You can set preload='auto' on the video element to load the first frame of the video automatically.
Solution for #2, #3 etc. frames. We need attach disposable handler .one() for resetting default frame.
<video width="300" height="150" id='my-video'>
<source src="testvideo.mp4#t=2" type="video/mp4" />
</video>
$(function () {
let videoJs = videojs('my-video');
videoJs.one('play', function () {
this.currentTime(0);
});
});
I found a great way to dynamically add poster to a video!
To show the desired frame from video (in my case it's the frame at 1.75 seconds) - add preload="metadata" to the video element and #t=1.75 to the end of source URL.
Add eventListener to the video element that will listen for play event only once.
Once the event is emitted reset the video time.
<video width="100%" controls="controls" preload="metadata" id="myVid">
<source src="path/to/your/video#t=1.75" type="video/mp4">
</video>
<script>
var el = document.getElementById('myVid');
el.addEventListener('play', () => {
el.currentTime = 0;
}, { once: true });
</script>

HTML audio Element how to replay?

I setup a HTML5 page, that include a node.
The page will to playing a music(mp3 format),but it just play sound to end, and I use javascript to control audio element,even so,I can't replay it and only STOP.
Does HTML5 audio Element support REPLAY? And how to?
please read this
http://www.position-absolute.com/articles/introduction-to-the-html5-audio-tag-javascript-manipulation/
and for replay event
you can set option, on replay click
audioElement.currentTime=0;
audioElement.play();
The suggestions above did not worked for me or where not applicable. I needed to replay sound when my code needed to do it.
The following code worked (at least chrome):
audioElement.setAttribute('src', audioSrc);
audioElement.play();
in other words, setting the src attribute again, then play() did the job
If the server hosting the video does not support seeking on client (HTTP RangeRequest), the command
audioElement.currentTime=0;
from #JapanPro's answer is silently ignored in Chromium. This behavior is filled as crbug #121765.
There is a handy guide on MDN how to configure your server to play nice. But if you cannot, I had success with doing
audioElement.load();
which unsurprisingly reloads the audio source and seeks to the start as a side effect. Not nice, but it is quite intuitive and it works.
source: http://www.whatwg.org/specs/web-apps/current-work/#loading-the-media-resource
Use:
audio.pause() // important!!!
audio.currentTime = 0
audio.play()
The html5 audio element has a loop attribute set it to loop=loop
http://www.w3schools.com/html5/html5_audio.asp
don't use node.load() this is way too slow for slow devices.
To stop, you should just use:
node.currentTime = 0
To replay you can do:
node.currentTime = 0
node.play()
You can try this:
<audio id="audiotag1" src="audio/flute_c_long_01.wav" preload="auto"></audio>
Play 5-sec sound on single channel
<script type="text/javascript">
function play_single_sound() {
document.getElementById('audiotag1').play();
}
</script>
Ref: http://www.storiesinflight.com/html5/audio.html
In HTML5 you can just set audioElement.loop='true';

html5 video playing twice (audio doubled) with JQuery .append()

Huge WTF that I thought was a bug hidden in the semicomplex web app that I'm making, but I have pared it down to the simplest code possible, and it is still replicable in Firefox, Chrome, and Safari, unpredictably but more than 1/2 of the time.
http://jsfiddle.net/cDpV9/7/
var v = $("<video id='v' src='http://ia600401.us.archive.org/18/items/ForrestPlaysTaik/forresto-plays-taik-piano-360.webm' autobuffer='auto' preload autoplay controls></video>");
$("#player").append(v);
Add a video element.
Video starts to load and play.
Video audio sounds like it is doubled.
Pause the visible video, and one audio track continues.
Delete the video element; the ghost audio keeps playing.
Delete the frame, and the ghost audio stops (though once in Firefox it continued to play after closing the window, and didn't stop until quitting Firefox).
Here is a screen capture to maybe show that I'm not completely crazy: http://www.youtube.com/watch?v=hLYrakKagRY
It doesn't seem to happen when making the element with .html() instead of .append(), so that's my only clue: http://jsfiddle.net/cDpV9/6/
$("#player").html("<video id='v' src='http://ia600401.us.archive.org/18/items/ForrestPlaysTaik/forresto-plays-taik-piano-360.webm' autobuffer='auto' preload autoplay controls></video>");
I'm on OS X 10.6.7.
I think that I have it. Even just creating the JQuery object without adding it to the page causes the ghost player to play: http://jsfiddle.net/cDpV9/8/
var v = $("<video id='v' src='http://ia600401.us.archive.org/18/items/ForrestPlaysTaik/forresto-plays-taik-banjo-360.webm' autobuffer='auto' preload autoplay controls></video>");
For now I can work around this by using .html(). I'll report the issue to JQuery.
Maybe jQuery caches the content of $() before appending it to your player div? So there is another instance of the video tag. It could be an error in jQuery. Have you tried this without Jquery/js?
I would try adding the autoplay attribute after you append the video player. This should then instantiate the play function.
That would be something like this:
var v = $("<video id='v' src='videofile.webm' autobuffer='auto' preload controls></video>");
$("#player").append(v);
v.attr('autoplay','autoplay');
When you create elements in JavaScript i.e. image elements, objects etc, they are loaded instantly and stored in memory as objects. That is why you can preload images before you load a page. It is therefore not a jQuery bug.
Ref: http://www.w3.org/TR/html5/video.html#attr-media-autoplay
When present, the user agent (as described in the algorithm described
herein) will automatically begin playback of the media resource as
soon as it can do so without stopping.
I've got the same problem over here. This seems to be an issue with using the "autoplay" attribute on your video markup.
Remove the autoplay attribute
append your video DOMNode to any node
if you want autoplay behavior, call videodomnode.play() - using jquery this would be $('video')[0].play()
You could get the html of #player and append the video your self, then add the total with .html() like this:
var v = $("#player").html() + "<video id='v' src='http://ia600401.us.archive.org/18/items/ForrestPlaysTaik/forresto-plays-taik-piano-360.webm' autobuffer='auto' preload autoplay controls></video>";
$("#player").html(v);
It's not as good as the .append() function, but if the .append() doesn't work, you might be forced to do something like this.
This one worked best in my case:
var v = '<audio hidden name="media"><source src="text.mp3"><\/audio>';
$('#player').append(v);
$("audio")[$('audio').size()-1].play();
I solved mine by loading video after dom loaded:
$(window).bind("load", function() {
var v = $("<video id='bgvid' loop muted>
<source src='/blabla.mp4' type='video/mp4'>
</source>
</video>");
$(".video-container").append(v);
v.attr('autoplay','autoplay');
});

Categories

Resources