Play Html5 video and pause at specific points in time - javascript

I have an array of points in time (seconds) like this :
var points = [1,5,7,9,23,37];
I want the video to play from 1 to 5 and then pause. Then some event happens (like button click) and it plays from 5 to 7 and then pauses and so on. How can I do this using js/jquery ?

Just queue up the times (currentStopTime) and check the currentTime of the video. If currentTime >= currentStopTime then pause video, set currentStopTime to next time in the array.
var points = [1,5,7,9,23,37],
index = 1,
currentStopTime = points[index];
// start video using: video.currentTime = points[0], then video.play()
// run this from a timeupdate event or per frame using requestAnimationFrame
function checkTime() {
if (video.currentTime >= currentStopTime) {
video.pause();
if (points.length > ++index) { // increase index and get next time
currentStopTime = points[index]
}
else { // or loop/next...
// done
}
}
}
Then when paused, enable an action to happen, simply call play() to start video again. If you need an accurate restart time then force that time by adding:
...
if (video.currentTime >= currentStopTime) {
video.pause();
video.currentTime = currentStopTime;
index++;
....

Related

Chrome extension simulate hover over Youtube player

I am developing a Chrome extension for Youtube and when the user clicks a button that I have created I want to simulate a mouse hover over the player, without moving the mouse. When a video is playing and the mouse is, manually, hovered over the player, the controls (play, pause etc) and the progress bar shows and this is what I am trying to accomplish, but with a button click instead of hovering.
I don't want to pause the video, only show the bottom controls and progress bar when the user clicks the button I have created.
manifest.json
//name, description, background etc
"content_scripts": [
{
"matches": ["http://www.youtube.com/*", "https://www.youtube.com/*"],
"js": ["jquery.js", "content.js"]
}
]
content.js
$('#myButton').on('click', function() {
//I have tried the following:
$('#movie_player').trigger('mouseenter')
$('#movie_player').mouseenter()
document.getElementById('movie_player').onmouseenter()
//I can play/pause the video with:
$('#movie_player').click()
}
I have also tried "mouseover" (jQuery) and "onmouseover" (javascript) and I have also tried these on several different child elements of the #movie_player without success.
When hovering manually over the player, Chrome's DevTools shows me that the #movie_player element has a class (ytp-autohide) which gets removed/added when the mouse is entering/leaving the element. However. I can't just remove this class when the user clicks my button because then the progress bar/duration time is not updated.
Any ideas?
Managed to solve it if someone is interested (with help from this extension)
$('#myButton').on('click', function() {
const ytplayer = document.querySelector('.html5-video-player')
const video = ytplayer.querySelector('video')
const progressbar = ytplayer.querySelector('.ytp-play-progress')
const loadbar = ytplayer.querySelector('.ytp-load-progress')
//show controls and progress bar
$('.html5-video-player').toggleClass('ytp-autohide')
//update red progress bar
video.addEventListener('timeupdate', updateProgressBar)
function updateProgressBar() {
progressbar.style.transform = 'scaleX('+(video.currentTime/video.duration)+')'
}
//update grey buffer progress
video.addEventListener('progress', updateBufferProgress)
function updateBufferProgress() {
loadbar.style.transform = 'scaleX('+(video.buffered.end(video.buffered.length-1)/video.duration)+')'
}
//update current time
$('.ytp-time-current').text(formatTime( video.currentTime ))
//update current time every second
const i = setInterval(function(){
$('.ytp-time-current').text(formatTime( video.currentTime ))
}, 1000)
//stop after 3 seconds
setTimeout(function() {
$('.html5-video-player').toggleClass('ytp-autohide')
clearInterval(i)
video.removeEventListener('timeupdate', updateProgressBar)
video.removeEventListener('progress', updateBufferProgress)
}, 3000)
}
function formatTime(time){
time = Math.round(time)
const minutes = Math.floor(time / 60)
let seconds = time - minutes * 60
seconds = seconds < 10 ? '0' + seconds : seconds
return minutes + ':' + seconds
}

How to approach a setInterval triggering a setInterval within the same function

I a rewards site. Users earn points when they watch videos. Users want to skip to the end of the video to quickly earn their points. Therefore, the mechanism of the video being marked as completed is managed by a JS timer.
The Problem: When a user pauses the video, the timer needs to pause. When the user clicks play again, a setInterval is used to reopen the function, where a setInterval within the existing function does the same thing, creating a huge problem...
This is the code that is set every second to update the timer...
var video_percent_count = 0;
function video_percent() {
var prize_video = document.getElementById("prize_video");
total_duration = Math.floor(prize_video.duration) + 1;
video_percent_count++;
percent = video_percent_count / total_duration;
convert_percent = (percent * 100).toFixed(2);
if(convert_percent == 100) {
clearInterval(video_percent_interval);
}
if(prize_video.paused) {
clearInterval(video_percent_interval);
}
if(prize_video.play) {
setInterval("video_percent()", 1000);
}
$(".percent_container").text(convert_percent);
}
function prize_video(count_prize) {
var back_count_prize = count_prize - 1;
$("#prize_video").get(back_count_prize).play();
video_percent_interval = setInterval("video_percent()", 1000);
}
How can I properly manage play and pause and still keep setInterval clean?

Using javascript/jQuery, wait 3 seconds for click, then proceed

I've been trying to figure out how to run an infinite loop while pausing for user click, then allow for a break out.
When the loop starts, the user is presented with an image, and must choose the identical image from one of 4 displayed. If they successfully click the match within 5 seconds, they are presented another image, and the game goes on.
If they either choose an incorrect image, or 5 seconds elapses, the game ends.
I've got all of the functionality worked out, except this pause while waiting for a click or the time to expire.
Ideally, I'd also like the time to be adjustable on each iteration. Say start at 5 seconds, then shorten the time slightly (10ms) on each loop.
I believe it must be solvable using setTimeout() or setInterval(), but just can't wrap my head around it.
Here is a minimal concept of what I'm trying to accomplish.
$('#playnow').on('click',function(){
var speed = 5000;
var speed_reduce = 10;
var game_running = true;
/* create array of images */
var imgs = ['puppy.png','kitten.png','bunny.png','goldfish.png'];
var runnow = setInterval(
function(){
//get random image from loaded theme
rand_img = imgs[Math.floor(Math.random() * imgs.length) ];
//display chosen image
$('#goal_image').html('<img src="'+theme_dir+rand_img+'" />');
// wait up to 5 seconds for user to click or time to expire
if(*clicked and matched*){
//get new random image and reset timer (less 10ms)
}
if(*time expired*){
//bail out and game ends
}
/* reduce time */
speed -= speed_reduce;
},
speed);
});
You'll want something like this I think:
var speed = 5000, // the initial time
currentimage,
timer,
gamerunning;
function newimage(){
var imgs = ['puppy.png','kitten.png','bunny.png','goldfish.png'];
currentimage=Math.floor(Math.random() * imgs.length);
$('#goal_image').html('<img src="'+theme_dir+imgs[currentimage]+'" />');
timer = setTimeout(speed, lost)
}
function answer(id){
if(!gamerunning){return}
clearTimeout(timer)
if(id==currentimage){
speed -= 10; // time decrease every time.
newimage();
}else{
lost()
}
}
function lost(){
gamerunning=0;
speed=5000;
// what to do when lost.
}
$("#puppy").on("click",function(){answer(0)}); // here #puppy is the id of the answer image, and 0 the index in the imgs array.
$("#kitten").on("click",function(){answer(1)});
$("#bunny").on("click",function(){answer(2)});
$("#fish").on("click",function(){answer(3)});
$("#gamestartbutton").on("click",function(){gamerunning=1})
One way to solve this problem is to use setTimeout() and clearTimeout() rather than setInterval. Also, you need some event for the successful button click (I've pretended you have a special "#successfulmatch" button):
var speed = 5000;
var speed_reduce = 10;
var game_running = true;
var imgs = ['puppy.png','kitten.png','bunny.png','goldfish.png'];
var myTimeout;
function runNow(speed){
rand_img = imgs[Math.floor(Math.random() * imgs.length) ];
$('#goal_image').html('<img src="'+theme_dir+rand_img+'" />');
// Keep track of the timeout so we can cancel it later if the user clicks fast enough.
myTimeout = window.setTimeout(function(){
game_running = false;
gameEnds();
},speed);
}
$('#successfulmatch').on('click',function(){
if(game_running){
// Cancel the timeout because the user was fast enough
window.clearTimeout(myTimeout);
// Give the user less time than before
runNow(speed - speed_reduce);
}
else{
// Throw an error: you forgot to hide the clickable buttons when the game ended.
}
}
$('#playnow').on('click',function(){
runNow(speed);
}
Looks like you are mixing the logic for checking "has the user clicked the image? was it correct?" with the one for checking "has time expired?"
You can listen for onclick events on the images
and set a timeout event for the game over
so the user has to cancel that timer, to cancel imminent game over, by clicking on the images
if the right image is clicked the timer is reset
if not, it's game over
you can cancel a timeout event before it runs with cancelTimeout()
see W3C here for a reference.
here is a quick prototype:
$('#playnow').on('click', function() {
var speed = 5000;
var speed_reduce = 10;
var game_running = true;
/* create array of images */
var imgs = ['puppy.png', 'kitten.png', 'bunny.png', 'goldfish.png'];
// function that ends the game if it's called
function gameover() {
alert("GAME OVER");
game_running = false;
}
// in order to use clearTimeout() you must store the timer in a global variable
// setting a timeout that will end the game if it's not cleared before
window.timer = setTimeout(gameover, speed);
// function that is called whenever the user clicks on a image
function onclickimage(event) {
if (!game_running) return;
if ( /*clicked right img*/ ) {
// get random image from loaded theme
var rand_img = imgs[Math.floor(Math.random() * imgs.length)];
// display chosen image
$('#goal_image').html('<img src="' + theme_dir + rand_img + '" />');
// delete timer, user now has one more opportunity
clearTimeout(timer);
// speed is less 10ms
speed -= speed_reduce;
// launch timer again
window.gametimer = setTimeout(loop, speed);
} else { // if click did not match correct image
gameover();
}
}
});
Well, firstly, you need to clearInterval() when they either click or fail in order to stop the current interval. Then, you can restart an interval with the new speed. The interval seems to be working for.
Every 5 seconds a new picture is displayed. So, you want an onclick event for the picture that clears the interval and starts a new one. So, you may want to use setTimeout instead of setInterval since it is only a single iteration at a time.
You could use setInterval, I suppose, but there's no real benefit to it. This way also makes it relatively easy to reduce the speed each time.

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

Play an audio with corresponding sequence of images being animated w/ play & pause

I'm trying to create an animation of series of images with background audio using HTML5 and javascript maybe ajax or jquery. I'm basically trying to make an animation of a simple conversation between several people (portrayed by images) and speech through (audio).
I have an audio file (mp3/ogg) and a series of images. When I play the audio, the sequence of images will be displayed accordingly.
Here's the catch, If I pause or replay the audio, sequence of image must also stop or replay from the start.
So the sequence of images must be in sync with the audio playing.
Any ideas or concepts? Right now I have a working jPlayer with play/pause. Also can it be done with jPlayer?
Just make your decisions based on the currentTime of your audio. Example
var audio = document.querySelector('audio'),
img = document.querySelector('img'),
imgs = ['http://raptorsrepublic.com/wp-content/uploads/2012/08/meh_cat.jpg', 'http://2.bp.blogspot.com/_8tZf9lm-smo/R7hn7pNx-jI/AAAAAAAAALI/86DN7VedT_Q/s400/meh.jpg', 'http://2.bp.blogspot.com/-yWsoWNVX4jU/UAy5uJxD52I/AAAAAAAANSc/OTje6k_C5Q8/s1600/meh2.jpg'],
duration, interval, currentImg;
(function callee(ready) {
if (ready !== false) ready = true;
if (!ready) {
return audio.addEventListener('canplaythrough', callee);
}
if (!audio.playing) audio.play();
if (!duration) {
duration = audio.duration;
interval = duration / imgs.length;
}
if (isNaN(duration)) return setTimeout(callee, 1000);
var currentTime = audio.currentTime;
if (!currentImg) {
img.src = currentImg = imgs[0];
}
var currentTimeImage = imgs[Math.floor(currentTime / interval)];
if (currentTimeImage != currentImg) {
img.src = currentImg = currentTimeImage;
}
setTimeout(callee, 1000);
})(false);

Categories

Resources