HTML 5 dynamically loaded videos causing black screen on iPad - javascript

I'm loading in videos dynamically by changing the video tag's src in code. When I try my code on an ipad (no idea if it works in the simulator or not), the first video plays fine but the next one just gives me a black screen. I have tried playing the second video first (to check for encoding issues) and it plays fine.
Here is my javascript function that loads/plays the video:
function loadVideo(video_path){
var vid = document.getElementById('v');
vid.src = video_path;
vid.load();
// play the video once it has loaded
vid.addEventListener('canplaythrough', function(e){
vid.style.display = "block";
vid.play();
}, false);
// hide the video container once the video has finished playing
vid.addEventListener('ended', function(e){
vid.style.display = "none";
}, false);
}
Called from my code like:
$('a').click(function(){
switch(video){
case 0:
loadVideo('path/to/myvideo.mp4');
break;
case 1:
loadVideo('path/to/myvideo2.mp4');
break;
case 2:
loadVideo('path/to/myvideo3.mp4');
break;
// etc
}
video++;
});
And my html inside the body tag:
<video id="v" type="video/h264" width="960" height="500"></video>
I have tried removing the video tag after each play and inserting it in again but that had no effect. Ideas welcome! :)

This isn't a solution for your exact question, but the concepts are there and you should be able to adjust it to your own code (the full extent of which I'm not privy to, of course). The following code is something I put together to have the VIDEO element load in and play the next video source in a queue automatically after the current video source is done.
The reason I use timeupdate to check for the video being "near" the end instead of just looking for the ended event is because the ended event is notoriously unreliable on older devices (such as the original iPad). You can use the ended event if you so wish, of course.
(function ($) {
var srcs = [
"video1.mp4",
"video2.mp4",
"video3.mp4",
"video4.mp4"
],
index = 0,
$video = $("#vid").attr("src", srcs[index]).bind("timeupdate", timeUpdateHandler),
video = $video.get(0);
function timeUpdateHandler(e) {
if (video.currentTime >= (video.duration - 0.1)) {
nextVideo();
}
}
function nextVideo() {
index++;
if (index === srcs.length) {
index = 0;
}
$video.attr("src", srcs[index]);
video.play();
}
})(jQuery);
Let me know if this helps you or if you have any questions.

You can use
<video onended="javascript:on_video_ended();"></video>
<script>
function on_video_ended(){
//javascript code goes here.
}
</script>

Related

Need help in JavaScript to change and stop background video

In my site I have a video in background. Now I want to add two buttons, One will stop the video/start the video and one will stop the video and replace it with a image.
This is my site - site link
Can anyone please help me?
Thanks
you'll need to create the two buttons and style them as desired but here is the code you'll need to start/stop the video:
// assuming we're inside of your click listener callback
var video = document.querySelector('video');
if (video.playing) {
video.pause() // will bring the video to a halt
video.currentTime = 0; // brings it back to the beginning
} else {
video.play();
}
here is the code you'll need to replace the video with an image:
// assuming we're inside of your click listener callback
var video = document.querySelector('video');
var newImage = document.createElement('img');
newImage.src = 'source-of-your-image.jpg';
video.parentNode.insertBefore(newImage, video); // inserts img into DOM
video.parentNode.removeChild(video); // removes the video
You need some code like this to get the element by ID and for play/pause
var vid = document.getElementById("myVideo");
function playVid() {
vid.play();
}
function pauseVid() {
vid.pause();
}
And the HTML could be a[href]:
Play
Pause
To display the image you can use the poster attribute for video html5 tag. The image will display until the video is loaded and play is clicked and you can display it by reloading the video:
var vid = document.getElementById("myVideo");
function displayPoster() {
vid.load();
}

Pause and resume slick slider once video finishes

I have a slick.js slider that contains video and I want the slider to pause once it reaches a video slide and resume cycling once the video finishes without user interaction. I can get this functionality to work with the first video in a cycle but on the second video slide, the slider will not resume once the video completes.
Fiddle
I have a console log that writes out when the video completes but it won't say anything once the second video completes. I believe it is not seeing the function to play the slick slider.
function myHandler(e) {
console.log('Video Complete')
$('.sliderMain').slick('slickPlay');
}
You were only binding the first video tag to your myHandler function:
// It only gets the first element
var video = document.getElementsByTagName('video')[0];
video.addEventListener('ended',myHandler,false);
Since you're using jQuery, you can bind an event when the videos have ended like that:
$('video').on('ended',function(){
console.log('Video Complete')
$('.sliderMain').slick('slickPlay');
});
jQuery demo
The JavaScript equivalent would be so:
var videos = document.getElementsByTagName('video');
for (var i=0; i<videos.length; i++) {
videos[i].addEventListener('ended',myHandler,false);
}
JavaScript demo
SlickSlider is responsive and needs to work 360 (across all devices).
Your solution will not work on mobile, since autoplay of a video is forbidden.
Also this solution allows multiple videos to be playing at once, which is sub-optimal.
A better solution would be to pause the carousel only when the video is played by the user, and resume the carousel (pausing the video) when a slide is detected.
This works also on mobile devices. Just make sure, you don't serve a video tag on mobile. Before outputting your slide via PHP template, just check the user agent and serve a fallback image instead. Then use this for your video/autoplay/resume issue:
$('.homepage .hero-slider').on('afterChange', function(event, slick, currentSlide, nextSlide) {
var $active = $('.slick-slide.slick-current.slick-active');
var video = $active.find('video');
if (video.length == 1) {
var $slickInstance = $(this);
// play() only works with a valid id as selector :)
var video = document.getElementById(video.attr('id'));
video.play();
$slickInstance.slick('slickPause');
video.addEventListener('ended', function () {
$slickInstance.slick('slickPlay');
}, false);
}
});

Mp4 from Dropbox used with HTML5 video player, is not repeating

I'm working on a Squarespace website, and they don't allow video upload, so I'm using Dropbox to host a video.
The video starts playing, but he is not repeating.
This is the code:
<video id="htmlVideo" loop="loop">
<source type="video/mp4" src="https://www.dropbox.com/s/videoID/videoplayback.mp4?dl=1">
</video>
What could be the problem?
This is how I create the video
/*
function repeatForDropbox() {
console.log("repeatForDropbox caled" + htmlVideo );
}
*/
function createVideo() {
var video = document.createElement("video");
video.id = "htmlVideo";
video.loop = "loop";
var vidSource = document.createElement("source");
vidSource.type = "video/mp4";
vidSource.src = "https://www.dropbox.com/s/videoID/videoplayback.mp4?dl=1";
video.appendChild( vidSource );
var vidLocation = document.querySelector('#location').parentNode;
vidLocation.appendChild( video );
htmlVideo = document.querySelector(" #htmlVideo ");
// on load, play the video/mp4
window.onload = function () {
setTimeout(function() {
htmlVideo.play();
// htmlVideo.addEventListener("ended", repeatForDropbox);
// I tried here to make the video repeat, using the "ended" event listener
// so when the video ended, the video
// should get another <source> element(same src)
// and delete the old one
// but the event didn't fire
// I also tried htmlVideo.onended = function() {} , but same result
}, 500);
}
}
Just a guess, but I suspect this relates to redirects. A Dropbox share link with ?dl=1 on it will redirect you to a one-time use URL to download the content. Perhaps when the video player tries to loop, it tries to access the target of the redirect again.
This might show up in the network traffic from the browser, so it's worth taking a look. (E.g. the network tab of Chrome inspector, if you're using Chrome.)
I would see if squarespace will let you save the binary of the video into a text file and then import it with AJAX and save it to indexedDB before converting it to video.
Here's some links:
Display a video from a Blob Javascript
https://simpl.info/video/offline/
Just in case anyone still needs the solution, I found a workaround using jQuery:
$('video').on('ended', function () {
this.load();
this.play();
});
However, there is a slight delay between repeats!

Javascript stop and return to poster HTML 5 video

This is my javascript which pause and play the HTML 5 video when a button is pressed but I want to stop the video instead of pausing and returning to the video poster how can I achieve that?
function vidplay() {
var video = document.getElementById("bg-vid");
var button = document.getElementById("play");
if (video.paused) {
video.play();
} else {
video.pause();
}
}
Use load() method (although I believe changing the src attribute implicitly calls it):
...
if (video.paused) {
video.play()
} else {
load();
}
...
Note: this method re-loads the resource, thus depending on caching settings it may be re-downloaded causing unnecessary bandwidth and CPU usage.
The easiest way I have been able to find is to reset the source of the video. The other way to handle it would be to have a div with the poster image in that you swap out for the video.
The problem with this method is that by resetting the source you lose the playhead position so if that's important you'll also need to track the currentTime before resetting, and on play have the playhead set back to that currentTime value
<script>
var vid=document.getElementById('bg-vid');
vid.addEventListener("pause", resetVideo, false);
function resetVideo() {
// resets the video element by resetting the source
this.src = "video.mp4" // **source of video**
}
</script>

trying to add a multi source video player with more then one video?

Im trying to make a video player work in all browsers. There is
more then one video and every time you click on demo reel it plays the
video and if you click the video 1 the other video plays. How can i
make them both work in all browsers? Here is my html and javascript
html
<video id="myVideo" controls autoplay></video>
<div>
Demo Reel</div>
video 1</div>
</div>
javascript
function changeVid1() {
var changeStuff = document.getElementById("myVideo");
changeStuff.src = "video/demoreel.mp4"
}
function changeVid2() {
var changeStuff = document.getElementById("myVideo");
changeStuff.src = "video/video1.mp4";
}
After you switch the source of the video, you need to run .load() on it to force it to load the new file. Also, you need to provide multiple formats, because there is no video codec supported by all browsers.
First, set up your sources like this:
var sources = [
{
'mp4': 'http://video-js.zencoder.com/oceans-clip.mp4',
'webm':'http://video-js.zencoder.com/oceans-clip.webm',
'ogg':'http://video-js.zencoder.com/oceans-clip.ogv'
}
// as many as you need...
];
Then, your switch function should look like this:
function switchVideo(index) {
var s = sources[index], source, i;
video.innerHTML = '';
for (i in s) {
source = document.createElement('source');
source.src = s[i];
source.setAttribute('type', 'video/' + i);
video.appendChild(source);
}
video.load();
video.play(); //optional
}
See a working demo here.
This gives the browser a list of different formats to try. It will go through each URL until it finds one it likes. Setting the "type" attribute on each source element tells the browser in advance what type of video it is so it can skip the ones it doesn't support. Otherwise, it has to hit the server to retrieve the header and figure out what kind of file it is.
This should work in Firefox going back to 3.5 as long as you provide an ogg/theora file. And it will work in iPads, because you only have one video element on the page at a time. However, auto-play won't work until after the user clicks play manually at least once.
For extra credit, you can append a flash fallback to the video element, after the source tags, for older browsers that don't support html5 video. (i.e., IE < 9 - though you'll need to use jQuery or another shim to replace addEventListener.)

Categories

Resources