Webcam support on html5

Hi, I’ve seen some discussions around here about webcam support, including the openfl9 discussion about bringing it to “harder” platforms, besides html5. I was wondering: do we currently have this support for the html5 target?

I’m not sure about current support direct from OpenFL, but this workaround seems to be working: [HTML5] Launch native camera app

Just confirming the behaviour of the solution mentioned by @Confidant here.

This prompts the user to take/select a photo to be supplied to the website. Unfortunately, it’s quite limited to just this functionality.

For our purposes, this wasn’t quite what we were after, so we ended up stepping away from the option.

If that’s the sort of functionality you’re after though, then perfect :wink:

Hi, I found a way to use the webcam that works on my case. Sharing it for reference, but notice that this method won’t let you get the webcam sound, and the frame rate is low… The idea is getting the webcam stream into a video object at the HTML host page, then capturing it on a canvas object. From there you can grab the image source into a BitmapData and show it using a standard Bitmap at your OpenFL stage.

Fisrt, a class I made to extend the Bitmap one to receive the canvas stream:

CanvasWebcam.hx

package;

import haxe.Timer;
import js.html.CanvasElement;
import js.html.Element;
import js.Browser.document;
import openfl.display.Bitmap;
import openfl.display.BitmapData;

/**
 * CanvasWebcam: extends the standard Bitmap to receive a stream from a canvas object at the host HTML page.
 */
class CanvasWebcam extends Bitmap 
{
	/**
	 * the document selector fo the canvas object
	 */
	private var _selector:String;
	
	/**
	 * image recover timer
	 */
	private var _timer:Timer;
	
	/**
	 * reference to the canvas object of the host html page
	 */
	private var _canvas:CanvasElement;
	
	/**
	 * bitmapdata recoverred from the canvas image
	 */
	private var _newBData:BitmapData;

	/**
	 * Constructor.
	 * @param	sel	the canvas object selector for the host HTML page
	 * @param	rate	update framerate in miliseconds
	 * @param	smth	smooth the bitmap?
	 */
	public function new(sel:String, rate:Int = 250, smth:Bool = false) 
	{
		super();
		this.smoothing = smth;
		this._selector = sel;
		this._timer = new Timer(rate);
		this._timer.run = this.getCanvas;
	}
	
	/**
	 * Dispose resources used by the object.
	 */
	public function dispose()
	{
		this._timer.stop();
		this._timer = null;
		this._selector = null;
		this._canvas = null;
		if (this._newBData != null) this._newBData.dispose();
	}
	
	/**
	 * Try to get image from the canvas element.
	 */
	private function getCanvas():Void
	{
		// getting the canvas reference
		if (this._canvas == null) {
			var el:Element = document.querySelector(this._selector);
			if (Std.is(el, CanvasElement)) {
				this._canvas = cast(el, CanvasElement);
			}
		}
		// getting canvas image
		if (this._canvas != null) {
			this._newBData = BitmapData.fromCanvas(this._canvas);
			if (this._newBData != null) this.bitmapData = this._newBData;
		}
	}
	
}

Then, some CSS and JS to add to the host HTML page:

CanvasWebcam.css

#myvideo {
display: none;
}
#mycanvas {
display: none;
}

CanvasWebcam.js

/**
 * vide reference
 */
var cwVideoRef;

/**
 * canvas reference
 */
var cwCanvasRef;

/**
 * interval reference
 */
var cwInterval;

/**
 * Start the webcam capture to the canvas.
 * @param string vdSel the selector for the video object
 * @param string cvSel the selector for the canvas object
 * @param int cpInt the canvas image update interval in miliseconds
 * @return camera capture success (bool)
 */
function cwStartWebcam(vdSel, cvSel, cpInt = 100)
{
	if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
		console.log('Webcam not supported on your browser. Check for permissions. Also, major browsers only allow webcam access from secure domains - if you are running on a test machine, try "localhost" as your testing domain, since it is assumed secure on many browsers for testing purposes.');
		return (false);
	} else {
		cwVideoRef = document.querySelector(vdSel);
		cwCanvasRef = document.querySelector(cvSel);
		if (!cwVideoRef || !cwCanvasRef) {
			console.log("The video or the canvas elements were not found using the provided selector strings.");
			return (false);
		} else {
			// getting webcam feed to video object
			navigator.mediaDevices.getUserMedia({ audio: false, video: true })
				.then(function(stream) {
					if ("srcObject" in cwVideoRef) {
						cwVideoRef.srcObject = stream;
					} else {
						cwVideoRef.src = window.URL.createObjectURL(stream);
					}
					cwVideoRef.onloadedmetadata = function(e) {
						cwVideoRef.play();
					};
				})
				.catch(function(err) {
					console.log(err.name + ": " + err.message);
				});
			// updating the canvas with video content
			cwInterval = setInterval(cwCopyToCanvas, cpInt);
			return (true);
		}
	}
}

/**
 * Copy video object content to canvas.
 */
function cwCopyToCanvas()
{
	cwCanvasRef.getContext('2d').drawImage(cwVideoRef, 0, 0, cwCanvasRef.width, cwCanvasRef.height);
}

/**
 * Stop webcam capture.
 */
function cwStopWebcam()
{
	clearInterval(cwInterval);
	cwVideoRef = null;
	cwCanvasRef = null;
	cwInterval = null;
}

Now, add this to the HTML page (the button will start the camera grab):

<button onclick="cwStartWebcam('#myvideo', '#mycanvas');">Start camera</button>
<video id="myvideo" playsinline muted></video>
<canvas id="mycanvas"></canvas>

Finally, ath the OpenFL code, just create a new CanvasWebcam object:

this.webcam = new CanvasWebcam("#mycanvas");
this.addChild(this.webcam);
2 Likes

a test - click the “start video” at page top

Thanks, bookmarked for future!