Playing m3u8 video with video tag - html

<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>

Related

Video-js tag autoplay HLS Live stream

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();
});

Google Chrome does not autoplay HTML5 video on mobile

I have problems to get a video to play on my Android mobile in the latest version of Chrome. In other browsers like the Puffin browser the video is playing. For test purposes I tried all common formats:
mp4
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/mp4" /></video>
<br />
webm
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE.webm" type="video/webm" /></video>
<br />
ogg
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE.ogv" type="video/ogg" /></video>
https://codepen.io/anon/pen/ozpVNP
According to Mozilla the first video, that is H.264 + AAC in MP4 should play. I also take this article in account and tried to play the videos by JavaScript additionally as well as tried to remove the type attribute on the first video tag without success.
How can I get it work in Chrome on Mobile?
<video autoplay loop autobuffer muted playsinline>
<source src="video/video-hat.mp4" type="video/mp4">
</video>
The problem is that Google want that users initiate by themselves any media, so If you debug your device chrome browser, you will get the warning "Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture."
So that means you need to attach the video initialization, for example, with a click event
There doesn't appear to be any great info on this, so thought I'd post my findings.
I've been debugging html5 video playback on Chrome desktop and mobile on an Android 5.0.1 Samsung S4 with Chrome 61 and the embedded browser, and Safari 9 & 11, using an automatic javascript play/pause written in AngularJS (below). The video is embedded in a carousel so is sometimes visible, sometimes not. In summary:
I would recommend having both webm(vp8/vorbis) and mp4(h264/aac) formats. These are the most supported formats and have equivalent quality for the same bitrate. ffmpeg can encode both.
It seems Chrome mobile prefers webm if it can get it, so put that first.
If a browser plays a file when you direct it to the file url, this does not mean it will play it when embedded in a video tag, though it will tell you if the format & codecs are supported if it does play. Chrome mobile seems very picky about having a video source whose resolution is too high.
Safari (and probably iOS) will not play a video unless served by a server supporting byte-ranges. Apache, nginx and Amazon S3 for example do support them, but many smaller web servers (like WSGI servers) do not.
The order of the videos matters more than the source media attribute. Always have low resolution versions of a video first. The example below uses 1920x1080 and 1280x720. It seems if the mobile browser encounters a video that is "too high-res", it just stops processing the other sources and prefers the poster.
having a controls attribute and manual play vs playing through javascript doesn't appear to make any difference.
the muted attribute stops android from putting a little speaker icon in the status bar when playing but off-screen, even when the video doesn't have audio. As a side-note, I'd also really think about your audience if you intend to autoplay video with sound. Personally I think it's a bad idea.
the preload attribute doesn't seem to make much difference. The browser will tend to automatically preload the selected video metadata anyway.
having a source type attribute does not stop the video from playing. If anything it helps the browser choose which source to pick for the best
the JS video.oncanplay event is the best way to see if the video tag has been successful. If you don't get that, the video won't play, but the browser won't tell you why.
HTML:
<video class="img-responsive-upscale ng-scope"
video-auto-ctrl loop muted preload poster="0022.png">
<source src="vid_small.webm" media="(max-width: 1280px)" type="video/webm">
<source src="vid_small.mp4" media="(max-width: 1280px)" type="video/mp4">
<source src="vid.webm" media="(max-width: 1920px)" type="video/webm">
<source src="vid.mp4" type="video/mp4">
<img src="0022.png" alt="something"
title="Your browser does not support the <video> tag">
</video>
Javascript:
<script type="text/javascript">
angular.module('myproducts.videoplay', []).directive('videoAutoCtrl',
function() {
return {
require: '^uibCarousel',
link: function(scope, element, attrs) {
var video = element[0];
var canplay = false;
var rs = ["HAVE_NOTHING", "HAVE_METADATA", "HAVE_CURRENT_DATA", "HAVE_FUTURE_DATA", "HAVE_ENOUGH_DATA"];
var ns = ["NETWORK_EMPTY", "NETWORK_IDLE", "NETWORK_LOADING", "NETWORK_NO_SOURCE"];
function vinfo() {
console.log("currentSrc = " + video.currentSrc);
console.log("readyState = " + rs[video.readyState]);
console.log("networkState = " + ns[video.networkState]);
bufinfo();
}
function bufinfo() {
// tr is a TimeRanges object
tr = video.buffered
if (tr.length > 0) {
var ranges = ""
for (i = 0; i < tr.length; i++) {
s = tr.start(i);
e = tr.end(i);
ranges += s + '-' + e;
if (i + 1 < tr.length) {
ranges += ', '
}
}
console.log("buffered time ranges: " + ranges);
}
}
video.onerror = function () {
console.log(video.error);
}
video.oncanplay = function () {
canplay = true;
if (!playing) {
console.log("canplay!");
vinfo();
}
}
var playing = false;
function playfulfilled(v) {
console.log("visible so playing " + video.currentSrc.split('/').pop());
playing = true;
}
function playrejected(v) {
console.log("play failed", v);
}
function setstate(visible) {
if (canplay) {
if (visible) {
p = video.play();
if (p !== undefined) {
p.then(playfulfilled, playrejected);
}
} else if (playing) {
video.pause();
console.log("invisible so paused");
playing = false;
}
} else {
console.log("!canplay, visible:", visible);
vinfo();
}
}
// Because $watch calls $parse on the 1st arg, the property doesn't need to exist on first load
scope.$parent.$watch('active', setstate);
}
};
});
</script>
I had an issue where the video worked on my desktop chrome, and desktop-mobile view, but not my iphone. Turns out i needed to add the "playsinline" property to the video tag. :]
The issue fixed for me after switching off "Data saving" mode in chrome.
I spend all my afternoon to fix an autoplay problem on iOS and discovered you just to disable the "ECO MODE" or it won't play automatically.

loop html5 video using ended event broken

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>

PLaying two videos in sequence in Chrome by using the <video> tag

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.

use html5 video player only if browser is Safari

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+.