diff --git a/.gitignore b/.gitignore
index d2f2174..f85065c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,4 +58,4 @@ typings/
.env
# build directories
-lib
\ No newline at end of file
+# lib
diff --git a/lib/index.d.ts b/lib/index.d.ts
new file mode 100644
index 0000000..b68e920
--- /dev/null
+++ b/lib/index.d.ts
@@ -0,0 +1,31 @@
+///
+import { ReactElement } from "react";
+declare type ReactMediaRecorderRenderProps = {
+ error: string;
+ muteAudio: () => void;
+ unMuteAudio: () => void;
+ startRecording: () => void;
+ pauseRecording: () => void;
+ resumeRecording: () => void;
+ stopRecording: () => void;
+ mediaBlobUrl: null | string;
+ status: StatusMessages;
+ isAudioMuted: boolean;
+ previewStream: MediaStream | null;
+ clearBlobUrl: () => void;
+};
+declare type ReactMediaRecorderProps = {
+ render: (props: ReactMediaRecorderRenderProps) => ReactElement;
+ audio?: boolean | MediaTrackConstraints;
+ video?: boolean | MediaTrackConstraints;
+ screen?: boolean;
+ onStop?: (blobUrl: string, blob: Blob) => void;
+ onStart?: () => void;
+ blobPropertyBag?: BlobPropertyBag;
+ mediaRecorderOptions?: MediaRecorderOptions | null;
+ customMediaStream?: MediaStream | null;
+ stopStreamsOnStop?: boolean;
+};
+declare type StatusMessages = "media_aborted" | "permission_denied" | "no_specified_media_found" | "media_in_use" | "invalid_media_constraints" | "no_constraints" | "recorder_error" | "idle" | "acquiring_media" | "delayed_start" | "recording" | "stopping" | "stopped";
+export declare const ReactMediaRecorder: ({ render, audio, video, onStop, onStart, blobPropertyBag, screen, mediaRecorderOptions, customMediaStream, stopStreamsOnStop, }: ReactMediaRecorderProps) => ReactElement ReactElement import("react").Component)> | null) | (new (props: any) => import("react").Component)>;
+export {};
diff --git a/lib/index.js b/lib/index.js
new file mode 100644
index 0000000..c4563dd
--- /dev/null
+++ b/lib/index.js
@@ -0,0 +1,18 @@
+"use strict";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]0){console.error("The constraints "+unSupportedConstraints.join(",")+" doesn't support on this browser. Please check your ReactMediaRecorder component.");}};if(typeof audio==="object"){checkConstraints(audio);}
+if(typeof video==="object"){checkConstraints(video);}
+if(mediaRecorderOptions&&mediaRecorderOptions.mimeType){if(!MediaRecorder.isTypeSupported(mediaRecorderOptions.mimeType)){console.error("The specified MIME type you supplied for MediaRecorder doesn't support this browser");}}
+if(!mediaStream.current){getMediaStream();}},[audio,screen,video,getMediaStream,mediaRecorderOptions]);var startRecording=function(){return __awaiter(void 0,void 0,void 0,function(){var isStreamEnded;return __generator(this,function(_a){switch(_a.label){case 0:setError("NONE");if(!!mediaStream.current)return[3,2];return[4,getMediaStream()];case 1:_a.sent();_a.label=2;case 2:if(!mediaStream.current)return[3,5];isStreamEnded=mediaStream.current.getTracks().some(function(track){return track.readyState==="ended";});if(!isStreamEnded)return[3,4];return[4,getMediaStream()];case 3:_a.sent();_a.label=4;case 4:mediaRecorder.current=new MediaRecorder(mediaStream.current);mediaRecorder.current.ondataavailable=onRecordingActive;mediaRecorder.current.onstop=onRecordingStop;mediaRecorder.current.onstart=onRecordingStart;mediaRecorder.current.onerror=function(){setError("NO_RECORDER");setStatus("idle");};mediaRecorder.current.start();setStatus("recording");_a.label=5;case 5:return[2];}});});};var onRecordingActive=function(_a){var data=_a.data;mediaChunks.current.push(data);};var onRecordingStart=function(){onStart();};var onRecordingStop=function(){var chunk=mediaChunks.current[0];var blobProperty=Object.assign({type:chunk.type},blobPropertyBag||(video?{type:"video/mp4"}:{type:"audio/wav"}));var blob=new Blob(mediaChunks.current,blobProperty);var url=URL.createObjectURL(blob);setStatus("stopped");setMediaBlobUrl(url);onStop(url,blob);};var muteAudio=function(mute){setIsAudioMuted(mute);if(mediaStream.current){mediaStream.current.getAudioTracks().forEach(function(audioTrack){return(audioTrack.enabled=!mute);});}};var pauseRecording=function(){if(mediaRecorder.current&&mediaRecorder.current.state==="recording"){mediaRecorder.current.pause();}};var resumeRecording=function(){if(mediaRecorder.current&&mediaRecorder.current.state==="paused"){mediaRecorder.current.resume();}};var stopRecording=function(){if(mediaRecorder.current){if(mediaRecorder.current.state!=="inactive"){setStatus("stopping");mediaRecorder.current.stop();if(stopStreamsOnStop){mediaStream.current&&mediaStream.current.getTracks().forEach(function(track){return track.stop();});}
+mediaChunks.current=[];}}};return render({error:RecorderErrors[error],muteAudio:function(){return muteAudio(true);},unMuteAudio:function(){return muteAudio(false);},startRecording:startRecording,pauseRecording:pauseRecording,resumeRecording:resumeRecording,stopRecording:stopRecording,mediaBlobUrl:mediaBlobUrl,status:status,isAudioMuted:isAudioMuted,previewStream:mediaStream.current?new MediaStream(mediaStream.current.getVideoTracks()):null,clearBlobUrl:function(){return setMediaBlobUrl(null);},});};
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index b3d5ca1..f75daf0 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -21,8 +21,11 @@ type ReactMediaRecorderProps = {
video?: boolean | MediaTrackConstraints;
screen?: boolean;
onStop?: (blobUrl: string, blob: Blob) => void;
+ onStart?: () => void;
blobPropertyBag?: BlobPropertyBag;
mediaRecorderOptions?: MediaRecorderOptions | null;
+ customMediaStream?: MediaStream | null;
+ stopStreamsOnStop?: boolean;
};
type StatusMessages =
@@ -56,9 +59,12 @@ export const ReactMediaRecorder = ({
audio = true,
video = false,
onStop = () => null,
+ onStart = () => null,
blobPropertyBag,
screen = false,
mediaRecorderOptions = null,
+ customMediaStream = null,
+ stopStreamsOnStop = true,
}: ReactMediaRecorderProps) => {
const mediaRecorder = useRef(null);
const mediaChunks = useRef([]);
@@ -75,7 +81,9 @@ export const ReactMediaRecorder = ({
video: typeof video === "boolean" ? !!video : video,
};
try {
- if (screen) {
+ if (customMediaStream) {
+ mediaStream.current = customMediaStream;
+ } else if (screen) {
//@ts-ignore
const stream = (await window.navigator.mediaDevices.getDisplayMedia({
video: video || true,
@@ -168,6 +176,7 @@ export const ReactMediaRecorder = ({
mediaRecorder.current = new MediaRecorder(mediaStream.current);
mediaRecorder.current.ondataavailable = onRecordingActive;
mediaRecorder.current.onstop = onRecordingStop;
+ mediaRecorder.current.onstart = onRecordingStart;
mediaRecorder.current.onerror = () => {
setError("NO_RECORDER");
setStatus("idle");
@@ -181,6 +190,10 @@ export const ReactMediaRecorder = ({
mediaChunks.current.push(data);
};
+ const onRecordingStart = () => {
+ onStart();
+ };
+
const onRecordingStop = () => {
const [chunk] = mediaChunks.current;
const blobProperty: BlobPropertyBag = Object.assign(
@@ -219,8 +232,10 @@ export const ReactMediaRecorder = ({
if (mediaRecorder.current.state !== "inactive") {
setStatus("stopping");
mediaRecorder.current.stop();
- mediaStream.current &&
- mediaStream.current.getTracks().forEach((track) => track.stop());
+ if (stopStreamsOnStop) {
+ mediaStream.current &&
+ mediaStream.current.getTracks().forEach((track) => track.stop());
+ }
mediaChunks.current = [];
}
}
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..757d754
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,41 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@types/dom-mediacapture-record@^1.0.2":
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/@types/dom-mediacapture-record/-/dom-mediacapture-record-1.0.7.tgz#08bacca4296ef521d59049f43e65cf971bbf6be1"
+ integrity sha512-ddDIRTO1ajtbxaNo2o7fPJggpN54PZf1ZUJKOjto2ENMJE/9GKUvaw3ZRuQzlS/p0E+PnIcssxfoqYJ4yiXSBw==
+
+"@types/node@^12.12.11":
+ version "12.12.54"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1"
+ integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w==
+
+"@types/prop-types@*":
+ version "15.7.3"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
+ integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
+
+"@types/react@^16.9.11":
+ version "16.9.49"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.49.tgz#09db021cf8089aba0cdb12a49f8021a69cce4872"
+ integrity sha512-DtLFjSj0OYAdVLBbyjhuV9CdGVHCkHn2R+xr3XkBvK2rS1Y1tkc14XSGjYgm5Fjjr90AxH9tiSzc1pCFMGO06g==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^3.0.2"
+
+csstype@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.3.tgz#2b410bbeba38ba9633353aff34b05d9755d065f8"
+ integrity sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag==
+
+jsmin@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/jsmin/-/jsmin-1.0.1.tgz#e7bd0dcd6496c3bf4863235bf461a3d98aa3b98c"
+ integrity sha1-570NzWSWw79IYyNb9GGj2YqjuYw=
+
+typescript@^3.7.2:
+ version "3.9.7"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
+ integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==