let's get down to the code:
I'm preparing the document with:
<video width="300" height="400" id="videoStage"></video><button onclick='video()'>Play video</button>
as for the JS function:
function video(){
var vid_url = "https://fbcdn-video-a.akamaihd.net/cfs-ak-ash4/v/82342/969/274169121921_63622.mp4?oh=99ef0d9285cbbd7adf8bc07a845dc0d1&oe=519E400F&__gda__=1369439362_83c7f900e92bdbaa201f49d35a7c144a";
stage = document.getElementById('videoStage');
stage.src = vid_url;
stage.play();
}
working code sample: http://jsbin.com/eviyel/1
this code works just fine and plays the video both on my desktop and my mobile device.
But(!) when the video() function is applied to document.ready - it only plays on my desktop and as for my mobile device it displays empty.
Any solution guys? 10x.
I found the answer myself:
Mobile browsers (such as chrome mobile and iOs's) must have a valid 'click' first to enable both video+audio playback.
Once that click as been achieved, the element that was used to play the video/audio is now playable.
You can now change the SRC of that element to play any new media source programmatically without having to click on the DOM once again.
Starting from iOS 10 autoplaying videos that are muted is allowed without user interaction:
https://webkit.org/blog/6784/new-video-policies-for-ios/
Android still seems to require user interaction, although it might be possible to use a touchend event from scrolling the page to start the video playback.
Related
I have a .webm video that I am dynamically setting as the source for the video tag.
vidPlayer = document.getElementById("player");
vidPlayer.src = videoPath;
The corresponding HTML:
<body>
<video id="player" class="video-player"></video>
</body>
This is working perfectly on the web browser but when I view this on my mobile, I get a white screen.
I checked the elements tab in the developer tools if different HTML was getting rendered, but it wasn't.
However, in the network tab for chrome web, there is a call made to fetch the video but the same does not happen for chrome android.
I am running this code on localhost.
Can anybody tell me what I am doing wrong or why this is happening?
So, apparently, if your video does not have controls enabled, then for mobile browsers, the user must interact(tap or swipe on the screen) for the video to be visible on the screen.
With controls enabled the video is visible from the start.
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
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
i'm running a react js app that works perfectly fine on laptop but on the iphone the videos won't play even if you click them.
here is the code used to display the videos. I have no error in the developer console of safari either when clicking the video.
<video className='video1' loop autoPlay controls="true" width='50%' height='50%' src='leadmagic.mp4' type='video/mp4'></video>
Add an event click listener on your video tag and in it something like
$(".video1").click(function()
{
this.start()
});
If it doesn't autoplay on your phone it's probably that it isn't available on phone (On Android, I've got the same problem) to avoid the use of mobile data without the user's agreement
Part of my current project involves loading external videos through HTML5's native video tag and then resizing them with Javascript to be the full height & width of the DOM.
My code seems to work perfectly on desktop browsers, but when I load up my project on my ipad the video doesn't get resized because the onloadedmetadata event never gets fired.
Here is a small code sample which reproduces the problem:
function init() {
var video = document.getElementById('viddy');
video.addEventListener('loadedmetadata', function(e){
var dimensions = [video.videoWidth, video.videoHeight];
alert(dimensions);
});
}
document.addEventListener("DOMContentLoaded", init, false);
<video id="viddy" autoplay>
<source src="http://media.w3.org/2010/05/sintel/trailer.webm" type='video/webm' />
<source src="http://www.w3schools.com/html/movie.mp4" type="video/mp4" />
</video>
http://jsfiddle.net/AUSNu/213/
I've even tried coding up a solution using jQuery, on the off-chance that the event may fire, but it still doesn't.
$('#viddy').on('loadedmetadata', function() {
alert('test');
});
I even went as far as enabling remote debugging through safari on my ipad, but still no output within the console.
Are there any workarounds to this? I couldn't find much info about this on the web / in documentation.
Unfortunately, there isn't really a way around this. Mobile Safari will not download any part of the video file until it gets a user interaction (i.e. some kind of touch event), not even the header, which is required to know the dimensions.
In your specific example, you need to enable controls on the video so the user can start it playing. (Or you can write your own code that starts it, but it has to be triggered by a touch or click event.) Once it starts playing, the loadedmetadata even will fire, and you can do what you want.
I recommend reading this other answer where someone else was trying to do pretty much the same thing. It discusses the problem in more detail along with a working link. Also, it addresses another problem with scaling the video that you will probably run into.
Safari on iPad (iOS6) does not scale HTML5 video to fill 100% of page width