I'm working on a HTML5 (for HLS videos) video player and i'm having problems to do trickplay actions (ff and rewind). the main issue is that the player doesn't seem to work with the currentTime attribute. is there any other property that i could use, don't know something like seekByTime , or SkippTo .
Any help?
this is my code (actually not working) :
function fastForward(mediaPlayer){
var a=mediaPlayer.duration;
var b=mediaPlayer.currentTime;
if(a>b){
mediaPlayer.currentTime=mediaPlayer.currentTime+10;
}
};
function rewind(mediaPlayer){
var a=mediaPlayer.duration;
var b=mediaPlayer.currentTime;
if(b>10){
mediaPlayer.currentTime=mediaPlayer.currentTime-60;
}
};
I try changing currentTime on Chrome 36, and IE 11 and run like a charm. In iOS you can also use PlaybackRate with negative values.
The code that I tested:
function changeCurrentTime(direction) {
if (direction == "-" && _video.currentTime > 5)
_video.currentTime -= 5;
else if (direction == "+" && _video.currentTime < _video.duration + 5)
_video.currentTime += 5;
}
In http://jsfiddle.net/5v2etjfg/6/ you can find my complete example.
Inspired on: https://developer.mozilla.org/en-US/Apps/Build/Audio_and_video_delivery/HTML5_playbackRate_explained
Hope this help.
Related
Since not all browsers support MPEG DASH for live video (safari), I am looking for a way to display 3 iframes based on the client. I think client sniffing is needed in this case because I want one page for all.
Is there a way to show a specific iframe based on the client (or iframe wrapped in a div).
iframe 1 - display on safari only
iframe 2 - display on IE 7 only
iframe 3 - display on all others
===========
1 will output HLS video
2 will output rtmp flash
3 will output MPEG Dash
You can use some javascript to detect the browser and then change the iframe 'src' attribute. One library is bowser: https://github.com/lancedikson/bowser
Html:
<iframe id="iframe_id"></iframe>
Javascript
const iframe = document.getElementById('iframe_id')
// do here your logic
if (bowser.msie && bowser.version == 7) {
iframe.setAttribute('src', 'ie7url');
} elseif(bowser.safari) {
iframe.setAttribute('src', 'safariurl');
} else {
iframe.setAttribute('src', 'defaulturl');
}
Following this question, you can detect the user agent:
var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
var is_explorer = navigator.userAgent.indexOf('MSIE') > -1;
var is_firefox = navigator.userAgent.indexOf('Firefox') > -1;
var is_safari = navigator.userAgent.indexOf("Safari") > -1;
var is_opera = navigator.userAgent.toLowerCase().indexOf("op") > -1;
I am using a Wordpress plugin to add timestamp links of videos that will seek the video automatically to a certain timeframe.
Javascript:
function onYouTubeIframeAPIReady(){
console.log('Confirmation of call to onYouTubeIframeAPIReady()');
var STT = {
settings: STTSettings,
media: undefined,
skipTo: undefined,
isHTML5: false,
isYoutube: true,
doHTML5Skip: function() {
STT.media.removeEventListener('canplaythrough', STT.doHTML5Skip);
STT.media.currentTime = STT.skipTo;
STT.media.play();
},
doYoutubeSkip: function() {
STT.media.seekTo(STT.skipTo);
STT.media.playVideo();
}
};
STTSkipTo = function(time) {
var audio = document.getElementsByTagName('audio'),
video = document.getElementsByTagName('video'),
iframe = document.getElementsByTagName('iframe'),
timeArray = time.split(':').reverse(),
seconds = parseInt(timeArray[0]),
minutes = timeArray.length > 1 ? parseInt(timeArray[1]) : 0,
hours = timeArray.length > 2 ? parseInt(timeArray[2]) : 0;
STT.skipTo = seconds + (minutes * 60) + (hours * 3600);
if (STT.media) {
console.log(STT.media.seekTo);
STT.doSkip();
return;
}
if ((parseInt(STT.settings.link_audio) && audio.length) ||
(parseInt(STT.settings.link_video) && video.length))
{
STT.doSkip = STT.doHTML5Skip;
if (parseInt(STT.settings.link_audio) && audio.length) {
STT.media = audio[0];
} else {
STT.media = video[0];
}
STT.media.addEventListener('canplaythrough', STT.doHTML5Skip);
STT.media.load();
STT.media.play();
return;
} else if (parseInt(STT.settings.link_youtube && iframe.length)) {
// Inspect the iframes, looking for a src with youtube in the URI
for (var i = 0; i < iframe.length; i++) {
if (iframe[i].src.search('youtube') !== -1) {
// Set up the JS interface
STT.doSkip = STT.doYoutubeSkip;
iframe[0].id = 'stt-youtube-player';
STT.media = new YT.Player('stt-youtube-player', {
events: {
onReady: STT.doYoutubeSkip
}
});
return;
}
}
}
console.log('Skip to Timestamp: No media player found!');
return;
}
}
On my localhost, the plugin works seamlessly but on my hosted website, I get the following error with the stack as follows:
Uncaught TypeError: STT.media.seekTo is not a function
I think for some reason the website is unable to load the www-widgetapi.js which is a dependency for YouTube iframe API and thus is unable to generate the required function definition. However, I did try to include the script manually in the header but it still didn't work.
If anyone knows of any other wordpress plugin, please advice.
Based from this documentation, you need to set both the two parameter of the player.seekTo(seconds:Number, allowSeekAhead:Boolean).
Seeks to a specified time in the video. If the player is paused when the function is called, it will remain paused. If the function is called from another state (playing, video cued, etc.), the player will play the video.
The seconds parameter identifies the time to which the player should advance.
The player will advance to the closest keyframe before that time unless the player has already downloaded the portion of the video to which the user is seeking.
The allowSeekAhead parameter determines whether the player will make a new request to the server if the seconds parameter specifies a time outside of the currently buffered video data.
It should be like: Player.seekTo(120, true)//120 seconds
If I write something like this:
function renderuj(){
scene.renderer.setClearColor(0xeeeeee, 1);
ob1.animation.update(0.5);
ob2.animation.update(0.5);
scene.renderer.render(scene.scene, scene.camera);
animationFram = requestAnimationFrame(renderuj);
}
the animation working in loop.
But I want to play only once and no more.
How to do that
inside the .js file where is 3D animation/object we can see this
animation" : [{"name":"test1","fps":24,"length":10
and I try add to my code something like this
if(temp < 10)
temp++;
else
cancelRequestAnimFrame(animationFram );
but I have only half of animation
Not sure what type for animation object you are using but you probably want to do something like this.
if ( obj.animation.time + delta < obj.animation.duration ) {
// running
obj.animation.update( delta );
} else {
// finished
obj.animation.update( obj.animation.duration - obj.animation.time );
}
Because IOS prevents auto-loading of video it is necessary to add a 'poster' image to indicate a play button (in this case).
However I also want to display a loading image for slow connections by swapping the poster image for a loading image when loading has started.
The problem is on normal connections the play button shows for a split second before the loading image.
So how can I show the play poster image for when it is detected that no loading is going to take place until the play button is pressed.
if ( yourVideoElement.readyState === HAVE_ENOUGH_DATA ) {
// it's loaded
}
https://developer.mozilla.org/en/DOM/HTMLMediaElement
UPDATE
Or you could use jQuery:
var videoDuration = $html5Video.prop('duration');
var updateProgressBar = function(){
if ($html5Video.prop('readyState')) {
var buffered = $html5Video.prop("buffered").end(0);
var percent = 100 * buffered / videoDuration;
//Your code here
//If finished buffering buffering quit calling it
if (buffered >= videoDuration) {
clearInterval(this.watchBuffer);
}
}
};
var watchBuffer = setInterval(updateProgressBar, 500);
You have to check two things, first the networkState and the readyState additionally you have to make sure, that either the preload attribute has a value other than 'none' or you are using an autoplay attribute. In this case you can write the following code (better to wait untill window.onload):
$(window).on('load', function(){
var myVideo = $('video');
if(myVideo.prop('readyState') < 1 && myVideo.prop('networkState') != 2){
//no automatically loading code
myVideo.prop('poster', 'noloading.jpg');
}
});
This is not tested, readyState == 0 means that there is no data and networkState 2 means it does not try to load.
With a timeout:
$(window).on('load', function(){
var myVideo = $('video');
if(myVideo.prop('readyState') < 1 && myVideo.prop('networkState') != 2){
//probably no automatically loading code
setTimeout(function(){
if(myVideo.prop('readyState') < 1 && myVideo.prop('networkState') != 2){
//no automatically loading code
myVideo.prop('poster', 'noloading.jpg');
}
}, 1000);
}
});
I'm trying to detect when a video file has completed loading. i made it work successfully on firefox and safari but on chrome, buffered event behaves strange..
so,
in my local host chrome works fine but when i upload to server;
buffer percentage stops about %50 but buffers %100,
when page refreshed, percentage stay at %0 but it continues to buffering..
here is my javascript
function loaded()
{
var v = document.getElementById('myVideo');
var r = v.buffered;
var total = v.duration;
var current=v.currentTime;
var start = r.start(0);
var end = r.end(0);
var downloadPercent= Math.round((end / total)*100)
$("#loadProgress").css('width',downloadPercent+ '%');
if(downloadPercent==100){
$("#preloaderWrapper").fadeOut(function(){
document.getElementById('myVideo').play();
clearInterval(ratoteLoad);
$(this).remove();
});
}
}
$('#myVideo').bind('progress', function()
{
loaded();
});
any idea?
thank you
try this instead:
myVideoTag = document.getElementById('video');
myVideoTag.addEventListener('progress', function(e) {
var percent = null;
// FF4+, Chrome
if (myVideoTag && myVideoTag.buffered && myVideoTag.buffered.length > 0 && myVideoTag.buffered.end && myVideoTag.duration) {
percent = myVideoTag.buffered.end(0) / myVideoTag.duration;
}
// Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end()
// to be anything other than 0. If the byte count is available we use this instead.
// Browsers that support the else if do not seem to have the bufferedBytes value and
// should skip to there. Tested in Safari 5, Webkit head, FF3.6, Chrome 6, IE 7/8.
else if (myVideoTag && myVideoTag.bytesTotal != undefined && myVideoTag.bytesTotal > 0 && myVideoTag.bufferedBytes != undefined) {
percent = myVideoTag.bufferedBytes / myVideoTag.bytesTotal;
}
if (percent !== null) {
percent = 100 * Math.min(1, Math.max(0, percent));
// ... do something with var percent here (e.g. update the progress bar)
}
}, false);
... comments copied from mediaelement.js, code as well but adjusted for easier display here. I omitted the code for Firefox 3.0 as it's less than relevant.
working fine in all current browsers
PS: thx to John Dyer for mejs - great stuff ;)