Capturing video from web browser in HTML5 - html

I'm trying to follow this guide on capturing video from webcam in HTML5
http://www.html5rocks.com/en/tutorials/getusermedia/intro/
I have copied and pasted the following code but Chrome does not ask for permission to use my camera
<video autoplay></video>
<script>
var onFailSoHard = function(e) {
console.log('Reeeejected!', e);
};
// Not showing vendor prefixes.
navigator.getUserMedia({video: true, audio: true}, function(localMediaStream) {
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(localMediaStream);
// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia.
// See crbug.com/110938.
video.onloadedmetadata = function(e) {
// Ready to go. Do some stuff.
};
}, onFailSoHard);
</script>
Whereas when I click "capture video" in the guide it works, my webcam shows...
Another website has similar code but yet again it's not working for me
http://dev.opera.com/articles/view/playing-with-html5-video-and-getusermedia-support/
<!-- HTML code -->
<video id="sourcevid" autoplay>Put your fallback message here.</video>
/* JavaScript code */
window.addEventListener('DOMContentLoaded', function() {
// Assign the <video> element to a variable
var video = document.getElementById('sourcevid');
// Replace the source of the video element with the stream from the camera
if (navigator.getUserMedia) {
navigator.getUserMedia('video', successCallback, errorCallback);
// Below is the latest syntax. Using the old syntax for the time being for backwards compatibility.
// navigator.getUserMedia({video: true}, successCallback, errorCallback);
function successCallback(stream) {
video.src = stream;
}
function errorCallback(error) {
console.error('An error occurred: [CODE ' + error.code + ']');
return;
}
} else {
console.log('Native web camera streaming (getUserMedia) is not supported in this browser.');
return;
}
}, false);
I was wondering if I'm missing something or has something changed, because none of the sample code has worked for me so far.

Found out what was happening. For anyone wondering, on Chrome you only have access to the webcam if running from a server. It won't work on just a file.

Related

Embed camera frame in web app html5

I want to beuild web app that the user will upload a image from device camera.
I know that I can use <input type="file" accept="image/*" capture="camera">.
My question is that if there is a way to "embed" the camera screen in the page itself. In other words, I want that the screen will look like this:
I suggest you can read the article Capturing Audio & Video in HTML5.
Here is the code to access your camera:
<video autoplay></video>
<script>
var errorCallback = function(e) {
console.log('Reeeejected!', e);
};
// Not showing vendor prefixes.
navigator.getUserMedia({video: true, audio: true}, function(localMediaStream) {
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(localMediaStream);
// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia.
// See crbug.com/110938.
video.onloadedmetadata = function(e) {
// Ready to go. Do some stuff.
};
}, errorCallback);
</script>
Taking screenshots:
<video autoplay></video>
<img src="">
<canvas style="display:none;"></canvas>
<script>
var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var localMediaStream = null;
function snapshot() {
if (localMediaStream) {
ctx.drawImage(video, 0, 0);
// "image/webp" works in Chrome.
// Other browsers will fall back to image/png.
document.querySelector('img').src = canvas.toDataURL('image/webp');
}
}
video.addEventListener('click', snapshot, false);
// Not showing vendor prefixes or code that works cross-browser.
navigator.getUserMedia({video: true}, function(stream) {
video.src = window.URL.createObjectURL(stream);
localMediaStream = stream;
}, errorCallback);
</script>
Video tag is there HTML5 to handle this. and you need to use getUserMedia api to handle the streaming. most of the modern browsers supports it. To validate whether it is supported, use javascript to check that. You can try this:
if(navigator.getUserMedia()) ....
Here's a good tutorial on how to use a web cam to capture images. The same person also has a tutorial on capturing video to GIFs.
http://davidwalsh.name/browser-camera
HTML 5 Image capture tutorial & demo

Export HTML5 blob video to MP4

I am trying to use Chrome's screen sharing feature to make a screen recorder and save the video in MP4 format. However, I have no idea how I do this. The demo is at https://figgycity50.kd.io/screencap.html (include https!) and the code is:
<video autoplay></video>
<button>start</button>
<script>
navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.getUserMedia;
var stream = null;
button = document.querySelector("button");
function start(e) {
// Seems to only work over SSL.
navigator.getUserMedia({
video: {
mandatory: {
chromeMediaSource: 'screen',
maxWidth: 1280,
maxHeight: 720
}
}
}, function(s) {
stream = s;
button.textContent = 'Stop';
button.removeEventListener('click', start);
button.addEventListener('click', stop);
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(stream);
video.autoplay = true;
stream.onended = function(e) {
//The save code should go here.
};
//document.body.appendChild(video);
}, function(e) {
});
}
function stop() {
stream.stop();
button.addEventListener('click', start);
button.textContent = 'Capture your screen';
}
button.addEventListener('click', start);
</script>
How do I do this?
You cannot save directly to MP4 format with the way the current state of getUserMedia API is working, you can however save in webm format and convert it afterwards.
Several attempts have been made, webRTC experiment project has several versions of recording in the browser implemented:
https://www.webrtc-experiment.com/RecordRTC/
You can however save directly in MP4 format using HTML Media Capture.
This works by extending the <input type="file"/> and adding new values for the accept parameter with options for audio, video and photo/snapshot. This however works only for mobile browsers, as the desktop browser will only interpret it as a simple file upload.
HDFVR has a demo of this, if you access their demo from a mobile device.
More details can be read in the following article:
http://hdfvr.com/html5-video-recording

Youtube autoplay not working on mobile devices with embedded HTML5 player

To my problem, I have one link . I want to play the video by clicking the link in a fancybox overlay window. This is not a problem. The problem is the parameters, for example "autoplay" or "autohide".
The following link doesn't work:
The Overlay-Window opened, but the video is not playing automatically.
EDIT: I want to use the HTML5 Player on mobile devices. On a desktop-browser it works with the parameters, but not on mobile devices.
As it turns out, autoplay cannot be done on iOS devices (iPhone, iPad, iPod touch) and Android.
See https://stackoverflow.com/a/8142187/2054512 and https://stackoverflow.com/a/3056220/2054512
Have a look on code below.
Tested and found working on Mobile and Tablet devices.
<!-- 1. The <iframe> (video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
The code below was tested on iPhone, iPad (iOS13), Safari (Catalina). It was able to autoplay the YouTube video on all devices. Make sure the video is muted and the playsinline parameter is on. Those are the magic parameters that make it work.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=2.0, minimum-scale=1.0, user-scalable=yes">
</head>
<body>
<!-- 1. The <iframe> (video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
width: '100%',
videoId: 'osz5tVY97dQ',
playerVars: { 'autoplay': 1, 'playsinline': 1 },
events: {
'onReady': onPlayerReady
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.mute();
event.target.playVideo();
}
</script>
</body>
</html>
The official statement "Due to this restriction, functions and parameters such as autoplay, playVideo(), loadVideoById() won't work in all mobile environments.
Reference: https://developers.google.com/youtube/iframe_api_reference
There is a way to make youtube autoplay, and complete playlists play through. Get Adblock browser for Android, and then go to the youtube website, and and configure it for the desktop version of the page, close Adblock browser out, and then reopen, and you will have the desktop version, where autoplay will work.
Using the desktop version will also mean that AdBlock will work. The mobile version invokes the standalone YouTube player, which is why you want the desktop version of the page, so that autoplay will work, and so ad blocking will work.
How to use a Youtube channel live url to embed and autoplay. Instead of Video ID that has to be constantly updated for live stream changes.
I mixed two sets of code and came up with a working auto play Youtube video embed from a channel live stream.
My thanks to both of the other contributors for their help. Hopefully this helps someone else some time.
Example stream
https://www.youtube.com/embed/live_stream?channel=UCwobzUc3z-0PrFpoRxNszXQ
The code below by Zubi answered Nov 25 '16 at 7:20 works with Youtube videos.
With code by Darien Chaffart found at
https://stackoverflow.com/a/61126012/1804252
Example
<html>
<head>
</head>
<body>
<center>
<script src="https://www.youtube.com/iframe_api"></script>
<!-- Insert Livestream Video -->
<iframe id="live-video" src="https://www.youtube.com/embed/live_stream?channel=UCwobzUc3z-0PrFpoRxNszXQ&enablejsapi=1" width="100%" height="100%" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen enablejsapi="1"></iframe>
<!-- Basic API code for Youtube videos -->
<script>
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('live-video', {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady() {
var url = player.getVideoUrl(); /*Use Youtube API to pull Video URL*/
var match = url.match(/[?&]v=([^&]+)/);
var videoId = match[1]; /*Use regex to determine exact Video URL*/
// Insert a new iFrame for the livestream chat after a specific div named chatframe*/
var livevid = document.createElement("iframe");
livevid.src = 'https://www.youtube.com/live_chat?v=' + videoId + ''
livevid.width = '100%';
livevid.height= '100%';
document.getElementById("chatframe").appendChild(livevid);
}
function onPlayerStateChange() {
}
function onPlayerReady(event) {
event.target.playVideo();
}
// The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 90000000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
</center>
</body>
</html>

How to disable seeking with HTML5 video tag ?

I know this is not advisable. But still need this feature to be implemented. Tried everything from onseeking,onseeked to media controller. Nothing worked. Are there any external libraries to disable seeking. would be helpful if some pointers on how to go about using custom controls.
The question is quite old but still relevant so here is my solution:
var video = document.getElementById('video');
var supposedCurrentTime = 0;
video.addEventListener('timeupdate', function() {
if (!video.seeking) {
supposedCurrentTime = video.currentTime;
}
});
// prevent user from seeking
video.addEventListener('seeking', function() {
// guard agains infinite recursion:
// user seeks, seeking is fired, currentTime is modified, seeking is fired, current time is modified, ....
var delta = video.currentTime - supposedCurrentTime;
if (Math.abs(delta) > 0.01) {
console.log("Seeking is disabled");
video.currentTime = supposedCurrentTime;
}
});
// delete the following event handler if rewind is not required
video.addEventListener('ended', function() {
// reset state in order to allow for rewind
supposedCurrentTime = 0;
});
JsFiddle
It is player agnostic, works even when the default controls are shown and cannot be circumvented even by typing code in the console.
Extending the answer from #svetlin-mladenov, you can do the following to prevent the user from seeking any part of the video which has not been watched yet. This will also allow the user to rewind and the seek out any part of the video which had already watched previously.
var timeTracking = {
watchedTime: 0,
currentTime: 0
};
var lastUpdated = 'currentTime';
video.addEventListener('timeupdate', function () {
if (!video.seeking) {
if (video.currentTime > timeTracking.watchedTime) {
timeTracking.watchedTime = video.currentTime;
lastUpdated = 'watchedTime';
}
//tracking time updated after user rewinds
else {
timeTracking.currentTime = video.currentTime;
lastUpdated = 'currentTime';
}
}
});
// prevent user from seeking
video.addEventListener('seeking', function () {
// guard against infinite recursion:
// user seeks, seeking is fired, currentTime is modified, seeking is fired, current time is modified, ....
var delta = video.currentTime - timeTracking.watchedTime;
if (delta > 0) {
video.pause();
//play back from where the user started seeking after rewind or without rewind
video.currentTime = timeTracking[lastUpdated];
video.play();
}
});
You could use an HTML5 video player like video.js and use CSS to hide the seek bar.
Or you could build your own controls for HTML5 video.
Also, the event you're looking for is 'seeking'. As in (with new jquery event binding):
$(myVideoElement).on('seeking', function(){
// do something to stop seeking
})
<!DOCTYPE html>
<html>
<body>
<video controls onseeking="myFunction(this.currentTime)">
<source src="mov_bbb.mp4" type="video/mp4">
<source src="mov_bbb.ogg" type="video/ogg">
Your browser does not support HTML5 video.
</video>
<p>Video courtesy of Big Buck Bunny.</p>
<script>
var currentpos = 0;
function myFunction(time) {
if(time > currentpos) {
video.currentTime = currentpos;
}
}
var video = document.getElementsByTagName('video')[0];
function getpos(){
currentpos = video.currentTime;
}
onesecond = setInterval('getpos()', 1000);
</script>
</body>
</html>
Did the trick for me :)
var supposedCurrentTime = 0;
$("video").on("timeupdate", function() {
if (!this.seeking) {
supposedCurrentTime = this.currentTime;
}
});
// prevent user from seeking
$("video").on('seeking', function() {
// guard agains infinite recursion:
// user seeks, seeking is fired, currentTime is modified, seeking is fired, current time is modified, ....
var delta = this.currentTime - supposedCurrentTime;
if (Math.abs(delta) > 0.01) {
//console.log("Seeking is disabled");
this.currentTime = supposedCurrentTime;
}
});
$("video").on("ended", function() {
// reset state in order to allow for rewind
supposedCurrentTime = 0;
});
To hide all the video controls use this -
document.getElementById("myVideo").controls = false;
Maybe it can help someone, I use this way to remove all the progress control callbacks.
player.controlBar.progressControl.off();
player.controlBar.progressControl.seekBar.off();
Assuming this is for a standard HTML5 video player and with no 3rd party JS library interfering:
This should stop them dead in their tracks, albeit over a decade late for your needs but still useful to others...
V.onseeking=function(){event.preventDefault(); alert('Please don\'t skip the tute!');};
NB: "V" being the ID of your player.
With video js as my video player instead of the vanilla HTML5 version:
.vjs-default-skin .vjs-progress-holder {
height: 100%;
pointer-events: none;
}

HTML5 video error handling

I need to tell, whether video cannot be played ("x" sign is shown in browser).
This code does't works. "onerror" event will never be fired under Firefox
var v = document.getElementsByTagName("video")[0];
if ( v != undefined )
v.onerror = function(e) {
if ( v.networkState == v.NETWORK_NO_SOURCE )
{
// handle error
}
}
What's wrong here ?
"onerror" is not a valid event type for <video>
Use "error" instead.
document.getElementsByTagName('video')[0].addEventListener('error', function(event) { ... }, true);
For a complete list of events for <video> go here: https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox
From Firefox 4 onwards, the 'error' event is dispatched on the <source> element.
And you should add an error handler on the only/last source:
HTML
<video id="vid" controls>
<source src="dynamicsearch.mp4" type="video/mp4"></source>
<source src="otherdynamicsearch.avi" type="video/avi"></source>
</video>
JS
var v = document.querySelector('video#vid');
var sources = v.querySelectorAll('source');
if (sources.length !== 0) {
var lastSource = sources[sources.length-1];
lastSource.addEventListener('error', function() {
alert('uh oh');
});
}
JQuery
$('video source').last().on('error', function() {
alert('uh oh');
});
AngularJS
You can create an error handling directive (or just use ng-error):
<video id="vid" controls>
<source src="dynamicsearch.mp4" type="video/mp4"></source>
<source src="otherdynamicsearch.avi" type="video/avi" ng-error="handleError()"></source>
</video>
Where the error handling directive's link function should do (copied from ng-error):
element.on('error', function(event) {
scope.$apply(function() {
fn(scope, {$event:event});
});
});
It's good to know that Chrome and Firefox have different onerror callbacks. The error must therefore be mapped. Mozilla uses error.originalTarget.
Here is a sample on how to do it with pure JavaScript:
const file = 'https://samples.ffmpeg.org/MPEG-4/MPEGSolution_jurassic.mp4';
window.fetch(file, {mode: 'no-cors'})
.then((response) => response.blob())
.then((blob) => {
const url = window.URL.createObjectURL(blob);
const video = document.createElement('video');
video.addEventListener('error', (event) => {
let error = event;
// Chrome v60
if (event.path && event.path[0]) {
error = event.path[0].error;
}
// Firefox v55
if (event.originalTarget) {
error = error.originalTarget.error;
}
// Here comes the error message
alert(`Video error: ${error.message}`);
window.URL.revokeObjectURL(url);
}, true);
video.src = url;
document.body.appendChild(video);
});
The above example maps an incoming error event into a MediaError which can be used to display an error playback message.
To catch error event, you should use video.addEventListener():
var video = document.createElement('video');
var onError = function() { // your handler};
video.addEventListener('error', onError, true);
...
// remove listener eventually
video.removeEventListener('error', onError, true);
Note that the 3rd parameter of addEventListener (on capture) should be set to true. Error event is typically fired from descendants of video element ( tags).
Anyway, relying on video tag to fire an error event is not the best strategy to detect if video has played. This event is not fired on some android and iOS devices.
The most reliable method, I can think of, is to listen to timeupdate and ended events. If video was playing, you'll get at least 3 timeupdate events. In the case of error, ended will be triggered more reliably than error.
Try adding the event listener to the tag instead - I think the onerror attribute ("error" event) works on the source tag now, not the video tag.
Pug example
video(src= encodeURI(item.urlVideo), type='video/mp4' onerror="myFunction('param',this)")
script(src='/javascripts/onerror.js')
function myFunction(param, me) {
console.log(me);
me.poster = './images/placeholder.jpg'; }