@bigbinary/neeto-media-recorder 2.7.6 → 2.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constants.js +6 -2
- package/constants.js.map +1 -1
- package/core.js +20 -1
- package/core.js.map +1 -1
- package/index.js +208 -5
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/src/translations/en.json +2 -1
package/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { shallow } from 'zustand/shallow';
|
|
2
|
-
import {
|
|
2
|
+
import { useState, useRef, useCallback, useEffect, forwardRef, useImperativeHandle } from 'react';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import { isNotEmpty, noop } from '@bigbinary/neeto-cist';
|
|
5
|
-
import { SCREEN_RECORDER_STATUS, UPLOAD_STATUS as UPLOAD_STATUS$1, ONE_SECOND_IN_MILLISECONDS as ONE_SECOND_IN_MILLISECONDS$1, MIME_TYPE as MIME_TYPE$1, ONE_MINUTE_IN_MILLISECONDS as ONE_MINUTE_IN_MILLISECONDS$1, IS_EXTENSION as IS_EXTENSION$1, SCREEN_RECORDER_ERROR, IS_SAFARI_EXTENSION, SCREEN_RECORDER_EVENT, UPLOAD_EVENT } from '@bigbinary/neeto-media-recorder/constants';
|
|
5
|
+
import { SCREEN_RECORDER_STATUS, UPLOAD_STATUS as UPLOAD_STATUS$1, ONE_SECOND_IN_MILLISECONDS as ONE_SECOND_IN_MILLISECONDS$1, MIME_TYPE as MIME_TYPE$1, ONE_MINUTE_IN_MILLISECONDS as ONE_MINUTE_IN_MILLISECONDS$1, IS_EXTENSION as IS_EXTENSION$1, SCREEN_RECORDER_ERROR, IS_SAFARI_EXTENSION, MIC_NOT_WORKING_SILENCE_TIMEOUT, SCREEN_RECORDER_EVENT, UPLOAD_EVENT } from '@bigbinary/neeto-media-recorder/constants';
|
|
6
6
|
import { screenRecorder, useMultipartS3UploadStatus, getMultipartS3Uploader } from '@bigbinary/neeto-media-recorder/core';
|
|
7
7
|
import PageLoader from '@bigbinary/neeto-molecules/PageLoader';
|
|
8
8
|
import Alert from '@bigbinary/neetoui/Alert';
|
|
@@ -512,7 +512,6 @@ var MIME_TYPE = {
|
|
|
512
512
|
mp4: "video/mp4",
|
|
513
513
|
webmH264: "video/webm;codecs=h264"
|
|
514
514
|
};
|
|
515
|
-
// 2 hours
|
|
516
515
|
|
|
517
516
|
var getSupportedMimeType = function getSupportedMimeType() {
|
|
518
517
|
return MIME_TYPE.webmH264;
|
|
@@ -921,6 +920,177 @@ var Controls = function Controls(_ref) {
|
|
|
921
920
|
});
|
|
922
921
|
};
|
|
923
922
|
|
|
923
|
+
var getAnalyser = function getAnalyser() {
|
|
924
|
+
var _screenRecorder$getAu;
|
|
925
|
+
var stream = (_screenRecorder$getAu = screenRecorder.getAudioStream) === null || _screenRecorder$getAu === void 0 ? void 0 : _screenRecorder$getAu.call(screenRecorder);
|
|
926
|
+
if (!stream) return null;
|
|
927
|
+
var ctx = new (window.AudioContext || window.webkitAudioContext)();
|
|
928
|
+
var source = ctx.createMediaStreamSource(stream);
|
|
929
|
+
var analyser = ctx.createAnalyser();
|
|
930
|
+
analyser.fftSize = 2048;
|
|
931
|
+
source.connect(analyser);
|
|
932
|
+
var data = new Uint8Array(analyser.fftSize);
|
|
933
|
+
return {
|
|
934
|
+
ctx: ctx,
|
|
935
|
+
source: source,
|
|
936
|
+
analyser: analyser,
|
|
937
|
+
data: data
|
|
938
|
+
};
|
|
939
|
+
};
|
|
940
|
+
var hasChrome = typeof chrome !== "undefined" && chrome.runtime && chrome.runtime.onMessage;
|
|
941
|
+
var useAudioIsCapturing = function useAudioIsCapturing(_ref) {
|
|
942
|
+
var isMicOn = _ref.isMicOn;
|
|
943
|
+
var _useState = useState(true),
|
|
944
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
945
|
+
hasAudio = _useState2[0],
|
|
946
|
+
setHasAudio = _useState2[1];
|
|
947
|
+
var _useState3 = useState(false),
|
|
948
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
949
|
+
disable = _useState4[0],
|
|
950
|
+
setDisable = _useState4[1];
|
|
951
|
+
var _useState5 = useState(false),
|
|
952
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
953
|
+
timerStarted = _useState6[0],
|
|
954
|
+
setTimerStarted = _useState6[1];
|
|
955
|
+
var timerRef = useRef(null);
|
|
956
|
+
var remainingRef = useRef(MIC_NOT_WORKING_SILENCE_TIMEOUT);
|
|
957
|
+
var startedAtRef = useRef(null);
|
|
958
|
+
var clearTimer = function clearTimer() {
|
|
959
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
960
|
+
timerRef.current = null;
|
|
961
|
+
};
|
|
962
|
+
var armTimer = function armTimer() {
|
|
963
|
+
if (timerRef.current || !timerStarted) return;
|
|
964
|
+
logger.info("useAudioIsCapturing new timer");
|
|
965
|
+
startedAtRef.current = Date.now();
|
|
966
|
+
timerRef.current = setTimeout(function () {
|
|
967
|
+
return setHasAudio(false);
|
|
968
|
+
}, remainingRef.current);
|
|
969
|
+
};
|
|
970
|
+
var pauseTimer = function pauseTimer() {
|
|
971
|
+
if (!timerRef.current) return;
|
|
972
|
+
var elapsed = Date.now() - startedAtRef.current;
|
|
973
|
+
remainingRef.current = Math.max(0, remainingRef.current - elapsed);
|
|
974
|
+
clearTimer();
|
|
975
|
+
};
|
|
976
|
+
var resumeTimer = function resumeTimer() {
|
|
977
|
+
if (timerRef.current || !timerStarted || disable) return;
|
|
978
|
+
logger.info("useAudioIsCapturing resumeTimer");
|
|
979
|
+
startedAtRef.current = Date.now();
|
|
980
|
+
timerRef.current = setTimeout(function () {
|
|
981
|
+
return setHasAudio(false);
|
|
982
|
+
}, remainingRef.current);
|
|
983
|
+
};
|
|
984
|
+
var reset = useCallback(function () {
|
|
985
|
+
logger.info("useAudioIsCapturing reset");
|
|
986
|
+
clearTimer();
|
|
987
|
+
remainingRef.current = MIC_NOT_WORKING_SILENCE_TIMEOUT;
|
|
988
|
+
setTimerStarted(false);
|
|
989
|
+
setHasAudio(true);
|
|
990
|
+
}, []);
|
|
991
|
+
|
|
992
|
+
// Listen for Chrome extension messages
|
|
993
|
+
useEffect(function () {
|
|
994
|
+
var handleMessage = function handleMessage(message) {
|
|
995
|
+
if (!(message.type === "IGNORE_AUDIO_NOT_CAPTURING")) return;
|
|
996
|
+
logger.info("useAudioIsCapturing -> IGNORE_AUDIO_NOT_CAPTURING received");
|
|
997
|
+
setDisable(true);
|
|
998
|
+
};
|
|
999
|
+
|
|
1000
|
+
// Check if we're in a Chrome extension context
|
|
1001
|
+
if (hasChrome) {
|
|
1002
|
+
chrome.runtime.onMessage.addListener(handleMessage);
|
|
1003
|
+
}
|
|
1004
|
+
return function () {
|
|
1005
|
+
if (hasChrome) {
|
|
1006
|
+
var _chrome, _chrome$runtime, _chrome$runtime$onMes;
|
|
1007
|
+
(_chrome = chrome) === null || _chrome === void 0 ? void 0 : (_chrome$runtime = _chrome.runtime) === null || _chrome$runtime === void 0 ? void 0 : (_chrome$runtime$onMes = _chrome$runtime.onMessage) === null || _chrome$runtime$onMes === void 0 ? void 0 : _chrome$runtime$onMes.removeListener(handleMessage);
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
}, []);
|
|
1011
|
+
useEffect(function () {
|
|
1012
|
+
if (!isMicOn || !timerStarted || disable) return noop;
|
|
1013
|
+
var analyserObj = null;
|
|
1014
|
+
var rafId;
|
|
1015
|
+
var loop = function loop() {
|
|
1016
|
+
if (!analyserObj) analyserObj = getAnalyser();
|
|
1017
|
+
// if no stream yet or analyser failed, treat as silence
|
|
1018
|
+
var isSilent = !analyserObj ? true : function () {
|
|
1019
|
+
analyserObj.analyser.getByteTimeDomainData(analyserObj.data);
|
|
1020
|
+
return analyserObj.data.every(function (v) {
|
|
1021
|
+
return v === 128;
|
|
1022
|
+
}); // absolute silence
|
|
1023
|
+
}();
|
|
1024
|
+
|
|
1025
|
+
if (isSilent) {
|
|
1026
|
+
armTimer();
|
|
1027
|
+
} else {
|
|
1028
|
+
clearTimer();
|
|
1029
|
+
remainingRef.current = MIC_NOT_WORKING_SILENCE_TIMEOUT;
|
|
1030
|
+
if (!hasAudio) setHasAudio(true);
|
|
1031
|
+
}
|
|
1032
|
+
rafId = requestAnimationFrame(loop);
|
|
1033
|
+
};
|
|
1034
|
+
loop();
|
|
1035
|
+
return function () {
|
|
1036
|
+
cancelAnimationFrame(rafId);
|
|
1037
|
+
clearTimer();
|
|
1038
|
+
if (analyserObj) {
|
|
1039
|
+
analyserObj.source.disconnect();
|
|
1040
|
+
analyserObj.ctx.close();
|
|
1041
|
+
}
|
|
1042
|
+
};
|
|
1043
|
+
}, [timerStarted, hasAudio, isMicOn, disable]);
|
|
1044
|
+
useEffect(function () {
|
|
1045
|
+
var _callbacks;
|
|
1046
|
+
if (!isMicOn) return noop;
|
|
1047
|
+
var callbacks = (_callbacks = {}, _defineProperty(_callbacks, SCREEN_RECORDER_EVENT.onStart, function () {
|
|
1048
|
+
reset();
|
|
1049
|
+
setTimerStarted(true);
|
|
1050
|
+
armTimer();
|
|
1051
|
+
}), _defineProperty(_callbacks, SCREEN_RECORDER_EVENT.onRestart, function () {
|
|
1052
|
+
reset();
|
|
1053
|
+
setTimerStarted(true);
|
|
1054
|
+
armTimer();
|
|
1055
|
+
}), _defineProperty(_callbacks, SCREEN_RECORDER_EVENT.onResume, function () {
|
|
1056
|
+
setTimerStarted(true);
|
|
1057
|
+
resumeTimer();
|
|
1058
|
+
}), _defineProperty(_callbacks, SCREEN_RECORDER_EVENT.onPause, function () {
|
|
1059
|
+
pauseTimer();
|
|
1060
|
+
}), _defineProperty(_callbacks, SCREEN_RECORDER_EVENT.onStop, function () {
|
|
1061
|
+
clearTimer();
|
|
1062
|
+
reset();
|
|
1063
|
+
}), _defineProperty(_callbacks, "disable-mic-not-working-warning", function disableMicNotWorkingWarning() {
|
|
1064
|
+
logger.info("useAudioIsCapturing -> disable-mic-not-working-warning");
|
|
1065
|
+
setDisable(true);
|
|
1066
|
+
setTimeout(function () {
|
|
1067
|
+
clearTimer();
|
|
1068
|
+
reset();
|
|
1069
|
+
}, 500);
|
|
1070
|
+
}), _callbacks);
|
|
1071
|
+
// start straight a way.
|
|
1072
|
+
callbacks[SCREEN_RECORDER_EVENT.onStart]();
|
|
1073
|
+
Object.entries(callbacks).forEach(function (_ref2) {
|
|
1074
|
+
var _ref3 = _slicedToArray(_ref2, 2),
|
|
1075
|
+
ev = _ref3[0],
|
|
1076
|
+
fn = _ref3[1];
|
|
1077
|
+
return screenRecorder.addCallback(ev, fn);
|
|
1078
|
+
});
|
|
1079
|
+
return function () {
|
|
1080
|
+
Object.entries(callbacks).forEach(function (_ref4) {
|
|
1081
|
+
var _ref5 = _slicedToArray(_ref4, 2),
|
|
1082
|
+
ev = _ref5[0],
|
|
1083
|
+
fn = _ref5[1];
|
|
1084
|
+
return screenRecorder.removeCallback(ev, fn);
|
|
1085
|
+
});
|
|
1086
|
+
};
|
|
1087
|
+
}, [isMicOn, reset]);
|
|
1088
|
+
return {
|
|
1089
|
+
hasAudio: hasAudio,
|
|
1090
|
+
reset: reset
|
|
1091
|
+
};
|
|
1092
|
+
};
|
|
1093
|
+
|
|
924
1094
|
var useHandleErrors = function useHandleErrors(_ref) {
|
|
925
1095
|
var error = _ref.error,
|
|
926
1096
|
recorderStatus = _ref.recorderStatus;
|
|
@@ -1286,7 +1456,13 @@ var MediaRecorder = function MediaRecorder(_ref, ref) {
|
|
|
1286
1456
|
appName = _ref$appName === void 0 ? globalProps.appName : _ref$appName,
|
|
1287
1457
|
_ref$mimeType = _ref.mimeType,
|
|
1288
1458
|
mimeType = _ref$mimeType === void 0 ? getSupportedMimeType() : _ref$mimeType,
|
|
1289
|
-
folderId = _ref.folderId
|
|
1459
|
+
folderId = _ref.folderId,
|
|
1460
|
+
_ref$isMicOn = _ref.isMicOn,
|
|
1461
|
+
isMicOn = _ref$isMicOn === void 0 ? false : _ref$isMicOn,
|
|
1462
|
+
_ref$onAudioNotCaptur = _ref.onAudioNotCapturing,
|
|
1463
|
+
onAudioNotCapturing = _ref$onAudioNotCaptur === void 0 ? function () {} : _ref$onAudioNotCaptur,
|
|
1464
|
+
_ref$onError = _ref.onError,
|
|
1465
|
+
onError = _ref$onError === void 0 ? function () {} : _ref$onError;
|
|
1290
1466
|
var _useTranslation = useTranslation(),
|
|
1291
1467
|
t = _useTranslation.t;
|
|
1292
1468
|
var _useState = useState(false),
|
|
@@ -1306,6 +1482,18 @@ var MediaRecorder = function MediaRecorder(_ref, ref) {
|
|
|
1306
1482
|
isRetryUpload = _useState8[0],
|
|
1307
1483
|
setIsRetryUpload = _useState8[1];
|
|
1308
1484
|
var recordingRef = useRef({});
|
|
1485
|
+
var _useAudioIsCapturing = useAudioIsCapturing({
|
|
1486
|
+
isMicOn: isMicOn
|
|
1487
|
+
}),
|
|
1488
|
+
hasAudio = _useAudioIsCapturing.hasAudio,
|
|
1489
|
+
reset = _useAudioIsCapturing.reset;
|
|
1490
|
+
useEffect(function () {
|
|
1491
|
+
if (hasAudio) return;
|
|
1492
|
+
onAudioNotCapturing();
|
|
1493
|
+
setTimeout(function () {
|
|
1494
|
+
reset();
|
|
1495
|
+
}, 1000);
|
|
1496
|
+
}, [hasAudio]);
|
|
1309
1497
|
|
|
1310
1498
|
/**
|
|
1311
1499
|
* @type {React.RefObject<Promise<unknown> | null>}
|
|
@@ -1359,6 +1547,16 @@ var MediaRecorder = function MediaRecorder(_ref, ref) {
|
|
|
1359
1547
|
_useCreateRecording$d2 = _useCreateRecording$d === void 0 ? {} : _useCreateRecording$d,
|
|
1360
1548
|
_useCreateRecording$d3 = _useCreateRecording$d2.recording,
|
|
1361
1549
|
recording = _useCreateRecording$d3 === void 0 ? {} : _useCreateRecording$d3;
|
|
1550
|
+
useEffect(function () {
|
|
1551
|
+
var elapsedTimeInSec = Math.round(elapsedTime / 1000);
|
|
1552
|
+
var checkDelay = 7; // we get data every 5 sec, 7 for safety
|
|
1553
|
+
// If data is insufficient after n secs, there is some issue with media recorder, discard.
|
|
1554
|
+
if (elapsedTimeInSec < checkDelay) return;
|
|
1555
|
+
if (!screenRecorder.hasData() && recorderStatus === SCREEN_RECORDER_STATUS.recording) {
|
|
1556
|
+
screenRecorder.setError(SCREEN_RECORDER_ERROR.InsufficientData);
|
|
1557
|
+
onError(SCREEN_RECORDER_ERROR.InsufficientData);
|
|
1558
|
+
}
|
|
1559
|
+
}, [elapsedTime]);
|
|
1362
1560
|
recordingRef.current = recording;
|
|
1363
1561
|
var handleCreateRecording = /*#__PURE__*/function () {
|
|
1364
1562
|
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
@@ -1588,7 +1786,12 @@ var MediaRecorder = function MediaRecorder(_ref, ref) {
|
|
|
1588
1786
|
className: "flex h-screen w-full flex-col items-center justify-start py-10 xl:py-14 2xl:py-20",
|
|
1589
1787
|
children: [/*#__PURE__*/jsxs("div", {
|
|
1590
1788
|
className: classNames("w-full max-w-3xl"),
|
|
1591
|
-
children: [/*#__PURE__*/jsx(UseDesktopAppCallout, {}), error === SCREEN_RECORDER_ERROR.
|
|
1789
|
+
children: [/*#__PURE__*/jsx(UseDesktopAppCallout, {}), error === SCREEN_RECORDER_ERROR.InsufficientData && /*#__PURE__*/jsx(Callout, {
|
|
1790
|
+
className: "mb-2 p-3",
|
|
1791
|
+
"data-cy": "recorder-insufficient-data-error-callout",
|
|
1792
|
+
style: "danger",
|
|
1793
|
+
children: t("neetoMediaRecorder.insufficientDataError")
|
|
1794
|
+
}), error === SCREEN_RECORDER_ERROR.NotAllowedError && /*#__PURE__*/jsxs("div", {
|
|
1592
1795
|
className: "flex flex-col items-center",
|
|
1593
1796
|
children: [/*#__PURE__*/jsx(Typography, {
|
|
1594
1797
|
className: "mb-2",
|