How to enable CORS for html5 video loading vtt file? - html5-video

My Need
html5 video element loads both a video and a vtt file saved in a different domain.
The problem
vtt is not loaded and error Text track from origin has been blocked from loading: Not at same origin as the document, and parent of track element does not have a 'crossorigin' attribute.
My investigation
I am aware that CORS needs to be used so vtt can be loaded in html5 successfully.
I have enabled CORS on server side for requests from any domain.
Some articles say adding crossorigin or crossorigin="anonymous" into ` element can do the job, but it doesn't work. Either the video is not loaded at all or different errors appear
I have put my code here below
<body>
<div class="container">
<video id="myvideo" controls preload="auto" width="640" height="264" autoplay>
<source src=http://video.dublearn.net/-KqIgE-3roMSBbiHUmLI/video.mp4 type="video/mp4"></source>
<track kind="captions" label="English" srclang="en" src=http://video.dublearn.net/-KqIgE-3roMSBbiHUmLI/video.vtt default>
</video>
</body>

Hopefully this helps the next person to stumble upon this SO question. I discovered that IE (10 and 11) does not support loading a cross-origin VTT file for a <track>, even if CORS is enabled. In order to add IE support for captions, I had to use a script like the one below.
This script downloads each VTT file via AJAX, creates a blob URL, and replaces each <track> src with its respective blob URL.
window.addEventListener("load", function() {
if (window.navigator.userAgent.indexOf("MSIE ") < 0 && window.navigator.userAgent.indexOf("Trident/") < 0) {
// Not IE, do nothing.
return;
}
var tracks = document.querySelectorAll("track")
for (var i = 0; i < tracks.length; i++) {
loadTrackWithAjax(tracks[i]);
}
});
function loadTrackWithAjax(track) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200 && this.responseText) {
// If VTT fetch succeeded, replace the src with a BLOB URL.
var blob = new Blob([this.responseText], { type: 'text/vtt' });
track.setAttribute("src", URL.createObjectURL(blob));
}
};
xhttp.open("GET", track.src, true);
xhttp.send();
}
<video controls preload width="600" height="337.5" autoplay crossorigin="anonymous">
<source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4" type="video/mp4"></source>
<track kind="captions" label="English" srclang="en" src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt" default>
</video>

I can confirm that the crossorigin=anonymous attribute on the video element does indeed load the text track as expected.
Give this code a shot:
<video id="myvideo" controls preload="auto" width="640" height="264" autoplay crossorigin="anonymous">
<source src=http://video.dublearn.net/-KqIgE-3roMSBbiHUmLI/video.mp4 type="video/mp4"></source>
<track kind="captions" label="English" srclang="en" src=http://video.dublearn.net/-KqIgE-3roMSBbiHUmLI/video.vtt default>
</video>
Finally, remember, you must use a web server to serve this HTML snipped - this cannot be done locally (ie. file//).
If you're familiar with node - install http-server, run with --cors and use ngrok.

Related

Magnific Popup with html5 video

How to use magnific-popup to retrieve and popup an html5 video from my server instead of getting the video from youtube, vimo, ...?
<video width="500" height="350" controls>
<source src="/static/video/bunny.mp4" type="video/mp4" />
Your browser does not support this video format.
</video>
Thanks.
I have got this to work using the following as a link to open the video:
<a class="popup-player" href="/static/video/bunny.mp4">
video link
</a>
and then used the Iframe type to display it:
$('.popup-player').magnificPopup({
type: 'iframe',
mainClass: 'mfp-fade',
removalDelay: 160,
preloader: false,
fixedContentPos: false,
iframe: {
markup: '<div class="mfp-iframe-scaler">'+
'<div class="mfp-close"></div>'+
'<iframe class="mfp-iframe" frameborder="0" allowfullscreen></iframe>'+
'</div>',
srcAction: 'iframe_src',
}
});
This is a very basic version, it opens the video in an iframe but I have yet to work out how to change the things like the height and width. I'm still learning this stuff so I dont know how it works I just know it puts a video up on the screen. If you get it working and build a more complex version please let me know so I can improve my version.
This worked great for me. Uses "Inline" type with auto-starting HTML5 video.
Javascript:
$('.openVideo').magnificPopup({
type: 'inline',
callbacks: {
open: function() {
$('html').css('margin-right', 0);
// Play video on open:
$(this.content).find('video')[0].play();
},
close: function() {
// Reset video on close:
$(this.content).find('video')[0].load();
}
}
});
HTML:
<a href="#video-01" class="openVideo">
<div id="video-01" class="video-popup mfp-hide">
<video preload="false" poster="/videos/01.png">
<source src="/videos/01.mp4" type="video/mp4">
</video>
</div>
Original source: https://github.com/dimsemenov/Magnific-Popup/issues/626
I think that you should check basics first:
-if the path to plugin is correct and included correctly
<!-- Magnific Popup core CSS file -->
<link rel="stylesheet" href="magnific-popup/magnific-popup.css">
<!-- jQuery 1.7.2+ or Zepto.js 1.0+ -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script><br />
<!-- Magnific Popup core JS file --><br />
<script src="magnific-popup/jquery.magnific-popup.js"></script>
It’s not required, but we recommend placing CSS files in <head> and JavaScript files and initialization code in the footer of your site (before the closing </body> tag).
If you already have jquery.js on your site, don’t include it a second time, or use jQuery.noConflict(); mode. Optionally, you can include Zepto.js instead of jQuery, or choose which one to include based on browser support. ACCORDING->http://dimsemenov.com/plugins/magnific-popup/documentation.html
-if you have the movie on your server and if the path to it is correct.
/ is for getting into folder
Then JS:
$(document).ready(function() {
$('.image-link').magnificPopup({type:'image'});
});
For more information see the link I putted few lines above

videojs Javascript api breaks with flash fallback

I'm using video JS to embed a video, and using a javascript to call a function when the video is done playing.
The problem is that in ie8 and lower, it uses a flash fall back. Is there anyway to get the flash fallback to trigger some sort of 'on video ended' event?
Thanks!
Make sure you're using video.js's API rather than that of an HTML5 video element which may or may not be present. This works:
<video id="MY_VIDEO_1" class="video-js vjs-default-skin" controls preload="auto" width="640" height="264" poster="http://www.videojs.com/img/poster.jpg">
<source src="http://vjs.zencdn.net/v/oceans.mp4" type='video/mp4'>
</video>
<script>
//Forcing flash tech
videojs('MY_VIDEO_1',{"techOrder":["flash"]}).ready(function(){
this.on('ended', function(e){
alert('end');
})
});
</script>

Video-JS + Colorbox, loading dynamic videos

Having an issue that has been frustrating me the last few days.
I have some videos on a site that are loaded dynamically from sitecore, and display on a page with thumbnail images. When you click those images you are taken to a lightbox with the video.
The problem is, the video plays in Chrome, Firefox and IE8 -, but not IE9 +. I thought it may be an encoding issue, but I have converted this video so many times to every format available to the web to no avail.
I am setting the plugin to load the video as flash first, then if flash isn't available, load as html5. This will clear all worries in terms of browser support of HTML5 video.
I was thinking that it may be the lightbox and videoJS plugin fighting with each other, or the fact that i am hiding videos and showing them, which i know can sometimes cause issues. I have decided to use a different lightbox, and people seem to have said that colorbox is a decent one to use with videoJS, especially since it has some built in callbacks onLoad.
On to the problem and the code:
The problem:
This lightbox is working, but videoJS seems to throw a few errors when i try and reset the player, which is breaking the videos in IE since its such a dumb browser.
As you can see in the demo link at the bottom, the videos play in IE just fine when they are just set on the page, but when you open the lightbox by pressing "vid1" or "vid2" you are riddled with console errors and the videos no longer play.
The code:
HTML + jScript:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"> </script>
<link href="http://vjs.zencdn.net/4.3/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/4.3/video.js"></script>
<link type="text/css" rel="stylesheet" href="colorbox.css" />
<script type="text/javascript" src="js/jquery.colorbox.js"></script>
<style type="text/css">
.hide {
display: none;
}
</style>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
$(".inline", this).colorbox({
inline: true,
rel: 'videohook',
width: '650px',
onLoad: function() {
//grab the video ID and store it
var vidID = $(this).attr("data-vidID");
//Reset the video players
videojs.players = {};
//set the videoJS player for this video.
videojs(vidID);
}
});
});
</script>
<a rel="videohook" data-vidID="my_video_1" class="inline" href="#video_1">vid 1</a>
<a rel="videohook" data-vidID="my_video_2" class="inline" href="#video_2">vid 2</a>
<div id="video_1" class="video">
<video id="my_video_1" class="video-js vjs-default-skin" controls
preload="none" width="640" height="264" poster=""
data-setup='{"techOrder": ["flash", "html5"]}'>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type='video/mp4'>
<source src="http://www.w3schools.com/html/mov_bbb.ogg" type='video/ogv'>
</video>
</div>
<div id="video_2" class="video">
<video id="my_video_2" class="video-js vjs-default-skin" controls
preload="none" width="640" height="264" poster=""
data-setup='{"techOrder": ["flash", "html5"]}'>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type='video/mp4'>
<source src="http://www.w3schools.com/html/mov_bbb.ogg" type='video/ogv'>
</video>
</div>
</body>
</html>
Console errors im getting:
Uncaught TypeError: Object #<HTMLObjectElement> has no method 'vjs_getProperty'
LIVE DEMO:
Go here to see the errors for yourself: http://kodistro.com
In this case, my solution is to inject the video tag HTML into the lightbox content (when opening) and then call videojs().
So, in pseudo-code:
<script type="text/javascript">
$(document).ready(function() {
$(".inline", this).colorbox({
inline: true,
rel: 'videohook',
width: '650px',
height: '274', //the size most be fixed
onLoad: function() {
var appendVideo1 = '<video id="my_video_1"......> </video>'; //insert the <video> tag. Note.Remove attribute data-setup='{"techOrder": ["flash", "html5"]}'
$("video_1").append(appendVideo1);
},
onComplete: function() {
videojs(my_video_1); //initialize video-js
},
onClosed: function() {
videojs(my_video_1).dispose(); //destroy video-js
}
});
});
</script>
<a rel="videohook" data-vidID="my_video_1" class="inline" href="#video_1">vid 1</a>
<div id="video_1" class="video">
</div>

videojs buffer not playing when using php file

I have this player:
<link href="http://vjs.zencdn.net/c/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/c/video.js"></script>
<video id="milokan" class="video-js vjs-default-skin" controls preload="auto" width="640" height="480" autoplay data-setup="{}">
<source src="play.php?file=<?php echo $code; ?>" type='video/mp4'>
</video>
AND play.php plays header("Content-Type: video/mp4");
This way there is no buffer, the player works but just when the whole file is done downloading.
How can I make it work and keep hiding the file I'm playing ?
Make sure you send the following headers in your response when serving up the video file:
Accept-Ranges: bytes
Content-Length: 22474866 // (example)
Content-Range: bytes 539490-23014355/23014356 // (example)
Content-Type: video/mp4 // (example)
And make sure that you can serve files starting at a certain byte offset if the client requests that. This is required for seeking to work in HTML5 video/audio.

VideoJS event triggers in older version of Android 2.x

We are having trouble firing events on Android 2.x devices. From our testing, Android 4.x and iOS 5/6 work correctly. But on Android 2.x devices, we are sometimes getting the "end" event and sometimes we are getting the "start" event.
It says it has cross browser compatibility but anyone run into these issues?
Here are the relevant parts of the code
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://vjs.zencdn.net/c/video-js.css">
<script src="http://vjs.zencdn.net/c/video.js"></script>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
</head>
<body>
<div id="videoplayer" style="margin:0 auto; text-align:center;">
<video id="video" class="video-js vjs-default-skin" controls autoplay preload="auto" width="300" height="300">
</video>
</div>
</body>
</html>
<script>
$(document).ready(function() {
_V_("video").ready(function() {
var thePlayer = this;
var startVideo = function() {
// do stuff
};
var endVideo = function() {
// do stuff
};
thePlayer.addEvent("play", startVideo);
thePlayer.addEvent("ended", endVideo);
});
});
</script>
I figured out the problem. I was able to reproduce it on a Android 2.2 and 2.3 emulator. No events were firing on video playback because there was an error loading the video.
Issues (For Android 2.x devices):
Playing a link from an HTTPS url was no working. The link we were using was an Amazon Cloudwatch URL which linked to an Amazon S3 bucket. When I changed the url to an HTTP vs HTTPS URL it worked.
I had to remove the autoplay attribute on the video element. Not sure why, but the video player in Android 2.x didn't like this.
Once I made these 2 fixes I was able to stream video on Android 2.x devices (as well as Android 4.x, iPhone and iPod)