Video.js remove poster when using currentTime before video starts - javascript

I have a playlist of videos, with a list of each video in a sidebar. When I click on the name of the video I want to load in the sidebar, the player switches the current video to the one I just clicked.
Some videos have sections, and those sections need to start playing at a certain time in the video. For example, I have a video with 2 sections, Section 1 starts at 0:00, but when I click on "Section 2" in the sidebar, the video should start playing at 1:30 seconds into the video.
Now I got this working with the following code, but the poster image is still playing over the video when I click on Section 2 which should start playing in the middle of the video. How can I get rid of the poster image when starting a video with currentTime offset?
(function($) {
var current, gototime;
var istime = false;
// video.js object
var $player = videojs('ppi-video');
$('a').on('click', function(e) {
e.preventDefault();
var attr = $(this).attr('data-video');
var time = $(this).attr('data-time');
if(typeof time !== 'undefined' && time !== false) {
istime = true;
gototime = time;
}else {
istime = false;
gototime = undefined;
}
// If link has data-video attribute... continue
if(typeof attr !== 'undefined' && attr !== false) {
if( current == attr ) return;
var image_path = "images/screens/";
var content_path = "source/";
// Wait till player is ready
$player.ready(function() {
// Hide the player?
$("#ppi-video_html5_api").fadeOut(400, function() {
// Change poster
$("#ppi-video_html5_api").attr('poster', image_path + attr + ".jpg");
$player.poster(image_path + attr + ".jpg");
});
$player.src([
{ type: "video/mp4", src: content_path + attr + ".mp4" },
{ type: "video/webm", src: content_path + attr + ".webm" },
]);
// Set the currently playing variable
current = attr;
$("#ppi-video_html5_api").fadeIn();
});
}
});
function updateVideo() {
if( istime ) {
$player.currentTime(gototime);
$player.ready(function() {
/**
* Trying to get rid of poster here, but not working
*/
$("#ppi-video_html5_api").attr('poster', '');
$player.poster('');
$player.play();
});
}else {
$player.currentTime(0);
}
}
// update video when metadata has loaded
$player.on('loadedmetadata', updateVideo);
})(jQuery);

I found myself in the same situation where i needed to programmatically hide the poster image. (i wanted the posterimage to hide on drag of a custom scrubbar)
I found two ways that might help someone else who is in the same situation (i know this is an old post, but i came across it looking for an answer).
First and most simply you can hide the poster image using css:
.vjs-poster.vjs-poster.vjs-poster {
display: none;
}
// specificity bumped for default css, your mileage may vary.
However because i wanted this to be done on drag event i figured i might as well just use js:
player.posterImage.hide();

It looks like on Chrome and Firefox, setting currentTime() needs to be delayed a bit. What I did was call play() and then pause() to remove the poster before the video starts. Then I set a timeout of 200 milliseconds which has a callback which then calls currentTime().
Kind of a makeshift workaround but it is working nicely.

Related

seekTo() is not a function YouTube iframe API error

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

mediaelement.js - multiple videos on one page - > end and show poster when you start another one

I have multiple videos on a site (mediaelement.js)
When i play one, all others pause and end which is fine.
But i want to show also the poster again.
How can i do it?
for now i modified the pauseOtherPlayers (function) to set the time back to 0 but i want the poster to show not only the beginning.
// FOCUS: when a video starts playing, it takes focus from other players (possibily pausing them)
media.addEventListener('play', function() {
var playerIndex;
// go through all other players
for (playerIndex in mejs.players) {
var p = mejs.players[playerIndex];
if (p.id != t.id && t.options.pauseOtherPlayers && !p.paused && !p.ended) {
p.pause();
p.setCurrentTime(0);
}
p.hasFocus = false;
}
t.hasFocus = true;
},false);
Whats the function to show the poster?
poster.show(); somehow does not work
thx
//////////////////////////////////////////////////////////////////////////////////////////
ok figured it out myself.
heres the code if anyone interested:
success: function (mediaElement, domObject) {
mediaElement.addEventListener("pause", function(e){
// Revert to the poster image when ended
var $thisMediaElement = (mediaElement.id) ? jQuery("#"+mediaElement.id) : jQuery(mediaElement);
$thisMediaElement.parents(".mejs-inner").find(".mejs-poster").show();
});
}

How to stop other sounds until one finishes (Js, HTML)

I need to include some sound files on a website, i recorded them and used the super complicated:
<a href="seo.html" onmouseover="new Audio('sounds/seo.mp3').play()">
to play them when the user scrolls over with the mouse. There are a total of four links on the website.
The problem is, when i mouse over one of them it starts playing, and then if i mouse over another it plays that one as well. If i move the mouse really fast accross the links i end up getting Giberish because all files are being played at the same time. How do i stop this ??
Ideal would be that the others CANNOT be played until the current playing is finished :)
An approch below.
Note, untested ;-)
HTML
a sound link -
a sound link -
a sound link -
a sound link
JS
var links = document.querySelectorAll('a.onmousesound');
var currentPlayedAudioInstance = null;
var onHoverPlaySound = function(element) {
if (currentPlayedAudioInstance &&
currentPlayedAudioInstance instanceof Audio) {
// is playing ?
// http://stackoverflow.com/questions/8029391/how-can-i-tell-if-an-html5-audio-element-is-playing-with-javascript
if (!currentPlayedAudioInstance.paused && !currentPlayedAudioInstance.ended && 0 < currentPlayedAudioInstance.currentTime) {
return false;
}
}
var file = element.getAttribute('data-file');
currentPlayedAudioInstance = new Audio(file);
currentPlayedAudioInstance.play();
};
for (var i = 0; i < links.length; i++) {
link.addEventListene('onmouseover', function() {
onHoverPlaySound(links[i]);
});
};

Javascript/HTML 5 Video - Detect if video is not loading

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

Videojs - how to change video poster dynamically

I want to make a playlist and the video source and poster is loaded dynamically. This is my code
var myFunc = function(){
var myPlayer = this;
var xmlhttp;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
if (xmlhttp.responseText != 'false') {
var obj = eval ("(" + xmlhttp.responseText + ")");
// update the video source
myPlayer = myPlayer.src(obj.videoFiles);
// update the video poster
obj = eval ("(" + '{"controls": true, "autoplay": false, "preload": "auto", "poster": "' + obj.posterUrl + '"}' + ")");
myPlayer = videojs("playlist", obj);
// start playback
myPlayer.play();
}
}
}
xmlhttp.open("GET",...,true);
xmlhttp.send();
};
var myPlayer = videojs("playlist");
myPlayer.on("ended", myFunc);
The videos are played well (one by one) but the posters does not show. I have tested by alert the obj.posterUrl and it is correct. Please help me.
Kind regards,
Thang
Typing in videojs('YOUR_VID_ID').poster in the console displays
function (src){
if (src === undefined) {
return this.poster_;
}
// update the internal poster variable
this.poster_ = src;
// update the tech's poster
this.techCall('setPoster', src);
// alert components that the poster has been set
this.trigger('posterchange');
}
So you should be able to do something like: myPlayer.poster( obj.posterUrl );
Note: this will only change the VideoJS poster image, not the video poster attribute.
[Original answer is not correct for any remotely recent version of Video.js]
Set the new poster with myPlayer.poster(POSTERURL), then set the new source with myPlayer.src({type: TYPE, src: VIDEOURL}). Setting the source will reset the player and show the poster.
Alternatively, use the playlist plugin: https://github.com/brightcove/videojs-playlist
Here is a really simple way to show the poster image when the video ends. This can be pretty easily modified for many use cases.
videoJS('#theVideo').on('ended', function() {
var videoposter = "poster-image-file.jpg";
$('.vjs-poster').css({
'background-image': 'url('+videoposter+')',
'display': 'block'
});
this.posterImage.show()
});
I found out about this here and wanted to share.
You'll get best results if you set the poster attribute of the encapsulated video- element directly. I loaded the new poster after the new vid in the background.
changeVideoSrc = function(url) {
var myPlayer = videojs('playerId'),
videoSrc = options.promoLocation + url,
poster = videoSrc.replace(/.mp4/, '.jpg');
myPlayer.posterImage.show();
myPlayer.src({type: "video/mp4", src: videoSrc});
myPlayer.one('canplay', function() {
$('video').attr('poster', poster);
});
};
When you call, videojs() inside the ajax function, the player has already been initialized, so the options block (obj) that you're passing in wont' do anything. You should either pass in those options when the player is first initialized, or set each property directly.
But the thing is you're also calling play() immediately after setting the new source, so the poster shouldn't ever show anyway. The poster is only meant to show until playback is started.

Categories

Resources