I would like to use the html5 video tag only if the users browser is Safari, and if it is not, use a flash video player.
The code below does not work (<!--[if Safari]> conditional is not valid), but it may give you an idea of what i am looking for
<!--[if Safari]>
<video id="player" width="480" controls>
<source src="path/to/movie.mov" />
</video>
<![endif]-->
<!--[if !Safari]>
<script src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script type="text/javascript">
var flashvars = {};
var params = {
allowscriptaccess: "true",
file:"path/to/movie.mov"
};
var attributes = {};
swfobject.embedSWF("swf/player.swf", "player", "640", "480", "9.0.0", flashvars, params, attributes);
</script>
<![endif]-->
Never use browser detection. Use feature detection instead. You can use Modernizr for that, but in this case, you don't need any JavaScript at all to fallback to Flash if the browser doesn't support HTML5's <video> element.
See this article at Nettuts+.
Related
I am live streaming via videojs. The stream works but I am unable to get it to autoplay. Instead I need to click the play button each time I go on the page.
<video-js id="my_video" autoplay controls preload="auto" width="762" height="428" poster="images/poster2.jpg">
<source src="http://xx.xxx.xxx.xx:1935/live/xxxxx/playlist.m3u8" type="application/x-mpegURL">
</video-js>
<script src="https://unpkg.com/video.js/dist/video.js"></script>
<script src="https://unpkg.com/#videojs/http-streaming/dist/videojs-http-streaming.js"></script>
<script>
var player = videojs('my_video');
video.autoplay = true
</script>
Many browsers won't allow autoplay now unless the video is muted. You can add the muted attribute.
You can also use the any option for autoplay, in which case the video will be autoplayed with sound if possible, if not then autoplayed muted if that is possible. Remove the autoplay attribute and use a setup option instead:
var player = videojs('my_video', {autoplay: 'any'});
var options, player;
options = {
controls: true,
autoplay:'any',
techOrder: [ 'chromecast', 'html5' ],
plugins: {
chromecast: {}
}
};
player = videojs(document.getElementById('vjs'), options, function() {
player.chromecast();
});
<video width="352" height="198" controls>
<source src="video.m3u8" type="application/x-mpegURL">
</video>
This code works fine with all browsers on my android device but doesn't works on Firefox / Chrome / Safari on my computer.
I need to play the video on all devices. What can I do?
HLS is not supported on most browsers natively. But can be played via libraries such as hls.js.
this should easily work
<script src="https://cdn.jsdelivr.net/npm/hls.js#latest"></script>
<video id="video"></video>
<script>
if(Hls.isSupported()) {
var video = document.getElementById('video');
var hls = new Hls();
hls.loadSource('https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function() {
video.play();
});
}
</script>
In the HTML5 spec, it suggests you put fallback material in the <video> tag for older browsers that do not support it.
<video width="400" controls>
<source src="mov_bbb.mp4" type="video/mp4">
<source src="mov_bbb.ogg" type="video/ogg">
Your browser does not support HTML5 video.
</video>
However, I cannot find anything for fallbacks when all source types are unsupported. For instance, my Chromium browser cannot play video/mp4, but it can play video/ogg. So I would expect this to render the fallback text.
<video width="400" controls>
<source src="mov_bbb.mp4" type="video/mp4">
Your browser does not support HTML5 video.
</video>
Instead, I just get a video player with nothing in it because it can't load the mp4 file.
Is there a way to have a fallback in HTML 5 video when there is no usable video source? I am aware that the fallback I was attempting is only for old browsers, but I still need a fallback for no available source.
Actually, when you try to load unsupported media types in <source> element, an error event will fire.
You could then listen to these events, and if none of the sources is recognized, trigger the fallback :
var sources = document.querySelectorAll('source');
var source_errors = 0;
for (var i = 0; i < sources.length; i++) {
sources[i].addEventListener('error', function(e) {
if (++source_errors >= sources.length)
fallBack();
});
}
function fallBack() {
document.body.removeChild(document.querySelector('video'));
document.body.appendChild(document.createTextNode('No video with supported media and MIME type found'));
}
<video controls>
<source src="foo.bar" type="video/foo" />
<source src="bar.foo" type="video/bar" />
</video>
It's mentioned in the specs a way to fallback.
"listen to the error event on the last source element and trigger fallback behavior"
<div>
<video width="400" controls>
<source src="mov_bbb.mp4" type="video/mp4">
<source src="mov_bbb.ogg" type="video/ogg"
onerror="parentNode.parentElement.innerText = 'Your browser does not support the video codec' ">
</video>
</div>
There's no HTML behaviour for this, so we'll have to add our own behaviour with JavaScript.
(function() {
"use strict";
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
function setVideoFallback(lazyArea) {
var lowData = false;
if ("connection" in navigator) {
lowData = navigator.connection.saveData === true ||
navigator.connection.effectiveType === "slow-2g" ||
navigator.connection.effectiveType === "2g";
}
//DocumentFragments don't support getElementsByTagName
//oldIE doesn't support querySelectorAll
var lazyVideos = lazyArea.querySelectorAll ?
lazyArea.querySelectorAll("video") :
lazyArea.getElementsByTagName("video");
for (var i = lazyVideos.length; i--;) {
var lazyVideo = lazyVideos[i];
var cantPlay = true;
if (lazyVideo.canPlayType) {
//Loop through the various source elements, and check if
//the browser thinks it can play them
//This works better if we specify the codec along with
//the MIME type
var sources = lazyVideo.getElementsByTagName("source");
for (var i2 = sources.length; i2--;) {
if (lazyVideo.canPlayType(sources[i2].type)) {
cantPlay = false;
break;
}
}
}
//If on a low-data connection, remove the autoplay attribute
//(it's only polite)
if (lowData) {
lazyVideo.removeAttribute("autoplay");
lazyVideo.setAttribute("controls", "");
}
//If you can't play any of the available formats, skip straight to fallback content
if (cantPlay) {
//Extract the fallback and replace the video with it
var children = lazyVideo.childNodes;
for (var i3 = children.length; i3--;) {
var childNode = children[i3];
if (childNode.tagName !== "TRACK" && childNode.tagName !== "SOURCE") {
insertAfter(childNode, lazyVideo);
}
}
lazyVideo.parentNode.removeChild(lazyVideo);
}
}
}
/**
* Retrieve the elements from the 'lazy load' noscript tags and prepare them for display
*/
function setUp() {
//Get all the noscript tags on the page
var lazyLoadAreas = document.getElementsByTagName("noscript");
var supportsTemplates = typeof HTMLTemplateElement === "function";
for (var i = lazyLoadAreas.length; i--;) {
var noScriptTag = lazyLoadAreas[i];
//only process the ones marked for lazy loading
if (!noScriptTag.hasAttribute("data-lazy-load")) continue;
// The contents of a noscript tag are treated as text to JavaScript
var lazyAreaHtml = noScriptTag.textContent || noScriptTag.innerHTML;
// So we stick them in the innerHTML of a new div tag to 'load' them
var lazyArea;
if (supportsTemplates) {
//(if possible, templates are better as they won't start any network calls)
var lazyTemplate = document.createElement("template");
lazyTemplate.innerHTML = lazyAreaHtml;
lazyArea = lazyTemplate.content;
} else {
lazyArea = document.createElement("div");
lazyArea.innerHTML = lazyAreaHtml;
}
setVideoFallback(lazyArea);
noScriptTag.parentNode.replaceChild(lazyArea, noScriptTag);
}
}
//If the page has loaded already, run setup - if it hasn't, run as soon as it has.
if (document.readyState !== "loading") {
setUp();
} else {
document.addEventListener("DOMContentLoaded", setUp);
}
})();
<main>
<figure>
<!--[if !IE]><!-->
<noscript data-lazy-load>
<video height="338" width="600" autoplay loop muted>
<!--<source src="./Sample.mp4" type="video/mp4; codecs=avc1.42E01E,mp4a.40.2">-->
<source src="http://dl3.webmfiles.org/big-buck-bunny_trailer.webm" type="video/webm; codecs=vp8,vorbis">
<source src="https://upload.wikimedia.org/wikipedia/commons/0/07/Backgammon_example.ogv" type="video/ogg; codecs=theora,vorbis">
<!--<![endif]-->
<img src="https://media2.giphy.com/media/BfbUe877N4xsUhpcPc/giphy.gif?cid=790b76115cadcffa59306b73776453f3" height="360" width="480"/>
<!--[if !IE]><!-->
</video>
</noscript>
<!--<![endif]-->
<figcaption>
A bunny emerging from his den and stretching.
<!--[if !IE]><!-->
<noscript aria-hidden="true"><p>
Note: Without JavaScript, the above animation might not play. In that case, the animation can be directly accessed
here.
</p></noscript>
<!--<![endif]-->
</figcaption>
</figure>
</main>
Using the canPlayType function, we ask the browser if it thinks it can play any of the source types. If it doesn't, we pull out the fallback content.
We encase the video in noscript tags so that it won't start loading until we've run the script (unless scripting is disabled, which is the desired behaviour).
We also use IE conditional tags, because oldIE can't read the contents of noscript tags with script.
(Tested with Edge, Firefox, Chrome, and every compatibility mode IE has. The Webm shows in all browers bar IE, which shows the GIF in every compatibility mode.)
#Jaw.sh There's two fallback options that are commonly in use.
Fallback to Flash version of the video.
Fallback to a direct download of the video.
Today's browsers (Opera I'm not sure and not really concerned), are all capable of playing MP4 H.264. So you shouldn't worry too much about incompatibilities, unless most of your viewers live in China.
I am searching for the holy grail of a simple looping html5 video, I am currently using the following code which doesn't seem work
<video width="650" height="650" class="outer_shadow" autoplay="" ended="this.play()" loop>
<source src="/videos?video_id=ag1kZXZ-anQtd2luZG93cg4LEghUaW1lRGF0YRgNDA">
</video>
Can anyone could hilight why this code doesn't work/suggest their best work arround?
Surely you just need to set the loop attribute (see fiddle tested in Chrome):
<video id="myVideo" width="650" height="650" class="outer_shadow" autoplay loop>
<source src="http://content.bitsontherun.com/videos/nPripu9l-60830.mp4">
</video>
If firefox still doesn't like the loop attribute, try the following fix:
document.getElementById('myVideo').addEventListener('ended', function(){
this.currentTime = 0;
}, false);
Update:
Perhaps not as simple as you had hoped but, as a work around for the problem, it might be worth trying one of the many HTML5 video libraries such as video.js. If the problem persists you could, as a worst case, force the library to use Flash where supported (ie. desktop) and fall-back to HTML5 where it's not (as explained here).
Here is the fiddle with working example of HTML5 video player that loops several videos. Just add your URLs to src array...
<script src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
<video id="video" width="500" height="400" controls autoplay></video>
<script>
var src = [
"http://content.adfox.ru/131007/adfox/205544/865991_11.mp4",
"http://all.rutube.ru/130627/gpmdigital/217059/805529_11.mp4"
];
var curSrc = 0;
$(function() {
$('#video').attr("src", src[curSrc % src.length]);
curSrc++;
var video = $('#video').get(0);
$('#video')
.on('loadedmetadata', function() {
video.currentTime=0.01;
video.play();
})
.on('ended', function() {
console.log('ended');
video.src = src[curSrc % src.length];
video.load();
curSrc++;
});
});
</script>
How do I play two videos in a sequence in the HTML5 video tag?
In Google Chrome, the following code plays only the first intro video.
<html>
<head>
<script src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
<script>
var i = 0;
var sources = ['1.mp4', '2.mp4'];
videoElement.addEventListener('ended', function(){
videoElement.src = sources[(++i)%sources.length];
videoElement.load();
videoElement.play();
}, true);
</script>
</head>
<body>
<video id="videoElement" width="640" height="360" autoplay="autoplay">
<source src="intro.mp4" type="video/mp4"></source>
</video>
<body>
<html>
Browser should fire error 'videoElement is not defined' with your JavaScript code, you must get video element from DOM instead of using its id directly. Please change your code to
$(document).ready(function() {
//place code inside jQuery ready event handler
//to ensure videoElement is available
var i = 0;
var sources = ['1.mp4', '2.mp4'];
$('#videoElement').bind('ended', function() {
//'this' is the DOM video element
this.src = sources[i++ % sources.length];
this.load();
this.play();
});
});
In case someone came across this question again, here is my solution to similar problem-I needed to play first video once and then second video in a loop. I also have support for .webm, .m4v and .mp4.
This is my JS:
$(document).ready(function(){
var vid = document.getElementById("landing-video");
vid.onplay = function() {
var source=vid.currentSrc;
folder = source.match(/(.+)(\/)/);
ext = source.match(/(\.\w+)$/);
};
vid.onended = function() {
$("#landing-video").attr({
"src":folder[0]+"video-2"+ext[0],
"loop":""
});
};
});
And this is my HTML:
<video autoplay="" muted="" poster="" id="landing-video">
<source src="my-folder/video-1.webm" type="video/webm">
<source src="my-folder/video-1.m4v" type="video/x-m4v">
<source src="my-folder/video-1.mp4" type="video/mp4">
</video>
This might save someone some time.