seek to a point in html5 video - javascript

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.

Related

how to detect if MUX video embedded in WordPress is streaming or playback of a fixed length video?

I've searched here and found some very old answers but I think this question has not been answered. I'm using the MediaCloud plugin in Wordpress to display videos. When I create a page, I can use a short tag to display a video by including this in my HTML markup:
<div id="my_video">
[mux_video id='2926' autoplay='false' loop='false' muted='false' controls='true' inline='false' preload='metadata']
</div>
Wordpress will query an internal db for media id=2926 and ends up rendering this HTML markup to display the video (url changed for privacy):
<div id="my_video">
<figure>
<video class='mux-player video-js' width=1920 height=1080 poster='https://www.example.com/wp-content/uploads/2021/08/2926--thumb.jpg' controls preload='metadata'>
<source src='https://stream.mux.com/<-LONG-ENCODED-ID-HERE>.m3u8' type='application/x-mpegURL' />
</video>
</figure>
</div>
My configuration of MediaCloud uses videojs to display the video but I've been unable to locate any useful function in the docs which can tell me if the video in question is a livestream or some previously broadcast live stream or uploaded video with a fixed duration (presumably progressive download?). It seems clear that the JS running in the page can tell the difference because a livestream clearly has the LIVE indicator visible and the timeline indicator/scrubber removed whereas an old video will have the timeline indicator/scrubber and displays the fixed length of the video.
I thought at first that I might sniff for the Program Data Time (PDT) and this might be absent for pre-recorded content, but MUX also provides PDT for old livestreams. This code will output the PDT for the currently running video but cannot be used to distinguish livestream from old videos:
const video1 = document.querySelector("#my_video video");
let player1 = videojs(video1);
window.player1 = player1;
player1.on('loadeddata', () => {
let metadataTrack = Array.prototype.find.call(player1.textTracks(), track => track.label === 'segment-metadata');
metadataTrack.on('cuechange', () => {
let pdt = metadataTrack.activeCues[0].value.dateTimeString;
document.getElementById('pdt_1').innerHTML = pdt;
});
});
I also tried checking for the video's duration to see if that might help me distinguish -- was thinking a livestream might have some empty value for duration but that's not the case. So far, it always shows me some positive integer value when I do this:
video1.addEventListener('loadedmetadata', (event) => {
// duration and dimensions of video are now known
let dur = Math.round(video1.duration);
console.log(dur)
});
Is there some simple JS that I can use to return a true/false value indicating whether the video in question is a livestream or whether it's an old video of fixed duration? Someone suggested querying the MUX API but that's not going to work for me in this case and would gum up my page load times.
player.duration() is Infinity for live streams. The live indicator checks that on durationchange events.

Playing random audio in HTML/Javascript

I am trying to figure out how to continuously play random audio sound bites, one after another without having them overlap on an HTML page using jquery. I have code that plays random sound bites on a timer, but sometimes they overlap and sometimes there is a pause in between the sounds. I had looked into ended and other EventListeners but I really have no idea what I am doing. Here is a portion my code:
<html>
<audio id="audio1">
<source src="cnn.mp3"></source>
</audio>
<audio id="audio2">
<source src="sonycrackle.mp3"></source>
</audio>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('audio').each(function(){
this.volume = 0.6;
});
var tid = setInterval(playIt, 2000);
});
function playIt() {
var n = Math.ceil(Math.random() * 2);
$("#audio"+n).trigger('play');
};
Is there a way to just continuously play these sounds bites one after another right after the previous sound plays? FWIW I have many sound bites but I am just showing two above for reference.
So I dabbled a bit, here's a full pure JavaScript solution.
Should be cross-browser, haven't tested (/lazy). Do tell me if you find bugs though
var collection=[];// final collection of sounds to play
var loadedIndex=0;// horrible way of forcing a load of audio sounds
// remap audios to a buffered collection
function init(audios) {
for(var i=0;i<audios.length;i++) {
var audio = new Audio(audios[i]);
collection.push(audio);
buffer(audio);
}
}
// did I mention it's a horrible way to buffer?
function buffer(audio) {
if(audio.readyState==4)return loaded();
setTimeout(function(){buffer(audio)},100);
}
// check if we're leady to dj this
function loaded() {
loadedIndex++;
if(collection.length==loadedIndex)playLooped();
}
// play and loop after finished
function playLooped() {
var audio=Math.floor(Math.random() * (collection.length));
audio=collection[audio];
audio.play();
setTimeout(playLooped,audio.duration*1000);
}
// the songs to be played!
init([
'http://static1.grsites.com/archive/sounds/background/background005.mp3',
'http://static1.grsites.com/archive/sounds/background/background006.mp3',
'http://static1.grsites.com/archive/sounds/background/background007.mp3'
]);
Some quick suggestions is add the attribute preload="auto" to the audio element and change the script to be $(window).onload instead of document ready. Document ready fires when html is in place but not necessarily when audio and other assets (like images) have loaded.
You could also look into using the AudioBuffer Interface in the new Web Audio API, it's described as "this interface represents a memory-resident audio asset (for one-shot sounds and other short audio clips)." which sounds like what you need. I believe part of the issues you're having (random pauses/delays/sound glitches with the audio element) are one of the reasons why it's being developed.
Read more here:
https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioBuffer
Unfortunately it's only Chrome and lastest Safari supported with Firefox support supposedly in the next 6(ish) months and no word yet on IE support.

trying to add a multi source video player with more then one video?

Im trying to make a video player work in all browsers. There is
more then one video and every time you click on demo reel it plays the
video and if you click the video 1 the other video plays. How can i
make them both work in all browsers? Here is my html and javascript
html
<video id="myVideo" controls autoplay></video>
<div>
Demo Reel</div>
video 1</div>
</div>
javascript
function changeVid1() {
var changeStuff = document.getElementById("myVideo");
changeStuff.src = "video/demoreel.mp4"
}
function changeVid2() {
var changeStuff = document.getElementById("myVideo");
changeStuff.src = "video/video1.mp4";
}
After you switch the source of the video, you need to run .load() on it to force it to load the new file. Also, you need to provide multiple formats, because there is no video codec supported by all browsers.
First, set up your sources like this:
var sources = [
{
'mp4': 'http://video-js.zencoder.com/oceans-clip.mp4',
'webm':'http://video-js.zencoder.com/oceans-clip.webm',
'ogg':'http://video-js.zencoder.com/oceans-clip.ogv'
}
// as many as you need...
];
Then, your switch function should look like this:
function switchVideo(index) {
var s = sources[index], source, i;
video.innerHTML = '';
for (i in s) {
source = document.createElement('source');
source.src = s[i];
source.setAttribute('type', 'video/' + i);
video.appendChild(source);
}
video.load();
video.play(); //optional
}
See a working demo here.
This gives the browser a list of different formats to try. It will go through each URL until it finds one it likes. Setting the "type" attribute on each source element tells the browser in advance what type of video it is so it can skip the ones it doesn't support. Otherwise, it has to hit the server to retrieve the header and figure out what kind of file it is.
This should work in Firefox going back to 3.5 as long as you provide an ogg/theora file. And it will work in iPads, because you only have one video element on the page at a time. However, auto-play won't work until after the user clicks play manually at least once.
For extra credit, you can append a flash fallback to the video element, after the source tags, for older browsers that don't support html5 video. (i.e., IE < 9 - though you'll need to use jQuery or another shim to replace addEventListener.)

HTML5 audio start over

Having
var audio = new Audio("click.ogg")
I play the click sound when needed by
audio.play()
However, sometimes user is so fast that a browser does not play the audio at all (probably when still playing a previous play request). Is this issue related to preload?
How can I force a browser to stop playing and start over? There is no stop, just pause in HTML5 audio component, correct? What workaround can be used here?
Update - Additional note:
I have multiple checkbox-like div elements with a touchend event. When such event is triggered, the elements visually change, a sound is played and an internal variable is set accordingly. If user tap on these elements slowly, everything works nicely. If tap fast, the sound is often completely skipped...
The simplest solution is to just reset the audio currentTime and ensure it's playing using the play() method. Checking if the audio is playing is not necessary as subsequent play() invocations will not do anything.
audio.currentTime = 0;
audio.play();
This is the code I've been using and it's working for me:
if(audioSupport.duration > 0 && !audioSupport.paused){
//already playing
audioSupport.pause();
audioSupport.currentTime = 0;
audioSupport.play();
}else{
//not playing
audioSupport.play();
}
I noticed that on Firefox, playing a sound again and again really fast (like a short ticking sound) will skip beats often. The best solution I got was to simply call cloneNode and play each sound that way. Its not perfect (compared to Chrome where it sounds flawless):
var audio = document.getElementById('myaudio');
setInterval(function() {
audio.cloneNode().play();
}, 100);
The only way i found how to play a short sound very quickly (so quick that the 2nd sound starts before the first ends) is to actually load 5 or 10 and if you have to play again but are already playing, just go to the next, which is not playing:
var soundEls = [];//load 10 audios instead of 1
for(var i=0;i<10;i++){
var soundEl = document.createElement('audio');
soundEl.src = url;
soundEl.preload = 'auto';
$(this._soundEl).append(soundEl);
soundEls.push(soundEl);
}
var soundElIndex = 0;
return {play:function(){
var soundEl = soundEls[soundElIndex];
if(soundEl.duration > 0 && !soundEl.paused){
//already playing, switch to next soundEl
soundElIndex++;
if(!soundEls[soundElIndex]) soundElIndex=0;
soundEls[soundElIndex].play();
}else{
//not playing
soundEl.play();
}
}};
Result of this is you can actually play the same sound over itself.
Probably not the right way to do it though.

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

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();
}

Categories

Resources