react-record-webcam
Advanced tools
Comparing version 0.0.5 to 0.0.6
@@ -1,92 +0,3 @@ | ||
import React from 'react'; | ||
import { RecorderOptions, Recorder, CAMERA_STATUS, BUTTON_LABELS, NAMESPACES } from './types'; | ||
declare type RenderControlsArgs = { | ||
isWebcamOn: boolean; | ||
isRecording: boolean; | ||
isPreview: boolean; | ||
openCamera: () => void; | ||
closeCamera: () => void; | ||
start: () => void; | ||
stop: () => void; | ||
retake: () => void; | ||
download: () => void; | ||
status: string; | ||
}; | ||
declare type RecordRtcProps = { | ||
cssNamespace?: string; | ||
downloadFileName?: string; | ||
getStatus?(status: string): void; | ||
options?: RecorderOptions; | ||
recordingLength?: number; | ||
render?({}: RenderControlsArgs): void; | ||
statusMessages?: { | ||
INIT: string | CAMERA_STATUS.INIT; | ||
CLOSED: string | CAMERA_STATUS.CLOSED; | ||
OPEN: string | CAMERA_STATUS.OPEN; | ||
RECORDING: string | CAMERA_STATUS.RECORDING; | ||
PREVIEW: string | CAMERA_STATUS.PREVIEW; | ||
ERROR: string | CAMERA_STATUS.ERROR; | ||
}; | ||
controlLabels?: { | ||
CLOSE: string | BUTTON_LABELS.CLOSE; | ||
DOWNLOAD: string | BUTTON_LABELS.DOWNLOAD; | ||
OPEN: string | BUTTON_LABELS.OPEN; | ||
RETAKE: string | BUTTON_LABELS.RETAKE; | ||
START: string | BUTTON_LABELS.START; | ||
STOP: string | BUTTON_LABELS.STOP; | ||
}; | ||
}; | ||
declare type RecordRtcState = { | ||
isPreview: boolean; | ||
isWebcamOn: boolean; | ||
isRecording: boolean; | ||
status: string; | ||
}; | ||
declare class RecordRtc extends React.PureComponent<RecordRtcProps, RecordRtcState> { | ||
constructor(props: RecordRtcProps); | ||
state: { | ||
status: string; | ||
isPreview: boolean; | ||
isWebcamOn: boolean; | ||
isRecording: boolean; | ||
}; | ||
recorder: Recorder; | ||
recorderOptions: { | ||
type: "video" | "audio"; | ||
mimeType: "video/mp4" | "audio/webm" | "video/webm;codecs=vp9" | "video/webm;codecs=vp8" | "video/webm;codecs=h264"; | ||
video: { | ||
minWidth: number; | ||
minHeight: number; | ||
maxWidth: number; | ||
maxHeight: number; | ||
minAspectRatio: number; | ||
}; | ||
} | { | ||
type: "video" | "audio"; | ||
mimeType: "video/mp4" | "audio/webm" | "video/webm;codecs=vp9" | "video/webm;codecs=vp8" | "video/webm;codecs=h264"; | ||
video: { | ||
minWidth: number; | ||
minHeight: number; | ||
maxWidth: number; | ||
maxHeight: number; | ||
minAspectRatio: number; | ||
}; | ||
}; | ||
webcamRef: React.RefObject<HTMLVideoElement>; | ||
previewRef: React.RefObject<HTMLVideoElement>; | ||
static defaultProps: { | ||
cssNamespace: NAMESPACES; | ||
}; | ||
componentDidUpdate(prevProps: RecordRtcProps, prevState: RecordRtcState): void; | ||
openCamera(): Promise<void>; | ||
closeCamera(): void; | ||
handleCloseCamera(): void; | ||
handleOpenCamera(): Promise<void>; | ||
handleStartRecording(): Promise<void>; | ||
handleStopRecording(): Promise<void>; | ||
handleRetakeRecording(): Promise<void>; | ||
download(): Promise<void>; | ||
handleError(error: Error): void; | ||
render(): JSX.Element; | ||
} | ||
export default RecordRtc; | ||
export * from './RecordWebcam'; | ||
export * from './useRecordWebcam'; | ||
export * from './types'; |
"use strict"; | ||
var __extends = (this && this.__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 = (this && this.__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 __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
exports.__esModule = true; | ||
var react_1 = __importDefault(require("react")); | ||
var Video_1 = __importDefault(require("./Video")); | ||
var Controls_1 = __importDefault(require("./Controls")); | ||
var record_1 = __importDefault(require("./record")); | ||
var types_1 = require("./types"); | ||
var utils_1 = require("./utils"); | ||
var RECORDER_OPTIONS = Object.freeze({ | ||
type: 'video', | ||
mimeType: 'video/mp4', | ||
video: { | ||
minWidth: 1280, | ||
minHeight: 720, | ||
maxWidth: 1920, | ||
maxHeight: 1080, | ||
minAspectRatio: 1.77 | ||
} | ||
}); | ||
var initialState = Object.freeze({ | ||
isPreview: false, | ||
isWebcamOn: false, | ||
isRecording: false, | ||
status: types_1.CAMERA_STATUS.CLOSED | ||
}); | ||
var RecordRtc = /** @class */ (function (_super) { | ||
__extends(RecordRtc, _super); | ||
function RecordRtc(props) { | ||
var _a; | ||
var _this = _super.call(this, props) || this; | ||
_this.state = __assign(__assign({}, initialState), { status: ((_a = _this.props.statusMessages) === null || _a === void 0 ? void 0 : _a.CLOSED) || initialState.status }); | ||
_this.recorderOptions = __assign(__assign({}, RECORDER_OPTIONS), _this.props.options); | ||
_this.webcamRef = react_1["default"].createRef(); | ||
_this.previewRef = react_1["default"].createRef(); | ||
_this.closeCamera = _this.closeCamera.bind(_this); | ||
_this.download = _this.download.bind(_this); | ||
_this.handleOpenCamera = _this.handleOpenCamera.bind(_this); | ||
_this.handleError = _this.handleError.bind(_this); | ||
_this.handleCloseCamera = _this.handleCloseCamera.bind(_this); | ||
_this.handleRetakeRecording = _this.handleRetakeRecording.bind(_this); | ||
_this.handleStartRecording = _this.handleStartRecording.bind(_this); | ||
_this.handleStopRecording = _this.handleStopRecording.bind(_this); | ||
_this.openCamera = _this.openCamera.bind(_this); | ||
return _this; | ||
} | ||
RecordRtc.prototype.componentDidUpdate = function (prevProps, prevState) { | ||
if (this.state.status !== prevState.status) { | ||
if (this.props.getStatus) | ||
this.props.getStatus(this.state.status); | ||
} | ||
}; | ||
RecordRtc.prototype.openCamera = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var recordrtc; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, record_1["default"](this.recorderOptions)]; | ||
case 1: | ||
recordrtc = _a.sent(); | ||
this.recorder = recordrtc; | ||
if (this.webcamRef.current) { | ||
this.webcamRef.current.srcObject = recordrtc.stream; | ||
} | ||
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 1700); })]; | ||
case 2: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RecordRtc.prototype.closeCamera = function () { | ||
if (this.recorder.stream.id) | ||
this.recorder.stream.stop(); | ||
}; | ||
RecordRtc.prototype.handleCloseCamera = function () { | ||
if (this.previewRef.current) { | ||
this.previewRef.current.removeAttribute('src'); | ||
this.previewRef.current.load(); | ||
} | ||
this.setState(__assign({}, initialState)); | ||
this.closeCamera(); | ||
}; | ||
RecordRtc.prototype.handleOpenCamera = function () { | ||
var _a, _b; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var error_1; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
_c.trys.push([0, 2, , 3]); | ||
this.setState(__assign(__assign({}, initialState), { isWebcamOn: true, status: ((_a = this.props.statusMessages) === null || _a === void 0 ? void 0 : _a.INIT) || types_1.CAMERA_STATUS.INIT })); | ||
return [4 /*yield*/, this.openCamera()]; | ||
case 1: | ||
_c.sent(); | ||
this.setState({ | ||
status: ((_b = this.props.statusMessages) === null || _b === void 0 ? void 0 : _b.OPEN) || types_1.CAMERA_STATUS.OPEN | ||
}); | ||
return [3 /*break*/, 3]; | ||
case 2: | ||
error_1 = _c.sent(); | ||
this.handleError(error_1); | ||
return [3 /*break*/, 3]; | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RecordRtc.prototype.handleStartRecording = function () { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var length_1, error_2; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_b.trys.push([0, 5, , 6]); | ||
return [4 /*yield*/, this.recorder.startRecording()]; | ||
case 1: | ||
_b.sent(); | ||
this.setState(__assign(__assign({}, initialState), { isRecording: true, isWebcamOn: true, status: ((_a = this.props.statusMessages) === null || _a === void 0 ? void 0 : _a.RECORDING) || types_1.CAMERA_STATUS.RECORDING })); | ||
if (!this.props.recordingLength) return [3 /*break*/, 4]; | ||
length_1 = this.props.recordingLength * 1000; | ||
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, length_1); })]; | ||
case 2: | ||
_b.sent(); | ||
return [4 /*yield*/, this.handleStopRecording()]; | ||
case 3: | ||
_b.sent(); | ||
this.closeCamera(); | ||
_b.label = 4; | ||
case 4: return [3 /*break*/, 6]; | ||
case 5: | ||
error_2 = _b.sent(); | ||
this.handleError(error_2); | ||
return [3 /*break*/, 6]; | ||
case 6: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RecordRtc.prototype.handleStopRecording = function () { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var blob, preview, error_3; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_b.trys.push([0, 3, , 4]); | ||
return [4 /*yield*/, this.recorder.stopRecording()]; | ||
case 1: | ||
_b.sent(); | ||
return [4 /*yield*/, this.recorder.getBlob()]; | ||
case 2: | ||
blob = _b.sent(); | ||
preview = window.URL.createObjectURL(blob); | ||
if (this.previewRef.current) { | ||
this.previewRef.current.src = preview; | ||
} | ||
this.closeCamera(); | ||
this.setState(__assign(__assign({}, initialState), { isWebcamOn: false, isPreview: true, status: ((_a = this.props.statusMessages) === null || _a === void 0 ? void 0 : _a.PREVIEW) || types_1.CAMERA_STATUS.PREVIEW })); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
error_3 = _b.sent(); | ||
this.handleError(error_3); | ||
return [3 /*break*/, 4]; | ||
case 4: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RecordRtc.prototype.handleRetakeRecording = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var error_4; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4 /*yield*/, this.handleOpenCamera()]; | ||
case 1: | ||
_a.sent(); | ||
return [3 /*break*/, 3]; | ||
case 2: | ||
error_4 = _a.sent(); | ||
this.handleError(error_4); | ||
return [3 /*break*/, 3]; | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RecordRtc.prototype.download = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var blob, filename, error_5; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4 /*yield*/, this.recorder.getBlob()]; | ||
case 1: | ||
blob = _a.sent(); | ||
filename = this.props.downloadFileName | ||
? this.props.downloadFileName + ".mp4" | ||
: new Date().getTime() + ".mp4"; | ||
utils_1.saveFile(filename, blob); | ||
return [3 /*break*/, 3]; | ||
case 2: | ||
error_5 = _a.sent(); | ||
this.handleError(error_5); | ||
return [3 /*break*/, 3]; | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
RecordRtc.prototype.handleError = function (error) { | ||
var _a; | ||
this.setState(__assign(__assign({}, initialState), { status: ((_a = this.props.statusMessages) === null || _a === void 0 ? void 0 : _a.ERROR) || types_1.CAMERA_STATUS.ERROR })); | ||
console.error({ error: error }); | ||
}; | ||
RecordRtc.prototype.render = function () { | ||
return (react_1["default"].createElement(react_1["default"].Fragment, null, | ||
react_1["default"].createElement("style", null, "\n ." + this.props.cssNamespace + "__wrapper {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-flow: column nowrap;\n flex-flow: column nowrap;\n -webkit-box-pack: justify;\n -ms-flex-pack: justify;\n justify-content: space-between;\n }\n ." + this.props.cssNamespace + "__status {\n margin: 1rem 0;\n }\n "), | ||
react_1["default"].createElement("div", { className: this.props.cssNamespace + "__wrapper}" }, | ||
react_1["default"].createElement(Video_1["default"], { cssNamespace: this.props.cssNamespace, style: { display: "" + (this.state.isWebcamOn ? 'block' : 'none') }, autoPlay: true, muted: true, loop: true, ref: this.webcamRef }), | ||
react_1["default"].createElement(Video_1["default"], { cssNamespace: this.props.cssNamespace, style: { display: "" + (this.state.isPreview ? 'block' : 'none') }, autoPlay: true, muted: true, loop: true, ref: this.previewRef }), | ||
this.props.render && | ||
this.props.render({ | ||
isWebcamOn: this.state.isWebcamOn, | ||
isRecording: this.state.isRecording, | ||
isPreview: this.state.isPreview, | ||
openCamera: this.handleOpenCamera, | ||
closeCamera: this.handleCloseCamera, | ||
start: this.handleStartRecording, | ||
stop: this.handleStopRecording, | ||
retake: this.handleRetakeRecording, | ||
download: this.download, | ||
status: this.state.status | ||
}), | ||
!this.props.render && (react_1["default"].createElement("div", { className: this.props.cssNamespace + "__status" }, "Status: " + this.state.status)), | ||
!this.props.render && (react_1["default"].createElement(Controls_1["default"], { cssNamespace: this.props.cssNamespace, openCamera: this.handleOpenCamera, closeCamera: this.handleCloseCamera, start: this.handleStartRecording, stop: this.handleStopRecording, retake: this.handleRetakeRecording, download: this.download, labels: this.props.controlLabels, showOpenCamera: !this.state.isWebcamOn && | ||
!this.state.isRecording && | ||
!this.state.isPreview, showCloseCamera: this.state.isWebcamOn, showStart: this.state.isWebcamOn && | ||
!this.state.isRecording && | ||
!this.state.isPreview, showStop: this.state.isRecording, showRetake: this.state.isPreview, showDownload: this.state.isPreview }))))); | ||
}; | ||
RecordRtc.defaultProps = { | ||
cssNamespace: types_1.NAMESPACES.CSS | ||
}; | ||
return RecordRtc; | ||
}(react_1["default"].PureComponent)); | ||
exports["default"] = RecordRtc; | ||
__exportStar(require("./RecordWebcam"), exports); | ||
__exportStar(require("./useRecordWebcam"), exports); | ||
__exportStar(require("./types"), exports); | ||
//# sourceMappingURL=index.js.map |
import { RecorderOptions, Recorder } from './types'; | ||
declare type CaptureUserMedia = { | ||
stream: MediaStream; | ||
recordRtc: Recorder; | ||
recordRtc: any; | ||
}; | ||
@@ -6,0 +6,0 @@ declare function captureUserMedia(options: RecorderOptions): Promise<CaptureUserMedia>; |
@@ -50,2 +50,3 @@ "use strict"; | ||
exports.__esModule = true; | ||
exports.captureUserMedia = void 0; | ||
// @ts-ignore | ||
@@ -52,0 +53,0 @@ var recordrtc_1 = require("recordrtc"); |
@@ -19,11 +19,11 @@ declare type RecordingType = 'video' | 'audio'; | ||
getBlob(): Promise<Blob>; | ||
stream: MediaStream; | ||
stream: any; | ||
}; | ||
export declare enum CAMERA_STATUS { | ||
INIT = "Starting camera ...", | ||
CLOSED = "Camera is closed", | ||
OPEN = "Camera is open", | ||
RECORDING = "Recording ...", | ||
PREVIEW = "Preview", | ||
ERROR = "Error" | ||
INIT = "INIT", | ||
CLOSED = "CLOSED", | ||
OPEN = "OPEN", | ||
RECORDING = "RECORDING", | ||
PREVIEW = "PREVIEW", | ||
ERROR = "ERROR" | ||
} | ||
@@ -30,0 +30,0 @@ export declare enum BUTTON_LABELS { |
"use strict"; | ||
exports.__esModule = true; | ||
exports.NAMESPACES = exports.BUTTON_LABELS = exports.CAMERA_STATUS = void 0; | ||
var CAMERA_STATUS; | ||
(function (CAMERA_STATUS) { | ||
CAMERA_STATUS["INIT"] = "Starting camera ..."; | ||
CAMERA_STATUS["CLOSED"] = "Camera is closed"; | ||
CAMERA_STATUS["OPEN"] = "Camera is open"; | ||
CAMERA_STATUS["RECORDING"] = "Recording ..."; | ||
CAMERA_STATUS["PREVIEW"] = "Preview"; | ||
CAMERA_STATUS["ERROR"] = "Error"; | ||
CAMERA_STATUS["INIT"] = "INIT"; | ||
CAMERA_STATUS["CLOSED"] = "CLOSED"; | ||
CAMERA_STATUS["OPEN"] = "OPEN"; | ||
CAMERA_STATUS["RECORDING"] = "RECORDING"; | ||
CAMERA_STATUS["PREVIEW"] = "PREVIEW"; | ||
CAMERA_STATUS["ERROR"] = "ERROR"; | ||
})(CAMERA_STATUS = exports.CAMERA_STATUS || (exports.CAMERA_STATUS = {})); | ||
@@ -12,0 +13,0 @@ var BUTTON_LABELS; |
"use strict"; | ||
exports.__esModule = true; | ||
exports.saveFile = void 0; | ||
exports.saveFile = function (filename, blob) { | ||
@@ -4,0 +5,0 @@ if (window.navigator.msSaveOrOpenBlob !== undefined) { |
{ | ||
"name": "react-record-webcam", | ||
"description": "A React webcam component 🎬📹", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"main": "dist/index.js", | ||
@@ -13,3 +13,3 @@ "files": [ | ||
"dependencies": { | ||
"recordrtc": "^5.5.8" | ||
"recordrtc": "^5.6.1" | ||
}, | ||
@@ -16,0 +16,0 @@ "peerDependencies": { |
107
README.md
@@ -5,29 +5,109 @@ <div align="center"> | ||
[![Build Status](https://travis-ci.org/samuelweckstrom/react-record-webcam.svg?branch=master)](https://travis-ci.org/samuelweckstrom/react-record-webcam) | ||
[![TypeScript](https://badges.frapsoft.com/typescript/code/typescript.svg?v=101)](https://github.com/ellerbrock/typescript-badges/) | ||
Webcam video and audio recording component for React. Uses classes so all React versions are supported. Works in all latest browser versions, although Safari requires MediaRecorder to be enabled in the experimental features. | ||
Webcam video and audio recording hook and component for React. Use hook for newer React versions, component uses classes so all React versions are supported. Works in all latest browser versions, although Safari requires MediaRecorder to be enabled in the experimental features. | ||
[Demo](https://codesandbox.io/s/react-record-webcam-demo-zog8c?file=/src/App.tsx) | ||
## How to | ||
<br> | ||
### Install | ||
## Install dependency | ||
``` | ||
yarn add react-record-webcam | ||
``` | ||
<br> | ||
### Use | ||
## Hook | ||
``` | ||
import Webcam from 'react-record-webcam' | ||
import { useRecordWebcam } from 'react-record-webcam' | ||
function RecordVideo(props) { | ||
const recordWebcam = useRecordWebcam(); | ||
return ( | ||
<div> | ||
<p>Camera status: {recordWebcam.status}</p> | ||
<button onClick={recordWebcam.open}>Open camera</button> | ||
<button onClick={recordWebcam.start}>Start recording</button> | ||
<button onClick={recordWebcam.stop}>Stop recording</button> | ||
<button onClick={recordWebcam.retake}>Retake recording</button> | ||
<button onClick={recordWebcam.download}>Download recording</button> | ||
<video ref={recordWebcam.webcamRef} autoPlay muted /> | ||
<video ref={recordWebcam.previewRef} autoPlay muted loop /> | ||
</div> | ||
) | ||
} | ||
``` | ||
Import the hook and initialize it in your function. The hook returns refs for both preview and recording video elements, functions to control recording (open, start, stop, retake, download) and camera status. | ||
``` | ||
import { useRecordWebcam, CAMERA_STATUS } from 'react-record-webcam' | ||
``` | ||
You can also import the `CAMERA_STATUS` constant to check for different states and toggle your UI accordingly. Check the CodeSandbox [demo](https://codesandbox.io/s/react-record-webcam-demo-zog8c?file=/src/App.tsx) for a more thorough example on how to do this. | ||
Passing options: | ||
``` | ||
const OPTIONS = { ... } | ||
const recordWebcam = useRecordWebcam(OPTIONS); | ||
``` | ||
| Option || | ||
| ------------- | ------------- | | ||
|`downloadFileName?: string` |Set a namespace for the component CSS classes| | ||
|`recordingLength?: number` |Length of recording in seconds| | ||
|`recordingLength: number` |Set max recording length in seconds | | ||
|`namespace: string` |Pass own CSS namespace| | ||
|`options: RecorderOptions` |Options for recording video| | ||
| |`type: video |audio`| | ||
| |`mimeType: video/mp4 | audio/webm | video/webm;codecs=vp9 | video/webm;codecs=vp8 | video/webm;codecs=h264` | ||
| |`video: { minWidth, minHeight, maxWidth, maxHeight, minAspectRatio }` | ||
<br> | ||
## Component | ||
``` | ||
import { RecordWebcam } from 'react-record-webcam' | ||
... | ||
<Webcam /> | ||
function RecordVideo(props) { | ||
return ( | ||
<RecordWebcam /> | ||
) | ||
} | ||
``` | ||
You can include the component as is and it will render controls, video and preview elements. Alternatively you can use the render prop for more control: | ||
### Styling | ||
``` | ||
function RecordVideo(props) { | ||
return ( | ||
<RecordWebcam | ||
render={(props: WebcamRenderProps) => { | ||
return ( | ||
<div> | ||
<h1>Component render prop demo</h1> | ||
<p>Camera status: {props.status}</p> | ||
<div> | ||
<button onClick={props.openCamera}>Open camera</button> | ||
<button onClick={props.retake}>Retake</button> | ||
<button onClick={props.start}>Start recording</button> | ||
<button onClick={props.stop}>Stop recording</button> | ||
<button onClick={props.download}>Download</button> | ||
</div> | ||
</div> | ||
); | ||
}} | ||
/> | ||
) | ||
} | ||
``` | ||
<br> | ||
You can use the below default class names or pass your own namespace to replace the default `react-record-webcam`. | ||
@@ -43,7 +123,8 @@ | ||
### Props | ||
| Prop | Example | | ||
<br> | ||
|Prop|| | ||
| ------------- | ------------- | | ||
| `cssNamespace: string` |Set a namespace for the component CSS classes| | ||
|`cssNamespace: string` |Set a namespace for the component CSS classes| | ||
|`downloadFileName: string` |Filename for video download | | ||
@@ -57,4 +138,2 @@ |`getStatus` |Callback to get webcam status | | ||
||`video: { minWidth, minHeight, maxWidth, maxHeight, minAspectRatio }` | ||
|`statusMessages: object` |Pass own status messages to recorder| | ||
||`{ INIT, CLOSED, OPEN, RECORDING, PREVIEW, ERROR }` | ||
|`controlLabels: object`|Pass custom labels to control buttons| | ||
@@ -61,0 +140,0 @@ || `{ CLOSE, DOWNLOAD, OPEN, RETAKE, START, STOP }` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
64049
26
918
150
1
Updatedrecordrtc@^5.6.1