I use video tag to play HLS video, and the video size is 0 always.
<video id=video src="http://xxx.m3u8" autoplay controls/>
<script>
const video = document.getElementById('video')
video.addEventListener('play', () => {
console.log(video.videoWidth, video.videoHeight)
// both are 0
})
</script>
Currently desktop browsers do not support playing an HLS video directly using just the video tag. (Maybe it does work on Safari or IOS).
To reproduce an HLS stream you need to use one of the video players available. You have some open source projects, like hlsjs: https://github.com/video-dev/hls.js. Or comercial players like flowplayer, or jwplayer.
Basic html code using hlsjs player:
<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>
"loadedmetadata" wont' work for HLS streams, so this is the best solution
var video = document.getElementById("video")
video.onplaying = function () {
var width = video.videoWidth
var height = video.videoHeight
console.log("video dimens loaded w="+width+" h="+height)
}
Related
I'm use a tag html5 video + hls.js for video streaming .m3u8
<div class="container-video">
<video id="video"
width="700"
height="400"
preload="auto"
controls>
<source [src]="videoLink" type="application/x-mpegURL">
</video>
</div>
playVideoLive(videoLink) {
const video = document.getElementsByTagName('video')[0];
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(videoLink);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function () {
video.play();
});
}
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = videoLink;
video.addEventListener('canplay', function () {
video.play();
});
}
}
Hoe i can show the dropdown with the list of quality video?
You can use an extra package to add the a track selector - there may be others but this one seems quite popular: https://www.npmjs.com/package/videojs-hls-quality-selector
You can also add your own controls and do it via the API using: https://github.com/video-dev/hls.js/blob/master/docs/API.md#hlscurrentlevel
There is a demo which uses the API here (at the time of writing) - go to the bottom of the demo page to see the levels and you can click on them there: https://hls-js-dev.netlify.app/demo/
In database, videos are saved in m3u8 format as shown below. I want to open video when I click on button or download it. I read this. But still not clear for me? Thanks in advance.
dfa7088-9d3c-4b23-0010a-59fc63f4441d/hls/qe8b807916f8816a.m3u8
#if( $item->media_type=='v')
<script src="https://cdn.jsdelivr.net/npm/hls.js#latest"></script>
<video id="video" src=" https://cdn.kenan.net/{{ $item->media_path}}" controls width="200px" height="200px"></video>
<script>
if(Hls.isSupported())
{
var video = document.getElementById('video');
var hls = new Hls();
hls.loadSource('playlist.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function()
{
video.play();
});
}
else if (video.canPlayType('application/vnd.apple.mpegurl'))
{
video.src = 'playlist.m3u8';
video.addEventListener('canplay',function()
{
video.play();
});
}
</script>
#else#endif
Summary
The API I speak about
The context
The problem: Actual result + Expected result
What I already have tried
Clues to help you to help me
Minimal and Testable Example: Prerequisites and Steps to follow + Sources
The API I speak about
https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder
The context
I have a video element that I load & play several times with different src. Between two different videos, a transition occures and each video appears with a fade in. When a video is playing, I draw it in a canvas with the transition and the fade in.
Everything I draw in the canvas is recorded using the Web API MediaRecorder. Then I download the WEBM file corresponding to this recording.
The problem
Actual result
The resulting WEBM is jerky. When I drew in the canvas, the drawing was fluid. But the WEBM resulting from the recording of the canvas drawing is jerky.
Expected result
The WEBM resulting from the recording of the canvas drawing must be as fluid as the canvas drawing itself. If it's impossible to have exactly this result, then: the WEBM must be approximately as fluid as the canvas drawing itself in a way that we quite can't say it's jerky.
What I have already tried
First, I've tried to set a time slice of 1ms, of 16ms (corresponding to 60fps), of 100ms, then 1000, then 10000, etc. to the method start of the Media Recorder, but it didn't work.
Second, I've tried to call requestData every 16ms (in a simple JS timeoutlistener executed every 16ms), but it didn't work.
Clues to help you to help me
Perhaps I'm wrong but it would be possible that a material limit exist on my computer (I have a HP Spectre x360 that doesn't have graphic card, but just a little graphics chip), or a logical limit on my Chromium browser (I have Version 81.0.4044.138 on my Ubuntu 16.04 LTS).
If you can confirm this it would solve this question. If you can explain how to deal with this problem it would be very good (alternative solution to the Web API Media Recorder, or something else).
Minimal and Testable Example
Prerequisites and Steps to follow
Have at least 2 WEBM videos (which will be the input videos, remember: we want to output a new video that contains the canvas drawing, which itself contains these two input videos plus transitions and colors effects etc.)
Have a HTTP server and a file called "index.html" that you will open with Chromium v.81 e.g.. Copy/paste the following sources inside ; click on the "Start" button (you won't need to click on the "Stop" button) ; it will draw both videos on the canvas, with the transitions & colors effects, it will record the canvas drawing, and a "Download the final output video" will appear, allowing you to download the output video. You will see that it's jerky.
In the following sources, copy/paste the paths of your videos in the JS array called videos.
Sources
<html>
<head>
<title>Creating Final Video</title>
</head>
<body>
<button id="start">Start</button>
<button id="stop_recording">Stop recording</button>
<video id="video" width="320" height="240" controls>
<source type="video/mp4">
</video>
<canvas id="canvas" width=3200 height=1608></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var videos = []; // Populated by Selenium
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var video = document.querySelector("video");
startRecording();
$('#start').click(function() {
showSomeMedia(0, 0);
});
function showSomeMedia(videos_counter) {
resetVideo();
if(videos_counter == videos.length) {
$('#stop_recording').click();
return;
} else {
setVideoSrc(videos_counter);
setVideoListener();
videos_counter++;
}
video.addEventListener('ended', () => {
showSomeMedia(videos_counter);
}, false);
}
function resetVideo() {
var clone = video.cloneNode(true);
video.remove();
video = clone;
}
function setVideoSrc(videos_counter) {
video.setAttribute("src", videos[videos_counter]);
video.load();
video.play();
}
function setVideoListener() {
var alpha = 0.1;
video.addEventListener('playing', () => {
function step() {
if(alpha < 1) {
ctx.globalAlpha = alpha;
}
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
requestAnimationFrame(step)
if(alpha < 1) {
alpha += 0.00001;
}
}
requestAnimationFrame(step);
}, false)
}
function startRecording() {
const chunks = [];
const stream = canvas.captureStream();
const rec = new MediaRecorder(stream);
rec.ondataavailable = e => chunks.push(e.data);
$('#stop_recording').click(function() {
rec.stop();
});
rec.onstop = e => exportVid(new Blob(chunks, {type: 'video/webm'}));
window.setTimeout(function() {
rec.requestData();
}, 1);
rec.start();
}
function exportVid(blob) {
const vid = document.createElement('video');
vid.src = URL.createObjectURL(blob);
vid.controls = true;
document.body.appendChild(vid);
const a = document.createElement('a');
a.download = 'my_final_output_video.webm';
a.href = vid.src;
a.textContent = 'Download the final output video';
document.body.appendChild(a);
}
</script>
</body>
</html>
The problem is solved by using my gaming laptop (RoG), wich has a good graphic card, able to record at higher frequency than my Spectre x360 development laptop.
I'm playing HLS audio in Chrome Browser on Android using HTML 5 <audio>.
How can I get Chrome to keep playing a HLS stream on lock stream or when browser tab is inactive?
On iOS the stream will continue to play when the browser tab is changed or screen is locked, but it stops the audio on Android.
<audio controls preload="meta">
<source
src="http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/sl.m3u8"
type="application/x-mpegURL"
/>
</audio>
I even added mediaSession info to try and help it along.
var audio = document.getElementById("audio");
if ("mediaSession" in navigator) {
audio.onplay = function() {
navigator.mediaSession.metadata = new MediaMetadata({
title: "TEST",
artist: "ARTIST"
});
};
}
Android will play hls streams natively, but if you want the behaviour where it plays on the lock screen use hls.js
let audio = document.getElementById("hls-audio");
let source = "http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/sl.m3u8"
if (Hls.isSupported()) {
console.log("hello hls.js!");
let hls = new Hls();
hls.attachMedia(audio);
hls.on(Hls.Events.MEDIA_ATTACHED, () => {
console.log("video and hls.js are now bound together !");
hls.loadSource(source);
});
}
audio.onplay = () => {
console.log("we can track events the same way with hls.js")
};
Is there a way I can start playing my HTML5 MP4 video only after the entire video is buffered (100%). When it is in the process of buffering, I should display the Loading screen. Please help. This code should work in both Firefox and IE11.
Hyperlink Titles Example :
- Play Video1: Fav Foods - Play Video1: Fav Veg - Play Video2: Fav Animal
And here is the code I have when I click on the hyperlink and also the Video tags. I load the video dynamically from the database. The attribute 'pos' tells the time in seconds where the player has to seek playing.
<video id="VideoContainer" controls="controls" style="width:500px;height:320px" preload="auto">
<source id="VideoData" src=#Model.IntroVideoPath type="video/mp4" />
Your browser does not support the video tag.
<a onclick="navVideo('#items.FileName','#items.StartSec');">#items.DisplayText</a>
function navVideo(fileName, pos) {
//Get Player and the source
var player = document.getElementById('VideoContainer');
var mp4Vid = document.getElementById('VideoData');
var mp4CurVid = $(mp4Vid).attr('src');
//Reload the player only if the file name changes
if (mp4CurVid != fileName) {
$(mp4Vid).attr('src', fileName);
player.load();
player.play();
if (pos != 0) {
setTimeout(function () {
player.currentTime = pos;
player.play();
}, 1000);
}
}
else {
player.pause();
player.currentTime = pos;
player.play();
}
The problem was with the encoding technique for that MP4 file. I encoded with different settings (random settings options for Mp4) and finally got that to work without buffer.
You could use the this http://videojs.com/ to get that to work.