HTML5 Video - Pause when get to middle of video - javascript

Aim: video clip is in 2 parts: first half of content is the playing forwards, the second half is the first half in reverse. The video plays when mouseover and will then pause at the halfway stage. On mouseout #1 if paused at the halfway stage it unpauses and plays to end: #2 if you mouseout for before it pauses it will jump to the corresponding timestamp in the 2nd half and play - eg if 10sec video and you mouse at 3sec mark it will jump to 7sec and play from there to the end. See Fiddle for a rough example:
https://jsfiddle.net/cucocreative/1n3Lyqd5/422/
or see this site for what we are trying toreplicate:
https://www.polestar.com/uk/polestar-2/ (first section under hero banner)
Fiddle has latest version of code (not below).
var myVideo=document.getElementById("video");
var halfway=0;
document.getElementById("halfway").innerHTML=halfway;
function Rewind() {
var duration = video.duration;
var currentTime = video.currentTime;
var jumpto = duration - currentTime;
var pause = duration/2;
document.getElementById("jumpto").innerHTML=jumpto;
myVideo.currentTime = jumpto;
myVideo.play();
}
function Play() {
if (myVideo.paused)
var duration = video.duration;
var pause = duration/2;
document.getElementById("pause").innerHTML=pause;
myVideo.play();
this.on('timeupdate', function () {
console.log(this.currentTime());
});
}
$("#video").on(
"timeupdate",
function(event){
var duration = video.duration;
var pause = duration/2;
onTrackedVideoFrame(this.currentTime, this.duration);
// Pause when hit the halfway stage
// check to see if halfway yet
// can't get the below to play nice with the rewind function
if(this.currentTime >= pause) {
//this.pause();
//var halfway = 1;
//document.getElementById("halfway").innerHTML=halfway;
}
});
function onTrackedVideoFrame(currentTime, duration){
$("#current").text(currentTime); //Change #current to currentTime
$("#duration").text(duration)
}
After a lot of deadends, I have figured out the rewind effect and can get it to pause at the halfway stage BUT when both blocks of code are together they don't play nice together so have commented out the pause code for the time being (see lines 36-40).
I can't figure out the logic to get the Rewind function to know if the video has gotten as far as being paused yet.
So currently, as long as you mouseout before the 2sec mark it works, after that's I need help with.
update: I did think that putting an if statement at line 12 to check if the currentTime is >= than the Duration would work but it's not.
if(this.currentTime >= pause) {
myVideo.currentTime = pause;
} else {
myVideo.currentTime = jumpto;
}

I managed to get a rough solution working, it probably needs a little fine tuning tho.
HTML
<div style="text-align:center" onmouseenter="Play()" onmouseleave="Rewind()">
<video
id="video"
onended="onVideoEnd()"
class="video"
width="480">
<source src="https://www.cucostaging.co.uk/side-reversed.mp4" type="video/mp4" />
Your browser does not support HTML5 video.
</video>
</div>
Script
//var myVideo=document.getElementById("video");
const myVideo = document.getElementById('video')
var status = 'STOP' // STOP | PLAY | REWIND
function Rewind() {
var currentTime = myVideo.currentTime;
var duration = myVideo.duration;
myVideo.currentTime = duration - currentTime;
status = 'REWIND'
myVideo.play();
}
function Play() {
var currentTime = myVideo.currentTime;
var duration = myVideo.duration;
let tempCurrent = status === 'STOP' ? 0 : duration - currentTime;
myVideo.currentTime = tempCurrent;
status = 'PLAY'
myVideo.play();
setTimeout(() => {
if(status === 'PLAY')
myVideo.pause()},
(2 - tempCurrent) * 1000)
}
function onVideoEnd() {
status = 'STOP'
}

Related

How to enable proper scrolling after scrub effect in a webpage using javascript?

I found a code from codepen to use it for scrub effect in video. After the video has ended I want to enable complete scrolling. How can I acheive that? Thanks in advance!
var frameNumber = 0, // start video at frame 0
// lower numbers = faster playback
playbackConst = 500,
// get page height from video duration
setHeight = document.getElementById("set-height"),
// select video element
vid = document.getElementById('v0');
// var vid = $('#v0')[0]; // jquery option
// dynamically set the page height according to video length
vid.addEventListener('loadedmetadata', function() {
setHeight.style.height = Math.floor(vid.duration) * playbackConst + "px";
});
// Use requestAnimationFrame for smooth playback
function scrollPlay(){
var frameNumber = window.pageYOffset/playbackConst;
vid.currentTime = frameNumber;
window.requestAnimationFrame(scrollPlay);
}
window.requestAnimationFrame(scrollPlay);

Screensaver loads image in radom location after inactivity, restarts if user does anything

I have the following two pieces of code (awful but I have no idea what I'm doing):
var stage = new createjs.Stage("canvas");
createjs.Ticker.on("tick", tick);
// Simple loading for demo purposes.
var image = document.createElement("img");
image.src = "http://dossierindustries.co/wp-content/uploads/2017/07/DossierIndustries_Cactus-e1499205396119.png";
var _obstacle = new createjs.Bitmap(image);
setInterval(clone, 1000);
function clone() {
var bmp = _obstacle.clone();
bmp.x= Math.floor((Math.random() * 1920) + 1);
bmp.y = Math.floor((Math.random() * 1080) + 1);
stage.addChild(bmp);
}
function tick(event) {
stage.update(event);
}
<script>
$j=jQuery.noConflict();
jQuery(document).ready(function($){
var interval = 1;
setInterval(function(){
if(interval == 3){
$('canvas').show();
interval = 1;
}
interval = interval+1;
console.log(interval);
},1000);
$(document).bind('mousemove keypress', function() {
$('canvas').hide();
interval = 1;
});
});
<script src="https://code.createjs.com/easeljs-0.8.2.min.js"></script>
<canvas id="canvas" width="1920" height="1080"></canvas>
Basically what I'm hoping to achieve is that when a user is inactive for x amount of time the full page (no matter on size) slowly fills with the repeated image. When anything happens they all clear and it begins again after the set amount of inactivity.
The code above relies on an external resource which I'd like to avoid and needs to work on Wordpress.
Site is viewable at dossierindustries.co
Rather than interpret your code, I made a quick demo showing how I might approach this.
The big difference is that drawing new images over time is going to add up (they have to get rendered every frame), so this approach uses a cached container with one child, and each tick it just adds more to the cache (similar to the "updateCache" demo in GitHub.
Here is the fiddle.
http://jsfiddle.net/dcs5zebm/
Key pieces:
// Move the contents each tick, and update the cache
shape.x = Math.random() * stage.canvas.width;
shape.y = Math.random() * stage.canvas.height;
container.updateCache("source-over");
// Only do it when idle
function tick(event) {
if (idle) { addImage(); }
stage.update(event);
}
// Use a timeout to determine when idle. Clear it when the mouse moves.
var idle = false;
document.body.addEventListener("mousemove", resetIdle);
function resetIdle() {
clearTimeout(this.timeout);
container.visible = false;
idle = false;
this.timeout = setTimeout(goIdle, TIMEOUT);
}
resetIdle();
function goIdle() {
idle = true;
container.cache(0, 0, stage.canvas.width, stage.canvas.height);
container.visible = true;
}
Caching the container means this runs the same speed forever (no overhead), but you still have control over the rest of the stage (instead of just turning off auto-clear). If you have more complicated requirements, you can get fancier -- but this basically does what you want I think.

HTML progress bar click and update

I've added a progress bar in my javascript code, to show the progress of a music track.
audioElement.addEventListener("timeupdate", function(){
var progress = document.getElementById("progress");
var value = 0;
if (audioElement.currentTime > 0) {
value = Math.floor((100 / audioElement.duration) * audioElement.currentTime);
}
progress.style.width = value + "%";}, false);
The code works fine, and I can see that my bar progresses as the music progresses as well.
Now I would like to be able to click anywhere on the progressbar, and be able to forward the music accordingly. In other words, I would like to be able to control the rewind/forward the track by clicking on the progress bar itself.
Could someone help me, and gave me some idea how to do this.
I am not an expert with HTML and JavaScripting, so I would appreciate some help.
Thanks,
--Rudy
I would do it like this, using jQuery to make things slightly easier:
http://jsfiddle.net/LQqGS/3/
$('.clickable').bind('click', function (ev) {
var $div = $(ev.target);
var $display = $div.find('.display');
var offset = $div.offset();
var x = ev.clientX - offset.left;
$('.progress').width(x);
});
<div class='clickable'>
<div class='display'>
<div class="progress"></div>
</div>
</div>
You can then use that x coordinate to manipulate your music player as a percentage of the div width.
I came across this question today while creating a custom HTML5 video player. Just in regards to video instead of audio. The process should work the same though for your audio needs.
I found this article and was able to incorporate the progress bar part of it into my player. https://msdn.microsoft.com/en-us/library/ie/gg589528%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
Instead of using a progressbar element, like I was doing, the method I used here is to use a canvas element instead.
<canvas id='progress-bar' width="200" height="20" style="border:1px solid green;">canvas not supported</canvas>
Then in your JavaScript, create a handle to reference it by
var mediaPlayer;
var progressBar;
var canvas;
When the document loads, initialize everything including the progress bar items
mediaPlayer = document.getElementById('media-video');
progressBar = document.getElementById('progress-bar');
canvas = document.getElementById('progress-bar');
canvas.addEventListener("click", function(e) {
var canvas = document.getElementById('progress-bar');
if (!e) {
e = window.event;
} //get the latest windows event if it isn't set
try {
//calculate the current time based on position of mouse cursor in canvas box
mediaPlayer.currentTime = mediaPlayer.duration * (e.offsetX / canvas.clientWidth);
}
catch (err) {
// Fail silently but show in F12 developer tools console
if (window.console && console.error("Error:" + err));
}
}, true);
mediaPlayer.addEventListener('timeupdate', updateProgressBar, false);
Then create a function outside of your initialization function for the timeupdate listener to call and automatically update the progress bar for you
function updateProgressBar() {
mediaPlayer = document.getElementById('media-video');
//get current time in seconds
var elapsedTime = Math.round(mediaPlayer.currentTime);
//update the progress bar
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
//clear canvas before painting
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
ctx.fillStyle = "rgb(255,0,0)";
var fWidth = (elapsedTime / mediaPlayer.duration) * (canvas.clientWidth);
if (fWidth > 0) {
ctx.fillRect(0, 0, fWidth, canvas.clientHeight);
}
}
}
I haven't completely cleaned it up yet. Hence the redundant handles to the same id. But I'm sure you get the picture.

Capture frames from video with HTML5 and JavaScript

I want to capture a frame from video every 5 seconds.
This is my JavaScript code:
video.addEventListener('loadeddata', function() {
var duration = video.duration;
var i = 0;
var interval = setInterval(function() {
video.currentTime = i;
generateThumbnail(i);
i = i+5;
if (i > duration) clearInterval(interval);
}, 300);
});
function generateThumbnail(i) {
//generate thumbnail URL data
var context = thecanvas.getContext('2d');
context.drawImage(video, 0, 0, 220, 150);
var dataURL = thecanvas.toDataURL();
//create img
var img = document.createElement('img');
img.setAttribute('src', dataURL);
//append img in container div
document.getElementById('thumbnailContainer').appendChild(img);
}
The problem I have is the 1st two images generated are the same and the duration-5 second image is not generated. I found out that the thumbnail is generated before the video frame of the specific time is displayed in < video> tag.
For example, when video.currentTime = 5, image of frame 0s is generated. Then the video frame jump to time 5s. So when video.currentTime = 10, image of frame 5s is generated.
Cause
The problem is that seeking video (by setting it's currentTime) is asynchronous.
You need to listen to the seeked event or else it will risk take the actual current frame which is likely your old value.
As it is asynchronous you must not use the setInterval() as it is asynchronous too and you will not be able to properly synchronize when the next frame is seeked to. There is no need to use setInterval() as we will utilize the seeked event instead which will keep everything is sync.
Solution
By re-writing the code a little you can use the seeked event to go through the video to capture the correct frame as this event ensures us that we are actually at the frame we requested by setting the currentTime property.
Example
// global or parent scope of handlers
var video = document.getElementById("video"); // added for clarity: this is needed
var i = 0;
video.addEventListener('loadeddata', function() {
this.currentTime = i;
});
Add this event handler to the party:
video.addEventListener('seeked', function() {
// now video has seeked and current frames will show
// at the time as we expect
generateThumbnail(i);
// when frame is captured, increase here by 5 seconds
i += 5;
// if we are not past end, seek to next interval
if (i <= this.duration) {
// this will trigger another seeked event
this.currentTime = i;
}
else {
// Done!, next action
}
});
If you'd like to extract all frames from a video, see this answer. The example below assumes that you want to extract a frame every 5 seconds, as OP requested.
This answer requires WebCodecs which is supported in Chrome and Edge as of writing.
<canvas id="canvasEl"></canvas>
<script type="module">
import getVideoFrames from "https://deno.land/x/get_video_frames#v0.0.8/mod.js"
let ctx = canvasEl.getContext("2d");
// `getVideoFrames` requires a video URL as input.
// If you have a file/blob instead of a videoUrl, turn it into a URL like this:
let videoUrl = URL.createObjectURL(fileOrBlob);
const saveFrameEverySeconds = 5;
let elapsedSinceLastSavedFrame = 0;
await getVideoFrames({
videoUrl,
onFrame(frame) { // `frame` is a VideoFrame object:
elapsedSinceLastSavedFrame += frame.duration / 1e6; // frame.duration is in microseconds, so we convert to seconds
if(elapsedSinceLastSavedFrame > saveFrameEverySeconds) {
ctx.drawImage(frame, 0, 0, canvasEl.width, canvasEl.height);
elapsedSinceLastSavedFrame = 0;
}
frame.close();
},
onConfig(config) {
canvasEl.width = config.codedWidth;
canvasEl.height = config.codedHeight;
},
});
URL.revokeObjectURL(fileOrBlob); // revoke URL to prevent memory leak
</script>
Demo: https://jsbin.com/qovapeziqi/edit?html,output
Github: https://github.com/josephrocca/getVideoFrames.js

progress bar for playing videos

I'm trying to add a progress bar that shows how far a videos into it's duration, but one that can be placed outside the video itself(like on another part of the screen). I've been looking around for some time, and have only found ones for showing the loading progress, which is what I don't need. Can anyone help me find where to find that, or supply one themselves even. just in case it's needed, here's the script for the video
var numb = $(this).index(),
videos = ['images/talking1.m4v', 'images/talking2.m4v', 'images/talking1.m4v', 'images/talking2.m4v', 'images/talking1.m4v', 'images/talking2.m4v'
],
myVideo = document.getElementById('myVid');
myVideo.src = videos[numb];
myVideo.load();
setTimeout(function(){
myVideo.play();
}, 200);
You could bind an event listener to the timeupdate event:
myVideo.addEventListener("timeupdate", function() {
// if the video is loaded and duration is known
if(!isNaN(this.duration)) {
var percent_complete = this.currentTime / this.duration;
// use percent_complete to draw a progress bar
}
});
Pick a max length for your progress bar, multiply it by percent_complete (which is between 0 and 1), and use that product as the current length of the bar.

Categories