Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-record-webcam

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-record-webcam - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

80

dist/index.d.ts

@@ -1,1 +0,79 @@

export * from './useRecordWebcam';
declare enum STATUS {
INITIAL = "INITIAL",
CLOSED = "CLOSED",
OPEN = "OPEN",
RECORDING = "RECORDING",
STOPPED = "STOPPED",
ERROR = "ERROR",
PAUSED = "PAUSED"
}
type Status = keyof typeof STATUS;
type Recording = {
id: string;
audioId: string;
audioLabel?: string;
fileName: string;
fileType: string;
isMuted: boolean;
mimeType: string;
objectURL: string | null;
onDataAvailableResolve: Function | null;
onDataAvailablePromise: Promise<void>;
previewRef: React.RefObject<HTMLVideoElement>;
recorder: MediaRecorder | null;
status: Status;
videoId: string;
videoLabel?: string;
webcamRef: React.RefObject<HTMLVideoElement>;
};
type RecordingError = {
recordingId?: string;
error: unknown;
};
type Options = {
fileName: string;
fileType: string;
mimeType: string;
};
type UseRecordWebcam = {
constraints: Partial<MediaTrackConstraints>;
recorderOptions: Partial<MediaRecorderOptions>;
options: Partial<Options>;
};
declare function useRecordWebcam(args?: Partial<UseRecordWebcam>): {
activeRecordings: Recording[];
applyConstraints: (recordingId: string, constraints: MediaTrackConstraints) => Promise<Recording | void>;
applyRecordingOptions: (recordingId: string, options: Options) => Promise<Recording | void>;
cancelRecording: (recordingId: string) => Promise<undefined>;
clearAllRecordings: () => Promise<void>;
clearPreview: (recordingId: string) => Promise<Recording | void>;
closeCamera: (recordingId: string) => Promise<Recording | void>;
createRecording: (videoId?: string, audioId?: string) => Promise<Recording | void>;
devicesById: {
[x: string]: {
label: string;
type: "videoinput" | "audioinput";
};
};
devicesByType: {
video: {
label: string;
deviceId: string;
}[];
audio: {
label: string;
deviceId: string;
}[];
};
download: (recordingId: string) => Promise<void>;
errorMessage: RecordingError | null;
muteRecording: (recordingId: string) => Promise<Recording | void>;
openCamera: (recordingId: string) => Promise<Recording | void>;
pauseRecording: (recordingId: string) => Promise<Recording | void>;
resumeRecording: (recordingId: string) => Promise<Recording | void>;
startRecording: (recordingId: string) => Promise<Recording | void>;
stopRecording: (recordingId: string) => Promise<Recording | void>;
};
export { useRecordWebcam };

@@ -1,2 +0,548 @@

export * from './useRecordWebcam';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxtQkFBbUIsQ0FBQyJ9
import { useMemo, useEffect, useState, useCallback, createRef } from 'react';
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/constants.ts
var DEFAULT_RECORDER_OPTIONS = {
audioBitsPerSecond: 128e3,
videoBitsPerSecond: 25e5,
mimeType: "video/webm;codecs=vp9"
};
var ERROR_MESSAGES = {
BY_ID_NOT_FOUND: "No recording by id found",
SESSION_EXISTS: "Recording session already exists"
};
var DEFAULT_CONSTRAINTS = {
aspectRatio: 1.7,
echoCancellation: true,
height: 720,
width: 1280
};
// src/useRecording.ts
function createRecording({
videoId,
audioId,
videoLabel,
audioLabel
}) {
const recordingId = `${videoId}-${audioId}`;
let onDataAvailableResolve = null;
const onDataAvailablePromise = new Promise((resolve) => {
onDataAvailableResolve = resolve;
});
const recording = {
id: recordingId,
audioId,
audioLabel,
fileName: String((/* @__PURE__ */ new Date()).getTime()),
fileType: "webm",
isMuted: false,
mimeType: "video/webm;codecs=vp9",
objectURL: null,
onDataAvailableResolve,
onDataAvailablePromise,
previewRef: createRef(),
recorder: null,
status: "INITIAL" /* INITIAL */,
videoId,
videoLabel,
webcamRef: createRef()
};
return recording;
}
var recordingMap = /* @__PURE__ */ new Map();
function useRecording(isDevMode) {
const [activeRecordings, setActiveRecordings] = useState([]);
const [errorMessage, setErrorMessage] = useState(null);
const updateActiveRecordings = () => __async(this, null, function* () {
const recordings = Array.from(recordingMap.values());
setActiveRecordings(recordings);
});
const isRecordingCreated = useCallback(
(recordingId) => {
const isCreated = recordingMap.get(recordingId);
return Boolean(isCreated);
},
[recordingMap]
);
const getRecording = useCallback(
(recordingId) => {
const recording = recordingMap.get(recordingId);
if (!recording) {
throw new Error(ERROR_MESSAGES.BY_ID_NOT_FOUND);
}
return recording;
},
[recordingMap]
);
const setRecording = useCallback(
(params) => __async(this, null, function* () {
const recording = createRecording(params);
recordingMap.set(recording.id, recording);
yield updateActiveRecordings();
return recording;
}),
[recordingMap]
);
const updateRecording = useCallback(
(recordingId, updatedValues) => __async(this, null, function* () {
const recording = recordingMap.get(recordingId);
recordingMap.set(recordingId, __spreadValues(__spreadValues({}, recording), updatedValues));
yield updateActiveRecordings();
return getRecording(recordingId);
}),
[recordingMap, setRecording, getRecording]
);
const deleteRecording = useCallback(
(recordingId) => __async(this, null, function* () {
recordingMap.delete(recordingId);
yield updateActiveRecordings();
}),
[recordingMap]
);
const clearAllRecordings = () => __async(this, null, function* () {
Array.from(recordingMap.values()).forEach((recording) => {
var _a;
const stream = (_a = recording.webcamRef.current) == null ? void 0 : _a.srcObject;
if (stream) {
stream.getTracks().forEach((track) => track.stop());
}
});
recordingMap.clear();
setActiveRecordings([]);
});
const handleError = (functionName, error, recordingId) => __async(this, null, function* () {
if (isDevMode) {
console.error(`@${functionName}: `, error);
}
if (recordingId) {
const recording = getRecording(recordingId);
setErrorMessage({ recordingId, error });
if (recording)
recording.status = "ERROR" /* ERROR */;
}
throw error;
});
return {
activeRecordings,
clearAllRecordings,
deleteRecording,
errorMessage,
getRecording,
handleError,
isRecordingCreated,
setRecording,
updateRecording
};
}
function byId(devices) {
return __async(this, null, function* () {
return devices.reduce(
(result, { deviceId, kind, label }) => {
if (kind === "videoinput" || kind === "audioinput") {
result[deviceId] = {
label,
type: kind
};
}
return result;
},
{}
);
});
}
function byType(devices) {
return __async(this, null, function* () {
return devices.reduce(
(result, { deviceId, kind, label }) => {
if (kind === "videoinput") {
result.video.push({ label, deviceId });
}
if (kind === "audioinput") {
result.audio.push({ label, deviceId });
}
return result;
},
{
video: [],
audio: []
}
);
});
}
function getUserPermission() {
return __async(this, null, function* () {
try {
const stream = yield navigator.mediaDevices.getUserMedia({
audio: true,
video: true
});
const mediaDevices = yield navigator.mediaDevices.enumerateDevices();
stream.getTracks().forEach((track) => {
track.stop();
});
return mediaDevices;
} catch (error) {
throw new Error("getUserPermission");
}
});
}
function useDeviceInitialization() {
const { handleError } = useRecording();
const [devicesByType, setDevicesByType] = useState({
video: [],
audio: []
});
const [devicesById, setDevicesById] = useState({});
const [initialDevices, setInitialDevices] = useState({
video: null,
audio: null
});
useEffect(() => {
const initializeDevices = () => __async(this, null, function* () {
try {
const mediaDevices = yield getUserPermission();
const [allById, allByType] = yield Promise.all([
byId(mediaDevices),
byType(mediaDevices)
]);
setDevicesById(allById);
setDevicesByType(allByType);
setInitialDevices({
video: {
deviceId: allByType.video[0].deviceId,
label: allByType.video[0].label
},
audio: {
deviceId: allByType.audio[0].deviceId,
label: allByType.audio[0].deviceId
}
});
} catch (error) {
handleError("initializeDevices", error);
}
});
initializeDevices();
}, []);
return { devicesByType, devicesById, initialDevices };
}
// src/stream.ts
function startStream(videoId, audioId, constraints) {
return __async(this, null, function* () {
const newStream = yield navigator.mediaDevices.getUserMedia({
video: { deviceId: { exact: videoId } },
audio: {
deviceId: { exact: audioId }
}
});
const tracks = newStream.getTracks();
tracks.forEach((track) => track.applyConstraints(constraints));
return newStream;
});
}
// src/useRecordWebcam.ts
function useRecordWebcam(args) {
const { devicesByType, devicesById, initialDevices } = useDeviceInitialization();
const {
activeRecordings,
clearAllRecordings,
deleteRecording,
errorMessage,
getRecording,
handleError,
isRecordingCreated,
setRecording,
updateRecording
} = useRecording();
const constraints = useMemo(
() => __spreadValues(__spreadValues({}, DEFAULT_CONSTRAINTS), args == null ? void 0 : args.constraints),
[args]
);
const recorderOptions = useMemo(
() => __spreadValues(__spreadValues({}, DEFAULT_RECORDER_OPTIONS), args == null ? void 0 : args.recorderOptions),
[args]
);
const createRecording2 = (videoId, audioId) => __async(this, null, function* () {
var _a, _b, _c, _d;
try {
const recordingId = `${videoId}-${audioId}`;
const isCreated = isRecordingCreated(recordingId);
if (isCreated)
throw new Error(ERROR_MESSAGES.SESSION_EXISTS);
const videoLabel = videoId ? devicesById == null ? void 0 : devicesById[videoId].label : (_a = initialDevices.video) == null ? void 0 : _a.label;
const audioLabel = audioId ? devicesById == null ? void 0 : devicesById[audioId].label : (_b = initialDevices.audio) == null ? void 0 : _b.label;
const recording = yield setRecording({
videoId: videoId || ((_c = initialDevices.video) == null ? void 0 : _c.deviceId),
audioId: audioId || ((_d = initialDevices.audio) == null ? void 0 : _d.deviceId),
videoLabel,
audioLabel
});
return recording;
} catch (error) {
handleError("createRecording", error, `${videoId}-${audioId}`);
}
});
const openCamera = (recordingId) => __async(this, null, function* () {
try {
const recording = getRecording(recordingId);
const stream = yield startStream(
recording.videoId,
recording.audioId,
constraints
);
if (recording.webcamRef.current) {
recording.webcamRef.current.srcObject = stream;
yield recording.webcamRef.current.play();
}
recording.status = "OPEN" /* OPEN */;
const updatedRecording = yield updateRecording(recording.id, recording);
return updatedRecording;
} catch (error) {
handleError("openCamera", error);
}
});
const closeCamera = (recordingId) => __async(this, null, function* () {
var _a;
try {
const recording = getRecording(recordingId);
if (recording.webcamRef.current) {
const stream = recording.webcamRef.current.srcObject;
stream == null ? void 0 : stream.getTracks().forEach((track) => track.stop());
((_a = recording.recorder) == null ? void 0 : _a.ondataavailable) && (recording.recorder.ondataavailable = null);
recording.webcamRef.current.srcObject = null;
recording.webcamRef.current.load();
}
recording.status = "CLOSED" /* CLOSED */;
const updatedRecording = yield updateRecording(recording.id, recording);
return updatedRecording;
} catch (error) {
handleError("closeCamera", error, recordingId);
}
});
const startRecording = (recordingId) => __async(this, null, function* () {
var _a;
try {
const recording = getRecording(recordingId);
const stream = (_a = recording.webcamRef.current) == null ? void 0 : _a.srcObject;
recording.recorder = new MediaRecorder(stream, recorderOptions);
recording.recorder.ondataavailable = (event) => __async(this, null, function* () {
var _a2, _b;
if (event.data.size) {
const blob = new Blob([event.data], {
type: `video/${((_a2 = args == null ? void 0 : args.options) == null ? void 0 : _a2.mimeType) || recording.mimeType}`
});
const url = URL.createObjectURL(blob);
recording.objectURL = url;
if (recording.previewRef.current)
recording.previewRef.current.src = url;
recording.status = "STOPPED" /* STOPPED */;
yield updateRecording(recording.id, recording);
(_b = recording.onDataAvailableResolve) == null ? void 0 : _b.call(recording);
}
});
recording.recorder.start();
recording.status = "RECORDING" /* RECORDING */;
const updatedRecording = yield updateRecording(recording.id, recording);
return updatedRecording;
} catch (error) {
handleError("startRecording", error, recordingId);
}
});
const pauseRecording = (recordingId) => __async(this, null, function* () {
var _a;
try {
const recording = getRecording(recordingId);
(_a = recording.recorder) == null ? void 0 : _a.pause();
recording.status = "PAUSED" /* PAUSED */;
const updatedRecording = yield updateRecording(recording.id, recording);
return updatedRecording;
} catch (error) {
handleError("pauseRecording", error, recordingId);
}
});
const resumeRecording = (recordingId) => __async(this, null, function* () {
var _a;
try {
const recording = getRecording(recordingId);
(_a = recording.recorder) == null ? void 0 : _a.resume();
recording.status = "RECORDING" /* RECORDING */;
const updatedRecording = yield updateRecording(recording.id, recording);
return updatedRecording;
} catch (error) {
handleError("resumeRecording", error, recordingId);
}
});
const stopRecording = (recordingId) => __async(this, null, function* () {
var _a;
try {
let recording = getRecording(recordingId);
(_a = recording.recorder) == null ? void 0 : _a.stop();
yield recording.onDataAvailablePromise;
recording = getRecording(recordingId);
recording.status = "STOPPED" /* STOPPED */;
const updatedRecording = yield updateRecording(recording.id, recording);
return updatedRecording;
} catch (error) {
handleError("stopRecording", error, recordingId);
}
});
const cancelRecording = (recordingId) => __async(this, null, function* () {
var _a, _b, _c;
try {
const recording = getRecording(recordingId);
const tracks = (_a = recording == null ? void 0 : recording.recorder) == null ? void 0 : _a.stream.getTracks();
(_b = recording == null ? void 0 : recording.recorder) == null ? void 0 : _b.stop();
tracks == null ? void 0 : tracks.forEach((track) => track.stop());
((_c = recording.recorder) == null ? void 0 : _c.ondataavailable) && (recording.recorder.ondataavailable = null);
if (recording.webcamRef.current) {
const stream = recording.webcamRef.current.srcObject;
stream == null ? void 0 : stream.getTracks().forEach((track) => track.stop());
recording.webcamRef.current.srcObject = null;
recording.webcamRef.current.load();
}
URL.revokeObjectURL(recording.objectURL);
recording.status = "INITIAL" /* INITIAL */;
const updatedRecording = yield updateRecording(recording.id, recording);
yield deleteRecording(updatedRecording.id);
} catch (error) {
handleError("cancelRecording", error, recordingId);
}
});
const clearPreview = (recordingId) => __async(this, null, function* () {
try {
const recording = getRecording(recordingId);
if (recording.previewRef.current)
recording.previewRef.current.src = "";
recording.status = "INITIAL" /* INITIAL */;
URL.revokeObjectURL(recording.objectURL);
const updatedRecording = yield updateRecording(recording.id, recording);
return updatedRecording;
} catch (error) {
handleError("clearPreview", error, recordingId);
}
});
const muteRecording = (recordingId) => __async(this, null, function* () {
var _a;
try {
const recording = getRecording(recordingId);
(_a = recording.recorder) == null ? void 0 : _a.stream.getAudioTracks().forEach((track) => {
track.enabled = !track.enabled;
});
recording.isMuted = !recording.isMuted;
const updatedRecording = yield updateRecording(recording.id, recording);
return updatedRecording;
} catch (error) {
handleError("muteRecording", error, recordingId);
}
});
const download = (recordingId) => __async(this, null, function* () {
var _a, _b;
try {
const recording = getRecording(recordingId);
const downloadElement = document.createElement("a");
if (recording == null ? void 0 : recording.objectURL) {
downloadElement.href = recording.objectURL;
}
downloadElement.download = `${((_a = args == null ? void 0 : args.options) == null ? void 0 : _a.fileName) || recording.fileName}.${((_b = args == null ? void 0 : args.options) == null ? void 0 : _b.fileType) || recording.fileType}`;
downloadElement.click();
} catch (error) {
handleError("download", error, recordingId);
}
});
const applyConstraints = (recordingId, constraints2) => __async(this, null, function* () {
var _a, _b;
try {
const recording = getRecording(recordingId);
if ((_a = recording.webcamRef.current) == null ? void 0 : _a.srcObject) {
const stream = (_b = recording.webcamRef.current) == null ? void 0 : _b.srcObject;
const tracks = stream.getTracks() || [];
tracks == null ? void 0 : tracks.forEach((track) => {
track.applyConstraints(__spreadValues({}, constraints2));
});
}
return recording;
} catch (error) {
handleError("applyConstraints", error, recordingId);
}
});
const applyRecordingOptions = (recordingId, options) => __async(this, null, function* () {
try {
const recording = getRecording(recordingId);
if (options.fileName) {
recording.fileName = options.fileName;
}
if (options.fileType) {
recording.fileType = options.fileType;
}
const updatedRecording = yield updateRecording(recording.id, recording);
return updatedRecording;
} catch (error) {
handleError("applyRecordingOptions", error, recordingId);
}
});
useEffect(() => {
return () => {
clearAllRecordings();
};
}, []);
return {
activeRecordings,
applyConstraints,
applyRecordingOptions,
cancelRecording,
clearAllRecordings,
clearPreview,
closeCamera,
createRecording: createRecording2,
devicesById,
devicesByType,
download,
errorMessage,
muteRecording,
openCamera,
pauseRecording,
resumeRecording,
startRecording,
stopRecording
};
}
export { useRecordWebcam };

21

package.json
{
"name": "react-record-webcam",
"description": "Webcam recording tool for React",
"version": "1.0.0",
"version": "1.0.1",
"main": "dist/index.js",
"files": [
"dist"
"dist",
"README.md",
"LICENSE"
],

@@ -14,20 +16,25 @@ "types": "dist/index.d.ts",

"peerDependencies": {
"react": "*"
"react": "^16.3 || ^17.0 || ^18.0"
},
"scripts": {
"start": "rm -rf ./dist && tsc --watch",
"build": "rm -rf ./dist && tsc"
"build": "tsup"
},
"keywords": [
"react",
"record",
"webcam",
"multi",
"recording",
"concurrent",
"simultaneous",
"record",
"recording",
"hook",
"video",
"audio"
]
],
"sideEffects": false,
"type": "module",
"exports": {
".": "./dist/index.js"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc