var ytplayer = document.getElementById("movie_player");
ytplayer.addEventListener('onStateChange', 'onPlayerChange');
function onPlayerChange(newState) {
alert('do something at least...');
if(newState == 0) {
alert('movie has stopped');
}
}
This is how I try to listen to YouTube events with a Google Chrome extension. It doesn't give me any error at all, even though it should when the movie has finished. Or at least when the state has changed. Does anyone know what is wrong?
Console doesn't give me any errors.
Your code works fine on Firefox because the player is Flash. However Chrome supports HTML5 and the player is HTML5 Video Player. So there is no element which has "movie_player" id. Are you sure your video player is Flash on Chrome. Right click the video and see player info in context menu. More details about YouTube HTML5 Player.
Youtube HTML5 player is currently in trial, so you should detect user's player mode and add a fallback for it at least YT completely use HTML5.
The HTML5 video element fires its own events. Right now, it looks like the easiest way to get at it is by class name (since it doesn’t have an id):
var videoElement = document.getElementsByClassName('video-stream')[0];
Video elements fire a bunch of events, which you can find listed here in the HTML5 spec.
For example:
videoElement.addEventListener('pause', function(){ alert('paused!'); })
Related
As most web developers are aware, there’s an annoying lack of support for the full screen api in Safari on iOS. However most popular video sites such as YouTube and Vimeo have a way of faking it by allowing the user to toggle between playing the video inline (with the playsinline attribute I assume) and playing the video in the native iOS player (like when videos don’t use playsinline). I made a simple script that I thought would do this, but it doesn’t work reliably and I’m sure there’s a better way to implement it. It goes like this:
var video = document.getElementById('video');
function toggleFullScreen() {
video.pause();
video.hasAttribute('playsinline') ? video.removeAttribute('playsinline') : video.setAttribute('playsinline', '');
video.play();
}
My question is: does anyone know how these sites do it? And is there a better way than toggling playsinline?
I have just created video object on fly , then add 2 attributes such as source and muted before appending the video object in the document and finally use method play() to play the added video as illustrated below.
let v = document.createElement("video");
v.setAttribute("src","videoplayback.mp4");
v.setAttribute("muted","muted");
document.body.appendChild(v);
v.play().catch((e)=>{ console.log(e)}); // it returns DomException why?
So can someone can tell me What is wrong or solve this for me .
NB :one image of the video is displayed but it is not running..
by default, not just in Chrome but also in Mozilla Firefox and other browsers the video autoplay command is being denied if the Video contains audio and is not muted.
The only way around it is a javascript forced autoplay with audio.
However if you set the video tag to muted="muted" and autoplay the video will still autoplay even if you have set your browser to not to autoplay videos onload.
It's a new feature that has been added to Google Chrome - media (e.g. videos and sounds) cannot be played before the user interacts actively with the page (click). Just add a created variable, put all your code inside a click handler, and create the video if created is false, and set created to true:
let created = false;
$(document).on("click", () => {
if (!created) {
created = true;
let v = document.createElement("video");
v.setAttribute("src","videoplayback.mp4");
v.setAttribute("muted","muted");
document.body.appendChild(v);
v.play().catch((e)=>{ console.log(e)});
}
});
This may seem obvious, however, make sure you don't have an extension installed that is preventing the video from playing. In my case, a site I recently completed has been working fine. I went back to take a look at the site and got this error message: VM476:96 Uncaught (in promise) DOMException: The play method is not allowed by the user agent.
Within a few minutes, I realized I recently installed AutoplayStopper which of course was preventing the video from running auto play.
This is because of your browser default settings. It has set not to play any Audio or video.
Firefox:
https://support.mozilla.org/en-US/kb/block-autoplay
With the release of OSX High-Sierra*, one of the new features in Safari is that videos on websites will not auto play anymore and scripts can't start it either, just like on iOS. As a user, I like the feature, but as a developer it puts a problem before me: I have an in-browser HTML5 game that contains video. The videos do not get automatically played anymore unless the user changes their settings. This messes up the game flow.
My question is, can I somehow use the players' interaction with the game as a trigger for the video to start playing automatically, even if said activity is not directly linked to the video element?
I cannot use jQuery or other frameworks, because of a restraint that my employer has put on our development. The one exception is pixi.js which - among all other animations - we are also using to play our videos inside a pixi container.
*The same restriction also applies on Mobile Chrome.
Yes, you can bind on event that are not directly ones triggered on the video element:
btn.onclick = e => vid.play();
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>
So you can replace this button with any other splash screen requesting an user click, and you'll be granted access to play the video.
But to keep this ability, you must call at least once the video's play method inside the event handler itself.
Not working:
btn.onclick = e => {
// won't work, we're not in the event handler anymore
setTimeout(()=> vid.play().catch(console.error), 5000);
}
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>
Proper fix:
btn.onclick = e => {
vid.play().then(()=>vid.pause()); // grants full access to the video
setTimeout(()=> vid.play().catch(console.error), 5000);
}
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>
Ps: here is the list of trusted events as defined by the specs, I'm not sure if Safari limits itself to these, nor if it includes all of these.
Important note regarding Chrome and preparing multiple MediaElements
Chrome has a long-standing bug caused by the maximum simultaneous requests per host which does affect MediaElement playing in the page, limiting their number to 6.
This means that you can not use the method above to prepare more than 6 different MediaElements in your page.
At least two workarounds exist though:
It seems that once a MediaElement has been marked as user-approved, it will keep this state, even though you change its src. So you could prepare a maximum of MediaElements and then change their src when needed.
The Web Audio API, while also concerned by this user-gesture requirement can play any number of audio sources once allowed. So, thanks to the decodeAudioData() method, one could load all their audio resources as AudioBuffers, and even audio resources from videos medias, which images stream could just be displayed in a muted <video> element in parallel of the AudioBuffer.
In my case i was combining transparent video (with audio) with GSAP animation. The solution from Kaiido works perfectly!
First, on user interaction, start and pause the video:
videoPlayer.play().then(() => videoPlayer.pause());
After that you can play it whenever you want. Like this:
const tl = gsap.timeline();
tl.from('.element', {scale: 0, duration: 5);
tl.add(() => videoPlayer.play());
Video will play after the scale animation :).
Tested in Chrome, Safari on iPhone
When I hide a YouTube video, it stops playing. However, this is not the case for Vimeo videos. Is there another way to stop a Vimeo video?
First, add an ID to your iFrame. Then add this to your javascript close window click function:
var $frame = $('iframe#yourIframeId');
// saves the current iframe source
var vidsrc = $frame.attr('src');
// sets the source to nothing, stopping the video
$frame.attr('src','');
// sets it back to the correct link so that it reloads immediately on the next window open
$frame.attr('src', vidsrc);
I recently needed to pause a Vimeo video that was inside a Bootstrap modal when the modal was closed.
The Vimeo video was embedded in an iframe.
This is what worked for me:
$("#my-bootstrap-modal").on('hidden.bs.modal', function (e) {
var div = document.getElementById("my-bootstrap-modal");
var iframe = div.getElementsByTagName("iframe")[0].contentWindow;
iframe.postMessage('{"method":"pause"}', '*');
});
Vimeo has a JavaScript API that allows you to access and invoke many properties and methods on the video player (including pausing the video and also unloading it completely). They also have an API Playground and some examples on GitHub.
[Edit]
Since you mention that you use the Universal Embed Code, here are some caveats from the web site:
With the Universal Embed Code, the only way to interact with the player is by using window.postMessage. postMessage is a relatively new development, so it's oly available in the following browsers: Internet Explorer 8+, Firefox 3+, Safari 4+, Chrome, and Opera 9+.
Because of the complexities involved with postMessage, we've written a JS mini-library that does all the hard work for you! You can find it on the downloads page or you can see some examples below.
To restore the SRC attribute, use the following before clearing:
var source = $('iframe#yourVideoId').attr('src');
Next, SRC attribute clear:
$('iframe#yourVideoId').attr('src', '');
Callback previous SRC attribute:
$('iframe#yourVideoId').attr('src', source);
var vidUrl = $("iframe#video-frame").attr('src');
//Basically stops and starts the video on modal open/close
$('#video').on('hidden.bs.modal', function (e) {
$("iframe#video-frame").attr('src','');
});
$('#video').on('show.bs.modal', function (e) {
$("iframe#video-frame").attr('src', vidUrl);
})
Another answer along the lines of David's...you can use jQuery to clear the SRC attribute of the iFrame.
$('iframe#targetID').attr('src','');
I'm using this with a Vimeo video and a lightbox effect. When the lightbox is triggered again, I add the video URL back to the iFrame SRC before showing it.
Using the Vimeo JavaScript API, it can be done with:
player.unload()
https://github.com/vimeo/player.js#unload-promisevoid-error
I'm working on a site for a client and they're insistent on using HTML5's video tag as the delivery method for some of their video content. I currently have it up and running with a little help from http://videojs.com/ to handle the Internet Explorer Flash fallback.
One thing they've asked me to do is, after the videos finish playing (they're all a different length), fade them out and then fade a picture in place of the video --- think of it like a poster frame after the video.
Is this even possible? Can you get the timecode of a currently playing movie via Javascript or some other method? I know Flowplayer (http://flowplayer.org/demos/scripting/grow.html) has an onFinish function, is that the route I should take in lieu of the HTML5 video method? Does the fact that IE users will be getting a Flash player require two separate solutions?
Any input would be greatly appreciated. I'm currently using jQuery on the site, so I'd like to keep the solution in that realm if at all possible. Thanks!
You can view a complete list of events in the spec here.
For example:
$("video").bind("ended", function() {
alert("I'm done!");
});
You can bind to the event on the element like anything else in jQuery...as for your comment question, whatever element you're delivering for IE, yes, it would need a separate handler rigged up to whatever event it provides.
For the other question about timecode, the timeupdate event occurs when it's playing, and the durationchange event occurs when the overall duration changes. You can bind to and use them just like I showed with the ended event above. With timeupdate you'll probably want the currentTime property, with durationchange you'll want the duration property, each of which you get directly off the DOM object, like this:
$("video").bind("durationchange", function() {
alert("Current duration is: " + this.duration);
});
There is an OnEnded event associated with the video tag. However, it does not work for me in the current version of Google Chrome.
HTML 5 Video OnEnded Event not Firing
and see also
Detect when an HTML5 video finishes
For a general-purpose solution (supports video tag with fallback see)
http://camendesign.com/code/video_for_everybody
or
http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library or http://www.mediafront.org/
I used this code. It basically reloads the video which will get the poster to show again. Assuming you want the image at the end to be the same as the poster. I only have one video on the page so using the video tag works. I have my video set to autoplay on page load so I added the pause after the reload.
<script type="text/javascript">
var video= $('video')[0];
var videoJ= $('video');
videoJ.on('ended',function(){
video.load();
video.pause();
});
</script>