ack-angular-webcam
Version:
Angular2 webcam component. Based on MediaDevices and getUserMedia.js
424 lines • 18.1 kB
JavaScript
"use strict";
//import * as a from './audioTest'
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
var core_1 = require("@angular/core");
var platform_browser_1 = require("@angular/platform-browser");
var videoHelp_1 = require("./videoHelp");
var template = "<video id=\"video\" *ngIf=\"(isSupportUserMedia||isSupportWebRTC)\" autoplay=\"\" playsinline=\"\">Video stream not available</video>";
var WebCamComponent = /** @class */ (function () {
function WebCamComponent(sanitizer, element) {
this.sanitizer = sanitizer;
this.element = element;
this.sets = { element: { width: 0, height: 0 } };
this.mime = 'image/jpeg';
this.useParentWidthHeight = false;
this.success = new core_1.EventEmitter();
this.errorChange = new core_1.EventEmitter();
this.catcher = new core_1.EventEmitter();
console.log("123");
}
WebCamComponent.prototype.ngOnInit = function () {
this.isSupportUserMedia = videoHelp_1.getMedia() != null ? true : false;
this.isSupportUserMedia = false;
this.isSupportWebRTC = !!(videoHelp_1.browser.mediaDevices && videoHelp_1.browser.mediaDevices.getUserMedia);
};
WebCamComponent.prototype.ngAfterViewInit = function () {
var _this = this;
this.applyDefaults();
setTimeout(function () { return _this.afterInitCycles(); }, 0);
};
WebCamComponent.prototype.ngOnChanges = function (changes) {
if (!this.initComplete)
return;
if (changes.facingMode
|| changes.videoDevice
|| changes.videoDeviceId) {
this.redraw(); //restart
}
if (changes.reflect) {
this.applyReflect();
}
};
WebCamComponent.prototype.ngOnDestroy = function () {
this.observer.disconnect();
window.removeEventListener('resize', this.onResize);
this.stop();
};
WebCamComponent.prototype.play = function () {
return this.redraw();
};
WebCamComponent.prototype.stop = function () {
var vid = this.getVideoElm();
if (vid && vid.pause) {
vid.pause();
}
if (this.stream) {
this.stream.getTracks().forEach(function (track) { return track.stop(); });
}
};
WebCamComponent.prototype.redraw = function () {
this.stop();
this.startCapturingVideo();
};
WebCamComponent.prototype.afterInitCycles = function () {
var _this = this;
var media = videoHelp_1.getMedia();
// Older browsers might not implement mediaDevices at all, so we set an empty object first
if ((videoHelp_1.browser.mediaDevices === undefined) && !!media) {
videoHelp_1.browser.mediaDevices = {};
}
// Some browsers partially implement mediaDevices. We can't just assign an object
// with getUserMedia as it would overwrite existing properties.
// Here, we will just add the getUserMedia property if it's missing.
var getUserMediaUndefined = (videoHelp_1.browser.mediaDevices && videoHelp_1.browser.mediaDevices.getUserMedia === undefined) && !!media;
if (getUserMediaUndefined) {
videoHelp_1.browser.mediaDevices.getUserMedia = function (constraints) {
return new Promise(function (resolve, reject) {
var userMedia = media.call(videoHelp_1.browser, constraints, resolve, reject);
if (userMedia.then) {
userMedia.then(function (stream) { return _this.applyStream(stream); });
}
})
.catch(function (err) { return _this.catchError(err); });
};
}
this.initComplete = true;
//deprecated. Use angular hash template referencing and @ViewChild
//setTimeout(()=>this.refChange.emit(this), 0)
this.createVideoResizer();
this.startCapturingVideo()
.then(function () { return setTimeout(function () { return _this.resize(); }, 10); })
.catch(function (err) { return _this.catchError(err); });
};
WebCamComponent.prototype.applyReflect = function () {
var videoElm = this.getVideoElm();
if (!videoElm)
return;
if (this.reflect) {
videoElm.style.transform = "scaleX(-1)";
}
else {
videoElm.style.transform = "scaleX(1)";
}
};
WebCamComponent.prototype.applyStream = function (stream) {
var videoElm = this.getVideoElm();
videoElm.srcObject = stream;
this.applyReflect();
};
WebCamComponent.prototype.createVideoResizer = function () {
var _this = this;
this.observer = new MutationObserver(function () { return _this.resize(); });
var config = {
attributes: true,
childList: true,
characterData: true
//,subtree: true
};
this.observer.observe(this.element.nativeElement, config);
this.onResize = function () { return _this.resize(); };
window.addEventListener('resize', this.onResize);
};
WebCamComponent.prototype.applyDefaults = function () {
this.options = this.options || {};
this.options.fallbackSrc = this.options.fallbackSrc || 'jscam_canvas_only.swf';
this.options.fallbackMode = this.options.fallbackMode || 'callback';
this.options.fallbackQuality = this.options.fallbackQuality || 200;
this.isFallback = this.options.fallback || (!this.isSupportUserMedia && !this.isSupportWebRTC && this.options.fallbackSrc) ? true : false;
if (!this.options.video && !this.options.audio) {
this.options.video = true;
}
};
WebCamComponent.prototype.onWebRTC = function () {
var _this = this;
var promise = Promise.resolve(null);
return this.promiseVideoOptions()
.then(function (options) {
_this.options.video = options;
return _this.setWebcam(_this.options);
});
};
WebCamComponent.prototype.promiseVideoOptions = function () {
var promise = Promise.resolve();
var videoOptions = {};
if (this.options.video && isOb(this.options.video)) {
Object.assign(videoOptions, this.options.video);
/* attempt to prevent bad videoOptions */
if (videoOptions.width && isOb(videoOptions.width) && !Object.keys(videoOptions.width).length) {
delete videoOptions.width;
}
if (videoOptions.height && isOb(videoOptions.height) && !Object.keys(videoOptions.height).length) {
delete videoOptions.height;
}
/* end: fix vid options */
}
if (this.facingMode) {
videoOptions.facingMode = this.facingMode; //{exact:this.facingMode}
}
if (this.videoDeviceId) {
//videoOptions.deviceId = {exact:this.videoDeviceId}
videoOptions.deviceId = this.videoDeviceId;
}
else if (this.videoDevice) {
//videoOptions.deviceId = {exact:this.videoDevice.deviceId}
videoOptions.deviceId = this.videoDevice.deviceId;
}
return promise.then(function () { return videoOptions; });
};
//old method name (deprecated)
WebCamComponent.prototype.resizeVideo = function (maxAttempts) {
if (maxAttempts === void 0) { maxAttempts = 4; }
return this.resize(maxAttempts);
};
WebCamComponent.prototype.resize = function (maxAttempts) {
var _this = this;
if (maxAttempts === void 0) { maxAttempts = 4; }
var video = this.getVideoElm();
if (!video)
return;
video.style.position = 'absolute';
var elm = this.useParentWidthHeight ? this.element.nativeElement.parentNode : this.element.nativeElement;
var width = this.options.width || parseInt(elm.offsetWidth, 10);
var height = this.options.height || parseInt(elm.offsetHeight, 10);
if (!width || !height) {
width = 320;
height = 240;
}
setTimeout(function () {
video.width = width;
video.height = height;
_this.sets.element.width = width;
_this.sets.element.height = height;
video.style.position = 'static';
//now that we set a width and height, it may need another adjustment if it pushed percent based items around
var resizeAgain = (!_this.options.width && width != parseInt(elm.offsetWidth, 10)) || (!_this.options.height && height != parseInt(elm.offsetHeight, 10));
if (resizeAgain && maxAttempts) {
_this.resize(--maxAttempts);
}
}, 1);
};
WebCamComponent.prototype.getVideoDimensions = function (video) {
video = video || this.getVideoElm();
var dim = { width: 0, height: 0 };
if (video.videoWidth) {
dim.width = video.videoWidth;
dim.height = video.videoHeight;
}
else {
dim.width = this.options.width || parseInt(this.element.nativeElement.offsetWidth, 10);
dim.height = this.options.height || parseInt(this.element.nativeElement.offsetHeight, 10);
}
if (!dim.width)
dim.width = 320;
if (!dim.height)
dim.height = 240;
return dim;
};
WebCamComponent.prototype.getVideoElm = function () {
var native = this.element.nativeElement;
var elmType = this.isFallback ? 'object' : 'video';
return native.getElementsByTagName(elmType)[0];
};
WebCamComponent.prototype.setWebcam = function (options) {
var _this = this;
return this.promiseStreamByVidOptions(options)
.then(function (stream) {
_this.applyStream(stream);
_this.processSuccess(stream);
_this.stream = stream;
return stream;
})
.catch(function (err) { return _this.catchError(err); });
};
WebCamComponent.prototype.catchError = function (err) {
this.errorChange.emit(this.error = err);
this.catcher.emit(err);
if (!this.errorChange.observers.length && !this.catcher.observers.length) {
return Promise.reject(err); //if no error subscriptions promise need to continue to be Uncaught
}
};
WebCamComponent.prototype.promiseStreamByVidOptions = function (optionObject) {
return new Promise(function (resolve, reject) {
try {
videoHelp_1.browser.mediaDevices.getUserMedia(optionObject)
.then(function (stream) { return resolve(stream); })
.catch(function (objErr) { return reject(objErr); });
}
catch (e) {
reject(e);
}
});
};
WebCamComponent.prototype.processSuccess = function (stream) {
if (this.isFallback) {
this.setupFallback();
}
else {
this.success.emit(stream);
}
};
/**
* Start capturing video stream
* @returns {void}
*/
WebCamComponent.prototype.startCapturingVideo = function () {
if (!this.isFallback && this.isSupportWebRTC) {
return this.onWebRTC();
}
return Promise.resolve(this.processSuccess());
};
WebCamComponent.prototype.getCanvas = function () {
var canvas = document.createElement('canvas');
var video = this.getVideoElm();
this.setCanvasWidth(canvas, video);
var ctx = canvas.getContext('2d');
if (this.reflect) {
ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
}
ctx.drawImage(video, 0, 0);
return canvas;
};
WebCamComponent.prototype.getBlob = function () {
var _this = this;
return new Promise(function (res, rej) {
var canvas = _this.getCanvas();
canvas.toBlob(function (file) {
res(file);
}, _this.mime, 1);
});
};
WebCamComponent.prototype.getFile = function (fileName) {
return this.getBlob().then(function (file) { return blobToFile(file, fileName); });
};
/** returns promise . @mime - null=png . Also accepts image/jpeg */
WebCamComponent.prototype.getBase64 = function (mime) {
if (this.isFallback) {
return this.flashPlayer.captureBase64(mime || this.mime);
//return this.getFallbackBase64(mime)
}
else {
var canvas = this.getCanvas();
return Promise.resolve(canvas.toDataURL(mime));
}
};
WebCamComponent.prototype.setCanvasWidth = function (canvas, video) {
var di = this.getVideoDimensions(video);
canvas.width = di.width;
canvas.height = di.height;
};
/** older browsers (IE11) cannot dynamically apply most attribute changes to object elements. Use this method during fallback */
WebCamComponent.prototype.createVidElmOb = function () {
var rtnElm = document.createElement('object');
rtnElm.innerHTML = 'Video stream not available';
rtnElm.setAttribute('type', 'application/x-shockwave-flash');
rtnElm.setAttribute('data', this.options.fallbackSrc);
var paramVar = document.createElement('param');
paramVar.setAttribute('name', 'FlashVars');
paramVar.setAttribute('value', 'mode=callback&quality=200');
rtnElm.appendChild(paramVar);
paramVar = document.createElement('param');
paramVar.setAttribute('name', 'allowScriptAccess');
paramVar.setAttribute('value', 'always');
rtnElm.appendChild(paramVar);
paramVar = document.createElement('param');
paramVar.setAttribute('name', 'movie');
paramVar.setAttribute('value', this.options.fallbackSrc);
rtnElm.appendChild(paramVar);
var obs = this.element.nativeElement.getElementsByTagName('object');
if (obs.length) {
this.element.nativeElement.removeChild(obs[0]);
}
this.element.nativeElement.appendChild(rtnElm);
return rtnElm;
};
WebCamComponent.prototype.setupFallback = function () {
this.isFallback = true;
var vidElm = this.getVideoElm() || this.createVidElmOb();
this.flashPlayer = new videoHelp_1.Fallback(vidElm);
};
/** single image to FormData */
WebCamComponent.prototype.captureAsFormData = function (options) {
options = options || {};
return this.getBase64(options.mime)
.then(function (base64) { return videoHelp_1.dataUriToFormData(base64, { fileName: options.fileName }); });
};
WebCamComponent.prototype.dataUriToFormData = function (base64, options) {
return videoHelp_1.dataUriToFormData(base64, { fileName: options.fileName });
};
__decorate([
core_1.Input(),
__metadata("design:type", MediaDeviceInfo)
], WebCamComponent.prototype, "videoDevice", void 0);
__decorate([
core_1.Input(),
__metadata("design:type", String)
], WebCamComponent.prototype, "videoDeviceId", void 0);
__decorate([
core_1.Input(),
__metadata("design:type", Boolean)
], WebCamComponent.prototype, "reflect", void 0);
__decorate([
core_1.Input(),
__metadata("design:type", String)
], WebCamComponent.prototype, "facingMode", void 0);
__decorate([
core_1.Input(),
__metadata("design:type", Object)
], WebCamComponent.prototype, "mime", void 0);
__decorate([
core_1.Input(),
__metadata("design:type", Boolean)
], WebCamComponent.prototype, "useParentWidthHeight", void 0);
__decorate([
core_1.Input(),
__metadata("design:type", Object)
], WebCamComponent.prototype, "options", void 0);
__decorate([
core_1.Output(),
__metadata("design:type", core_1.EventEmitter)
], WebCamComponent.prototype, "success", void 0);
__decorate([
core_1.Input(),
__metadata("design:type", Error)
], WebCamComponent.prototype, "error", void 0);
__decorate([
core_1.Output(),
__metadata("design:type", core_1.EventEmitter)
], WebCamComponent.prototype, "errorChange", void 0);
__decorate([
core_1.Output('catch'),
__metadata("design:type", core_1.EventEmitter)
], WebCamComponent.prototype, "catcher", void 0);
WebCamComponent = __decorate([
core_1.Component({
selector: 'ack-webcam',
template: template
}),
__metadata("design:paramtypes", [platform_browser_1.DomSanitizer,
core_1.ElementRef])
], WebCamComponent);
return WebCamComponent;
}());
exports.WebCamComponent = WebCamComponent;
function isOb(v) {
return typeof (v) === 'object';
}
function blobToFile(theBlob, fileName) {
var b = theBlob;
//A Blob() is almost a File() - it's just missing the two properties below which we will add
b.lastModifiedDate = new Date();
b.name = fileName;
//Cast to a File() type
return theBlob;
}
//# sourceMappingURL=webcam.component.js.map