UNPKG

react-webcam

Version:
449 lines (440 loc) 19.9 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("react")); else if(typeof define === 'function' && define.amd) define(["react"], factory); else if(typeof exports === 'object') exports["Webcam"] = factory(require("react")); else root["Webcam"] = factory(root["React"]); })(this, function(__WEBPACK_EXTERNAL_MODULE_react__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./src/react-webcam.tsx"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./src/react-webcam.tsx": /*!******************************!*\ !*** ./src/react-webcam.tsx ***! \******************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (undefined && undefined.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __rest = (undefined && undefined.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; // polyfill based on https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia (function polyfillGetUserMedia() { if (typeof window === 'undefined') { return; } // Older browsers might not implement mediaDevices at all, so we set an empty object first if (navigator.mediaDevices === undefined) { navigator.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. if (navigator.mediaDevices.getUserMedia === undefined) { navigator.mediaDevices.getUserMedia = function (constraints) { // First get ahold of the legacy getUserMedia, if present var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; // Some browsers just don't implement it - return a rejected promise with an error // to keep a consistent interface if (!getUserMedia) { return Promise.reject(new Error("getUserMedia is not implemented in this browser")); } // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise return new Promise(function (resolve, reject) { getUserMedia.call(navigator, constraints, resolve, reject); }); }; } })(); function hasGetUserMedia() { return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia); } var Webcam = /** @class */ (function (_super) { __extends(Webcam, _super); function Webcam(props) { var _this = _super.call(this, props) || this; _this.canvas = null; _this.ctx = null; _this.requestUserMediaId = 0; _this.unmounted = false; _this.state = { hasUserMedia: false }; return _this; } Webcam.prototype.componentDidMount = function () { var _a = this, state = _a.state, props = _a.props; this.unmounted = false; if (!hasGetUserMedia()) { props.onUserMediaError("getUserMedia not supported"); return; } if (!state.hasUserMedia) { this.requestUserMedia(); } if (props.children && typeof props.children != 'function') { console.warn("children must be a function"); } }; Webcam.prototype.componentDidUpdate = function (nextProps) { var props = this.props; if (!hasGetUserMedia()) { props.onUserMediaError("getUserMedia not supported"); return; } var audioConstraintsChanged = JSON.stringify(nextProps.audioConstraints) !== JSON.stringify(props.audioConstraints); var videoConstraintsChanged = JSON.stringify(nextProps.videoConstraints) !== JSON.stringify(props.videoConstraints); var minScreenshotWidthChanged = nextProps.minScreenshotWidth !== props.minScreenshotWidth; var minScreenshotHeightChanged = nextProps.minScreenshotHeight !== props.minScreenshotHeight; if (videoConstraintsChanged || minScreenshotWidthChanged || minScreenshotHeightChanged) { this.canvas = null; this.ctx = null; } if (audioConstraintsChanged || videoConstraintsChanged) { this.stopAndCleanup(); this.requestUserMedia(); } }; Webcam.prototype.componentWillUnmount = function () { this.unmounted = true; this.stopAndCleanup(); }; Webcam.stopMediaStream = function (stream) { if (stream) { if (stream.getVideoTracks && stream.getAudioTracks) { stream.getVideoTracks().map(function (track) { stream.removeTrack(track); track.stop(); }); stream.getAudioTracks().map(function (track) { stream.removeTrack(track); track.stop(); }); } else { stream.stop(); } } }; Webcam.prototype.stopAndCleanup = function () { var state = this.state; if (state.hasUserMedia) { Webcam.stopMediaStream(this.stream); if (state.src) { window.URL.revokeObjectURL(state.src); } } }; Webcam.prototype.getScreenshot = function (screenshotDimensions) { var _a = this, state = _a.state, props = _a.props; if (!state.hasUserMedia) return null; var canvas = this.getCanvas(screenshotDimensions); return (canvas && canvas.toDataURL(props.screenshotFormat, props.screenshotQuality)); }; Webcam.prototype.getCanvas = function (screenshotDimensions) { var _a = this, state = _a.state, props = _a.props; if (!this.video) { return null; } if (!state.hasUserMedia || !this.video.videoHeight) return null; if (!this.ctx) { var canvasWidth = this.video.videoWidth; var canvasHeight = this.video.videoHeight; if (!this.props.forceScreenshotSourceSize) { var aspectRatio = canvasWidth / canvasHeight; canvasWidth = props.minScreenshotWidth || this.video.clientWidth; canvasHeight = canvasWidth / aspectRatio; if (props.minScreenshotHeight && canvasHeight < props.minScreenshotHeight) { canvasHeight = props.minScreenshotHeight; canvasWidth = canvasHeight * aspectRatio; } } this.canvas = document.createElement("canvas"); this.canvas.width = (screenshotDimensions === null || screenshotDimensions === void 0 ? void 0 : screenshotDimensions.width) || canvasWidth; this.canvas.height = (screenshotDimensions === null || screenshotDimensions === void 0 ? void 0 : screenshotDimensions.height) || canvasHeight; this.ctx = this.canvas.getContext("2d"); } var _b = this, ctx = _b.ctx, canvas = _b.canvas; if (ctx && canvas) { // adjust the height and width of the canvas to the given dimensions canvas.width = (screenshotDimensions === null || screenshotDimensions === void 0 ? void 0 : screenshotDimensions.width) || canvas.width; canvas.height = (screenshotDimensions === null || screenshotDimensions === void 0 ? void 0 : screenshotDimensions.height) || canvas.height; // mirror the screenshot if (props.mirrored) { ctx.translate(canvas.width, 0); ctx.scale(-1, 1); } ctx.imageSmoothingEnabled = props.imageSmoothing; ctx.drawImage(this.video, 0, 0, (screenshotDimensions === null || screenshotDimensions === void 0 ? void 0 : screenshotDimensions.width) || canvas.width, (screenshotDimensions === null || screenshotDimensions === void 0 ? void 0 : screenshotDimensions.height) || canvas.height); // invert mirroring if (props.mirrored) { ctx.scale(-1, 1); ctx.translate(-canvas.width, 0); } } return canvas; }; Webcam.prototype.requestUserMedia = function () { var _this = this; var props = this.props; var sourceSelected = function (audioConstraints, videoConstraints) { var constraints = { video: typeof videoConstraints !== "undefined" ? videoConstraints : true }; if (props.audio) { constraints.audio = typeof audioConstraints !== "undefined" ? audioConstraints : true; } _this.requestUserMediaId++; var myRequestUserMediaId = _this.requestUserMediaId; navigator.mediaDevices .getUserMedia(constraints) .then(function (stream) { if (_this.unmounted || myRequestUserMediaId !== _this.requestUserMediaId) { Webcam.stopMediaStream(stream); } else { _this.handleUserMedia(null, stream); } }) .catch(function (e) { _this.handleUserMedia(e); }); }; if ("mediaDevices" in navigator) { sourceSelected(props.audioConstraints, props.videoConstraints); } else { var optionalSource_1 = function (id) { return ({ optional: [{ sourceId: id }] }); }; var constraintToSourceId_1 = function (constraint) { var deviceId = constraint.deviceId; if (typeof deviceId === "string") { return deviceId; } if (Array.isArray(deviceId) && deviceId.length > 0) { return deviceId[0]; } if (typeof deviceId === "object" && deviceId.ideal) { return deviceId.ideal; } return null; }; // @ts-ignore: deprecated api MediaStreamTrack.getSources(function (sources) { var audioSource = null; var videoSource = null; sources.forEach(function (source) { if (source.kind === "audio") { audioSource = source.id; } else if (source.kind === "video") { videoSource = source.id; } }); var audioSourceId = constraintToSourceId_1(props.audioConstraints); if (audioSourceId) { audioSource = audioSourceId; } var videoSourceId = constraintToSourceId_1(props.videoConstraints); if (videoSourceId) { videoSource = videoSourceId; } sourceSelected(optionalSource_1(audioSource), optionalSource_1(videoSource)); }); } }; Webcam.prototype.handleUserMedia = function (err, stream) { var props = this.props; if (err || !stream) { this.setState({ hasUserMedia: false }); props.onUserMediaError(err); return; } this.stream = stream; try { if (this.video) { this.video.srcObject = stream; } this.setState({ hasUserMedia: true }); } catch (error) { this.setState({ hasUserMedia: true, src: window.URL.createObjectURL(stream) }); } props.onUserMedia(stream); }; Webcam.prototype.render = function () { var _this = this; var _a = this, state = _a.state, props = _a.props; var audio = props.audio, forceScreenshotSourceSize = props.forceScreenshotSourceSize, disablePictureInPicture = props.disablePictureInPicture, onUserMedia = props.onUserMedia, onUserMediaError = props.onUserMediaError, screenshotFormat = props.screenshotFormat, screenshotQuality = props.screenshotQuality, minScreenshotWidth = props.minScreenshotWidth, minScreenshotHeight = props.minScreenshotHeight, audioConstraints = props.audioConstraints, videoConstraints = props.videoConstraints, imageSmoothing = props.imageSmoothing, mirrored = props.mirrored, _b = props.style, style = _b === void 0 ? {} : _b, children = props.children, rest = __rest(props, ["audio", "forceScreenshotSourceSize", "disablePictureInPicture", "onUserMedia", "onUserMediaError", "screenshotFormat", "screenshotQuality", "minScreenshotWidth", "minScreenshotHeight", "audioConstraints", "videoConstraints", "imageSmoothing", "mirrored", "style", "children"]); var videoStyle = mirrored ? __assign(__assign({}, style), { transform: (style.transform || "") + " scaleX(-1)" }) : style; var childrenProps = { getScreenshot: this.getScreenshot.bind(this), }; return (react__WEBPACK_IMPORTED_MODULE_0__["createElement"](react__WEBPACK_IMPORTED_MODULE_0__["Fragment"], null, react__WEBPACK_IMPORTED_MODULE_0__["createElement"]("video", __assign({ autoPlay: true, disablePictureInPicture: disablePictureInPicture, src: state.src, muted: !audio, playsInline: true, ref: function (ref) { _this.video = ref; }, style: videoStyle }, rest)), children && children(childrenProps))); }; Webcam.defaultProps = { audio: false, disablePictureInPicture: false, forceScreenshotSourceSize: false, imageSmoothing: true, mirrored: false, onUserMedia: function () { return undefined; }, onUserMediaError: function () { return undefined; }, screenshotFormat: "image/webp", screenshotQuality: 0.92, }; return Webcam; }(react__WEBPACK_IMPORTED_MODULE_0__["Component"])); /* harmony default export */ __webpack_exports__["default"] = (Webcam); /***/ }), /***/ "react": /*!**************************************************************************************!*\ !*** external {"root":"React","commonjs2":"react","commonjs":"react","amd":"react"} ***! \**************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE_react__; /***/ }) /******/ })["default"]; }); //# sourceMappingURL=react-webcam.js.map