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

react-hook-recorder

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-hook-recorder - npm Package Compare versions

Comparing version 0.0.8 to 0.0.9

.eslintignore

16

dist/useRecorder.d.ts

@@ -8,9 +8,10 @@ /// <reference types="dom-mediacapture-record" />

};
declare type StopRecordingCallback = (blob: Blob, url: String) => void;
export declare const enum RecorderStatus {
declare type StopRecordingCallback = (blob: Blob, url: string) => void;
export declare enum RecorderStatus {
"IDLE" = "idle",
"INIT" = "init",
"RECORDING" = "recording"
"RECORDING" = "recording",
"UNREGISTERED" = "unregistered"
}
export declare const enum RecorderError {
export declare enum RecorderError {
"STREAM_INIT" = "stream-init",

@@ -20,10 +21,11 @@ "RECORDER_INIT" = "recorder-init"

declare function useRecorder(mediaStreamConstraints?: Partial<MediaStreamConstraints>, mediaRecorderOptions?: Partial<MediaRecorderOptions>): {
mediaRecorder: MediaRecorder | undefined;
stream: MediaStream | undefined;
mediaRecorder?: MediaRecorder;
stream?: MediaStream;
startRecording: () => void;
stopRecording: (callback: StopRecordingCallback) => () => void;
register: (element: HTMLVideoElement) => void;
unregister: () => void;
status: RecorderStatus;
error: RecorderError | undefined;
error?: RecorderError;
};
export default useRecorder;

@@ -50,2 +50,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.RecorderError = exports.RecorderStatus = void 0;
var react_1 = require("react");

@@ -56,2 +57,14 @@ var defaultContraints = {

};
var RecorderStatus;
(function (RecorderStatus) {
RecorderStatus["IDLE"] = "idle";
RecorderStatus["INIT"] = "init";
RecorderStatus["RECORDING"] = "recording";
RecorderStatus["UNREGISTERED"] = "unregistered";
})(RecorderStatus = exports.RecorderStatus || (exports.RecorderStatus = {}));
var RecorderError;
(function (RecorderError) {
RecorderError["STREAM_INIT"] = "stream-init";
RecorderError["RECORDER_INIT"] = "recorder-init";
})(RecorderError = exports.RecorderError || (exports.RecorderError = {}));
function useRecorder(mediaStreamConstraints, mediaRecorderOptions) {

@@ -61,42 +74,26 @@ var _this = this;

var streamRef = react_1.useRef();
var _a = react_1.useState("init" /* INIT */), status = _a[0], setStatus = _a[1];
var videoElementRef = react_1.useRef();
var _a = react_1.useState(RecorderStatus.INIT), status = _a[0], setStatus = _a[1];
var _b = react_1.useState(), error = _b[0], setError = _b[1];
var register = react_1.useCallback(function (element) {
initStream(element).then(initMediaRecorder).catch(setError);
}, []);
var startRecording = react_1.useCallback(function () {
var _a;
setStatus("recording" /* RECORDING */);
(_a = mediaRecorderRef.current) === null || _a === void 0 ? void 0 : _a.start();
}, []);
var stopRecording = react_1.useCallback(function (callback) { return function () {
var _a;
setStatus("idle" /* IDLE */);
if (mediaRecorderRef.current) {
mediaRecorderRef.current.ondataavailable = function (_a) {
var blob = _a.data;
callback(blob, URL.createObjectURL(blob));
};
(_a = mediaRecorderRef.current) === null || _a === void 0 ? void 0 : _a.stop();
}
}; }, []);
var initStream = react_1.useCallback(function (videoRef) { return __awaiter(_this, void 0, void 0, function () {
var _a, err_1;
return __generator(this, function (_b) {
switch (_b.label) {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_b.trys.push([0, 2, , 3]);
_c.trys.push([0, 2, , 3]);
_a = streamRef;
return [4 /*yield*/, navigator.mediaDevices.getUserMedia(__assign(__assign({}, defaultContraints), (mediaStreamConstraints ? __assign({}, mediaStreamConstraints) : {})))];
return [4 /*yield*/, ((_b = navigator.mediaDevices) === null || _b === void 0 ? void 0 : _b.getUserMedia(__assign(__assign({}, defaultContraints), (mediaStreamConstraints ? __assign({}, mediaStreamConstraints) : {}))))];
case 1:
_a.current = _b.sent();
videoRef.srcObject = streamRef.current;
_a.current = _c.sent();
videoElementRef.current = videoRef;
videoElementRef.current.srcObject = streamRef.current;
return [2 /*return*/, streamRef.current];
case 2:
err_1 = _b.sent();
throw new Error("stream-init" /* STREAM_INIT */);
err_1 = _c.sent();
throw new Error(RecorderError.STREAM_INIT);
case 3: return [2 /*return*/];
}
});
}); }, []);
}); }, [mediaStreamConstraints]);
var initMediaRecorder = react_1.useCallback(function (stream) {

@@ -110,11 +107,39 @@ if ((mediaRecorderOptions === null || mediaRecorderOptions === void 0 ? void 0 : mediaRecorderOptions.mimeType) &&

mediaRecorderRef.current = recorder;
setStatus("idle" /* IDLE */);
setStatus(RecorderStatus.IDLE);
}
catch (_a) {
throw new Error("recorder-init" /* RECORDER_INIT */);
throw new Error(RecorderError.RECORDER_INIT);
}
}, [mediaRecorderOptions]);
var register = react_1.useCallback(function (element) {
initStream(element).then(initMediaRecorder).catch(setError);
}, [initMediaRecorder, initStream]);
var unregister = react_1.useCallback(function () {
var _a;
if (videoElementRef.current) {
videoElementRef.current.pause();
videoElementRef.current.src = "";
}
var tracks = (_a = streamRef.current) === null || _a === void 0 ? void 0 : _a.getTracks();
if (!tracks || (tracks === null || tracks === void 0 ? void 0 : tracks.length) === 0)
return;
tracks.forEach(function (track) { return track.stop(); });
setStatus(RecorderStatus.UNREGISTERED);
}, []);
if (!navigator.mediaDevices) {
throw new Error("Navigator is not compatible");
}
var startRecording = react_1.useCallback(function () {
var _a;
setStatus(RecorderStatus.RECORDING);
(_a = mediaRecorderRef.current) === null || _a === void 0 ? void 0 : _a.start();
}, []);
var stopRecording = react_1.useCallback(function (callback) { return function () {
var _a;
setStatus(RecorderStatus.IDLE);
if (mediaRecorderRef.current) {
mediaRecorderRef.current.ondataavailable = function (_a) {
var blob = _a.data;
callback(blob, URL.createObjectURL(blob));
};
(_a = mediaRecorderRef.current) === null || _a === void 0 ? void 0 : _a.stop();
}
}; }, []);
return {

@@ -126,2 +151,3 @@ mediaRecorder: mediaRecorderRef === null || mediaRecorderRef === void 0 ? void 0 : mediaRecorderRef.current,

register: register,
unregister: unregister,
status: status,

@@ -128,0 +154,0 @@ error: error,

{
"name": "react-hook-recorder",
"version": "0.0.8",
"version": "0.0.9",
"description": "React based hook to use native MediaRecorder API",

@@ -25,9 +25,16 @@ "main": "dist/index.js",

"@babel/core": "^7.13.15",
"@storybook/addon-actions": "^6.2.8",
"@storybook/addon-essentials": "^6.2.8",
"@storybook/addon-links": "^6.2.8",
"@storybook/react": "^6.2.8",
"@storybook/addon-actions": "^6.3.4",
"@storybook/addon-essentials": "^6.3.4",
"@storybook/addon-links": "^6.3.4",
"@storybook/react": "^6.3.4",
"@typescript-eslint/eslint-plugin": "^4.28.3",
"@typescript-eslint/parser": "^4.28.3",
"babel-loader": "^8.2.2",
"eslint": "^7.30.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
"rimraf": "^3.0.2",
"storybook": "^6.2.8"
"storybook": "^6.3.4",
"typescript": "^4.3.5"
},

@@ -34,0 +41,0 @@ "repository": {

@@ -15,11 +15,12 @@ import { useCallback, useRef, useState } from "react";

type StopRecordingCallback = (blob: Blob, url: String) => void;
type StopRecordingCallback = (blob: Blob, url: string) => void;
export const enum RecorderStatus {
export enum RecorderStatus {
"IDLE" = "idle",
"INIT" = "init",
"RECORDING" = "recording",
"UNREGISTERED" = "unregistered",
}
export const enum RecorderError {
export enum RecorderError {
"STREAM_INIT" = "stream-init",

@@ -32,10 +33,76 @@ "RECORDER_INIT" = "recorder-init",

mediaRecorderOptions?: Partial<MediaRecorderOptions>
) {
): {
mediaRecorder?: MediaRecorder;
stream?: MediaStream;
startRecording: () => void;
stopRecording: (callback: StopRecordingCallback) => () => void;
register: (element: HTMLVideoElement) => void;
unregister: () => void;
status: RecorderStatus;
error?: RecorderError;
} {
const mediaRecorderRef = useRef<MediaRecorder>();
const streamRef = useRef<MediaStream>();
const videoElementRef = useRef<HTMLVideoElement>();
const [status, setStatus] = useState<RecorderStatus>(RecorderStatus.INIT);
const [error, setError] = useState<RecorderError>();
const register = useCallback((element: HTMLVideoElement) => {
initStream(element).then(initMediaRecorder).catch(setError);
const initStream = useCallback(
async (videoRef: HTMLVideoElement) => {
try {
streamRef.current = await navigator.mediaDevices?.getUserMedia({
...defaultContraints,
...(mediaStreamConstraints ? { ...mediaStreamConstraints } : {}),
});
videoElementRef.current = videoRef;
videoElementRef.current.srcObject = streamRef.current;
return streamRef.current;
} catch (err) {
throw new Error(RecorderError.STREAM_INIT);
}
},
[mediaStreamConstraints]
);
const initMediaRecorder = useCallback(
(stream: MediaStream) => {
if (
mediaRecorderOptions?.mimeType &&
!MediaRecorder.isTypeSupported(mediaRecorderOptions.mimeType)
) {
console.warn(
`MIME type ${mediaRecorderOptions.mimeType} not supported`
);
}
try {
const recorder = new MediaRecorder(
stream,
{ ...mediaRecorderOptions } || {}
);
mediaRecorderRef.current = recorder;
setStatus(RecorderStatus.IDLE);
} catch {
throw new Error(RecorderError.RECORDER_INIT);
}
},
[mediaRecorderOptions]
);
const register = useCallback(
(element: HTMLVideoElement) => {
initStream(element).then(initMediaRecorder).catch(setError);
},
[initMediaRecorder, initStream]
);
const unregister = useCallback(() => {
if (videoElementRef.current) {
videoElementRef.current.pause();
videoElementRef.current.src = "";
}
const tracks = streamRef.current?.getTracks();
if (!tracks || tracks?.length === 0) return;
tracks.forEach((track) => track.stop());
setStatus(RecorderStatus.UNREGISTERED);
}, []);

@@ -63,39 +130,2 @@

const initStream = useCallback(async (videoRef: HTMLVideoElement) => {
try {
streamRef.current = await navigator.mediaDevices.getUserMedia({
...defaultContraints,
...(mediaStreamConstraints ? { ...mediaStreamConstraints } : {}),
});
videoRef.srcObject = streamRef.current;
return streamRef.current;
} catch (err) {
throw new Error(RecorderError.STREAM_INIT);
}
}, []);
const initMediaRecorder = useCallback((stream: MediaStream) => {
if (
mediaRecorderOptions?.mimeType &&
!MediaRecorder.isTypeSupported(mediaRecorderOptions.mimeType)
) {
console.warn(`MIME type ${mediaRecorderOptions.mimeType} not supported`);
}
try {
const recorder = new MediaRecorder(
stream,
{ ...mediaRecorderOptions } || {}
);
mediaRecorderRef.current = recorder;
setStatus(RecorderStatus.IDLE);
} catch {
throw new Error(RecorderError.RECORDER_INIT);
}
}, []);
if (!navigator.mediaDevices) {
throw new Error("Navigator is not compatible");
}
return {

@@ -107,2 +137,3 @@ mediaRecorder: mediaRecorderRef?.current,

register,
unregister,
status,

@@ -109,0 +140,0 @@ error,

{
"compilerOptions": {
"target": "es5",
"lib": ["es2017", "es7", "es6", "dom"],
"module": "commonjs",
"target": "ES5",
"lib": ["ES2017", "ES7", "ES6", "DOM"],
"module": "CommonJS",
"jsx": "react",

@@ -10,2 +10,3 @@ "strict": true,

"skipLibCheck": false,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,

@@ -15,3 +16,3 @@ "declaration": true,

},
"exclude": ["./src/stories"]
"exclude": ["./src/stories", "./dist"]
}
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