Nothing specific, E.g:
I have a video [with controls(Pause, play, forward... ) in a tag] How would you do to: when the video is in the second 30, make a div appear, then, in the second 32, make it disappear.
Thanks :)
If you're using the HTML5 <video> element you can use the ontimeupdate event to track where the playback has got to, as in this example:
// display the current and remaining times
video.addEventListener("timeupdate", function () {
// Current time
var vTime = video.currentTime;
document.getElementById("curTime").textContent = vTime.toFixed(1);
document.getElementById("vRemaining").textContent = (vLength - vTime).toFixed(1);
}, false);
Thanks to Microsoft for their reference
Here's a working example:
<!DOCTYPE html>
<html>
<head>
<title>Video demo</title>
<script>
// ontimeupdate event handler
function update(e) {
// get the video element id so that we can retrieve the current time.
el = document.getElementById('myVideo');
// set the current time in the page
document.getElementById('timer').innerHTML = el.currentTime;
// If the current time is between 10 and 15 seconds pop-up the
// second div
if (el.currentTime > 20 && el.currentTime <=25) {
document.getElementById('popup').style.display='block';
} else {
document.getElementById('popup').style.display='none';
}
}
</script>
<style>
video {width:300px;}
</style>
</head>
<body>
<video id=myVideo ontimeupdate="update()" src="http://archive.org/download/HardDriveSpinning/HardDriveWebm.webm" autoplay>Sorry - format unsupported</video>
<div id="timer"></div>
<div id="popup" style="display:none">Boo!</div>
</body>
</html>
See it at this fiddle (Works for Firefox and Chrome. IE doesn't like the WebM video format)
You could use window.setTimeout to run a function after a specified amount of time. This won't be enough by itself if the user is able to pause the video. You'd have to tell us more about how you're displaying the video in order to get a more in-depth solution.
But perhaps more importantly, you might want to go back to square one and think again about what you're really trying to accomplish. Because it seems to me that if it seems like you need to trigger DOM manipulations based on the time index of a video, there's probably a better way to do what you really want that doesn't involve that.
Related
I am coding an online psychology experiment. Participants have to watch a short movie and remember some information. To analyze the data everyone has to see the same movie, so it would be a problem if people pause it. Therefore, I disabled all controls and autoplay the video.
On Chrome this only works if the player starts mute. So I would like to turn on the sound automatically right after the video starts.
I am trying to use the following html with the video hosted here
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="user-scalable=no">
</head>
<body style="width: 1000px; height: 800px; background-color: grey;">
<div class="container">
<div id="video-player"></div>
</div>
<script src="https://muse.ai/static/js/embed-player.min.js"></script>
<script>
const player = MusePlayer({
container:'#video-player',
video: 'qhRjheS',
width: 720,
height: 480,
autoplay: true,
loop: true,
volume: 0,
style: 'no-controls',
shortcuts: false,
css: '*{pointer-events:none!important;}',
});
player.on('timeupdate', function(time) {player.setVolume(100)});
</script>
</body>
</html>
Where this line is the issue:
player.on('timeupdate', function(time) {player.setVolume(100)});
This works in the console, while the video is running, but crashes if it's put in the script.
Can anyone think of any way to turn on the sound automatically? If there is a small delay after the movie starts, that would be okay.
As an experiment (not a full solution) I'd try something like this:
setTimeout(() => player.on('timeupdate', () => player.setVolume(100)), 3000);
(I took the liberty of changing your code to use arrow functions.)
I suspect that the player isn't immediately ready to have the volume set, and takes a moment to be fully set up and ready to go. I'm not familar with MusePlayer specifically, but I'd look at the docs and see if there are other events, besides the 'timeupdate' event, that you'd want to receive first before setting up the listener for the 'timeupdate' event.
Thanks kshetline for the input. It's indeed a problem for me that chrome blocks autoplay. However, adding an event listener to start the movie on click is a workaround. I guess autostart is not possible, but this way all other controls still remain disabled once the movie starts.
document.body.addEventListener("click", function () {
player.play();
});
I am trying to get video duration in HTML5 with out playing video or before playing video to show on video thumb as you seen on you tube or any other video sites.
Any help will be really appreciate.
Thanks in Advance.
For HTML5 you should be able to use the video tag's duration property, once the file's metadata is loaded. See this answer for a good way to do it:
Retrieving HTML5 video duration separately from the file
To quote the anwser by Mikushi:
myVideoPlayer.addEventListener('loadedmetadata', function() {
console.log(videoPlayer.duration);
});
By listening for the 'loadedmetadata' event you will ensure the duration value has been loaded.
More details on the loadedmetadata can be found here: http://www.w3schools.com/tags/av_event_loadedmetadata.asp
EDIT
As per #lucas-vasques 's comment, instead of the loadmetadata event, you could use durationchange which the MDN Media Events list describes as ...
The metadata has loaded or changed, indicating a change in duration of
the media. This is sent, for example, when the media has loaded
enough that the duration is known.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
function getDuration() {
var s = document.getElementById('a');
alert(s.duration)
}
</script>
</head>
<body>
<div>
<video src="2.mp4" id="a" controls="controls"></video>
<button onclick="getDuration()">get duration</button>
</div>
</body>
</html>
There is a special event triggered on video elements called "loadedmetadata". Once this one is triggered, properties such as duration are available on the video element.
Here's an exhaustive list of all HTML5 video events : http://www.w3.org/2010/05/video/mediaevents.html
// Assume "video" is the video node
var i = setInterval(function() {
if(video.readyState > 0) {
var minutes = parseInt(video.duration / 60, 10);
var seconds = video.duration % 60;
// (Put the minutes and seconds in the display)
clearInterval(i);
}
}, 200);
What would be the best way to play multiple YouTube at once? I want them to be synced at the millisecond and therefore not to be affected by buffering issues, or advertisements of different lengths.
Update 1:
I think my question would be answered sufficiently if I would get an answer to the following question:
How can you detect using the javascript API of YouTube when the video is able to play (video has buffered sufficiently to be able to play / advertisement is not playing / video is not halted for any other reason)?
update 2:
The basic idea of YouTube syncing has been done by SwigView. The only thing missing is is for the video's to be synced more precisely at which SwigView didn't do a great job implementing.
I am starting to doubt it is even possible with the current API and I am looking at alternative approaches.
It's possible to sync two YouTube iFrame API players within a tolerance of 0.2s or better by measuring and adjusting the time difference between the two players in regular intervals. For example, the adjustment for a time difference of X milliseconds can be done pretty accurately by doubling or halving the playback speed of one player and setting it back to normal speed after X/2 milliseconds. Helpers for user interaction (stop, play, pause) can be added from the regular API repertoire. They also cover advertisements, since they pause the players.
Code to clarify:
script.js
// the players
var player1;
var player2;
// the rules
var syncThreshold=0.2; // seconds, threshold for an acceptable time difference to prevent non-stop syncing
var jumpThreshold=2; // seconds, threshold for a time difference that should be corrected by a rough jump
var jumpDeadTime=500; // milliseconds, a dead time in which we don't sync after a jump
// timeouts and intervals
var timeSyncInterval;
var syncActionTimeout=undefined;
// The YouTube API calls this once it's ready
function onYouTubeIframeAPIReady() {
player1 = new YT.Player('somediv1', {
videoId: 'zkv-_LqTeQA',
events: {
onReady: syncTime,
onStateChange: syncStateChange
}
});
player2 = new YT.Player('somediv2', {
videoId: 'zkv-_LqTeQA'
});
}
// the syncing magic
function syncTime(){
// making sure the syncing interval has not been set already for some reason
clearInterval(timeSyncInterval);
// setting a 1s interval in which we check it the players are in sync and correct in necessary
timeSyncInterval = setInterval(function () {
// if the timeout is already set, we are already trying to sync the players, so we don't have to do it again
if(syncActionTimeout==undefined){
// measure the time difference and calculate the duration of the sync-action
var time1=player1.getCurrentTime();
var time2=player2.getCurrentTime();
var timeDifference=time2-time1;
var timeDifferenceAmount=Math.abs(timeDifference);
var syncActionDuration=1000*timeDifferenceAmount/2;
if(timeDifferenceAmount>jumpThreshold){
// the players are too far apart, we have to jump
console.log("Players are "+timeDifferenceAmount+" apart, Jumping.");
player2.seekTo(player1.getCurrentTime());
// we give the player a short moment to start the playback after the jump
syncActionTimeout=setTimeout(function () {
syncActionTimeout=undefined;
},jumpDeadTime);
}else if(timeDifference>syncThreshold){
// player 2 is a bit ahead of player 1, slowing player 2 down
console.log("Player 2 is "+timeDifference+"s ahead of player 1. Syncing.");
player2.setPlaybackRate(0.5);
// setting a timeout that fires precisely when both players are sync
syncActionTimeout=setTimeout(function () {
// the players should be sync now, so we can go back to normal speed
player2.setPlaybackRate(1);
syncActionTimeout=undefined;
},syncActionDuration);
}else if(timeDifference<-syncThreshold){
console.log("Player 1 is "+(-timeDifference)+"s ahead of player 2. Syncing.");
// player 1 is bit ahead of player 2, slowing player 2 down
player2.setPlaybackRate(2);
// setting a timeout that fires precisely when both players are sync
syncActionTimeout=setTimeout(function () {
// the players should be sync now, so we can go back to normal speed
player2.setPlaybackRate(1);
// undefining the timeout to indicate that we're done syncing
syncActionTimeout=undefined;
},syncActionDuration);
}
}
},1000);
}
// a little helper to deal with the user
function syncStateChange(e){
if(e.data==YT.PlayerState.PLAYING){
player2.seekTo(player1.getCurrentTime());
player2.playVideo();
}else if(e.data==YT.PlayerState.PAUSED){
player2.seekTo(player1.getCurrentTime());
player2.pauseVideo();
}
}
index.html
<!DOCTYPE html>
<html>
<head>
<title>Sync Two Youtube Videos</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- CDN -->
<script type="text/javascript" src="//www.google.com/jsapi"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=onJSClientLoad"></script>
<script src="https://www.youtube.com/iframe_api"></script>
<!-- HOSTED -->
<script src="script.js"></script>
</head>
<body>
<div id="somediv1"></div>
<div id="somediv2"></div>
</body>
</html>
We have a video (13 minutes long) which we would like to control using HTML5. We want to be able to let our users control and select the parts of the video they want to play. Preferably this control would be through 2 input fields. They would input start time (in seconds) in first box and input duration to play (in seconds) in second box. For example, they might want to start the video 10 seconds in and play for 15 seconds. Any suggestions or guidance on the Javascript needed to do this?
Note: I have found the following:
Start HTML5 video at a particular position when loading?
But it addresses only starting at a particular time, and nothing with playing the video for a specified length of time.
You could use the timeupdate event listener.
Save the start time and duration time to variable after loadedmetadata event.
// Set video element to variable
var video = document.getElementById('player1');
var videoStartTime = 0;
var durationTime = 0;
video.addEventListener('loadedmetadata', function() {
videoStartTime = 2;
durationTime = 4;
this.currentTime = videoStartTime;
}, false);
If current time is greater than start time plus duration, pauses the video.
video.addEventListener('timeupdate', function() {
if(this.currentTime > videoStartTime + durationTime){
this.pause();
}
});
If you are able to set start time and end time of video while setting the video url.
you can specify the start and end time in the url itself like
src="future technology_n.mp4#t=20,50"
it will play from 20th second to 50th second.
There are a lot of nuances to using the javascript solution proposed by Paul Sham. A much easier course of action is to use the Media Fragment URI Spec. It will allow you to specify a small segment of a larger audio or video file to play. To use it simply alter the source for the file you are streaming and add #t=start,end where start is the start time in seconds and end is the end time in seconds.
For example:
var start = document.getElementById('startInput').value;
var end = document.getElementById('endInput').value;
document.getElementById('videoPlayer').src = 'http://www.example.com/example.ogv#t='+start+','+end;
This will update the player to start the source video at the specified time and end at the specified time. Browser support for media fragments is also pretty good so it should work in any browser that supports HTML5.
Extend to michael hanon comments:
IE returns buffered.length = 0 and seekable.length = 0. Video doesn't play. So solution:
src="video.mp4#t=10,30"
will not works in IE. If you would like to support IE only way is to use javascript to seek video just after start from 0 second.
I am trying to prevent the default scrolling within a web app which contains an HTML5 video element on Mobile Safari. Handling document.ontouchmove and calling e.preventDefault() has been the standard way that I've found to achieve this.
This seems to work everywhere except when you touch on top of the video element, where you can start pulling the page all around as if it is going to scroll. This only seems to happen when the native video controls are forced on. If you don't include the controls attribute and load the video in a way that it can be played in-line (such as on the iPad or in a UIWebView with allowsInlineMediaPlayback set), scrolling is prevented properly. So it seems like it has something to do with the native video controls (the big play button) capturing the event.
Here is a contrived example of what I am doing:
<!DOCTYPE HTML>
<html>
<head>
<title>HTML5 Video Example</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
</head>
<body style="background: blue;">
<video src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/bbb_trailer_iphone.m4v" controls></video>
<script>
window.onload = function() {
document.ontouchmove = function(e) {
e.preventDefault();
}
}
</script>
</body>
</html>
Any ideas of workarounds to completely prohibit scrolling behavior, even on the video? I've already tried handling ontouchmove directly on the video element and it doesn't work.
Thanks!
In my test, when ommiting the "controls" attribute of the video you can get the events to work. Use a custom div in top to provide custom controls
By example....
<video src="http://192.168.1.53/videoTester/Cuatro.mp4" id="player" width="100%" height="100%" x-webkit-airplay="allow" ></video>
Like you, I couldn't prevent scrolling, so as a workaround added a JS function to fire window.scrollTo(0, 1); every second which then means the user can only scroll for a certain time before the page is jumped back.
Try:
element.addEventListener('touchmove', function(event) {
// Prevent scrolling on this element
event.preventDefault();
}, false);
for just the element in question or:
window.addEventListener('touchmove', function(event) {
// Prevent scrolling on this element
event.preventDefault();
}, false);
for the whole window.
I came up with a good solution for this after running into the same issue. I got it to work by doing the following:
//Function to trigger when every half second to check if user scrolled
$(function () {
//select video player and the current time
var myPlayer = document.getElementById('VideoID');
var whereYouAt = myPlayer.currentTime;
var current;
setInterval(function () {
current = myPlayer.currentTime;
if (current > (whereYouAt + 1)) {
myPlayer.currentTime = whereYouAt; //If current 1 whole second
//Set time to before scroll.
}
else {
whereYouAt = current; //otherwise set where to current.
}
}, 500); //500 = half a second.
});
This will only work for HTML5 video and not if it triggers the mobile video player. I hope this helps and let me know if you have any questions.