@ricky0123/vad-react
Version:
Powerful, user-friendly, client-side voice activity detector (VAD) for React apps
162 lines • 5.96 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useMicVAD = exports.getDefaultReactRealTimeVADOptions = exports.utils = void 0;
const vad_web_1 = require("@ricky0123/vad-web");
const react_1 = __importStar(require("react"));
var vad_web_2 = require("@ricky0123/vad-web");
Object.defineProperty(exports, "utils", { enumerable: true, get: function () { return vad_web_2.utils; } });
const defaultReactOptions = {
startOnLoad: true,
userSpeakingThreshold: 0.6,
};
const getDefaultReactRealTimeVADOptions = (model) => {
return {
...(0, vad_web_1.getDefaultRealTimeVADOptions)(model),
...defaultReactOptions,
};
};
exports.getDefaultReactRealTimeVADOptions = getDefaultReactRealTimeVADOptions;
const reactOptionKeys = Object.keys(defaultReactOptions);
const vadOptionKeys = Object.keys((0, vad_web_1.getDefaultRealTimeVADOptions)("v5"));
const _filter = (keys, obj) => {
return keys.reduce((acc, key) => {
acc[key] = obj[key];
return acc;
}, {});
};
function useOptions(options) {
const model = options.model ?? vad_web_1.DEFAULT_MODEL;
options = { ...(0, exports.getDefaultReactRealTimeVADOptions)(model), ...options };
const reactOptions = _filter(reactOptionKeys, options);
const vadOptions = _filter(vadOptionKeys, options);
return [reactOptions, vadOptions];
}
function useEventCallback(fn) {
const ref = react_1.default.useRef(fn);
// we copy a ref to the callback scoped to the current state/props on each render
useIsomorphicLayoutEffect(() => {
ref.current = fn;
});
return react_1.default.useCallback((...args) => ref.current.apply(void 0, args), []);
}
function useMicVAD(options) {
const [reactOptions, vadOptions] = useOptions(options);
const [userSpeaking, updateUserSpeaking] = (0, react_1.useState)(false);
const [loading, setLoading] = (0, react_1.useState)(true);
const [errored, setErrored] = (0, react_1.useState)(false);
const [listening, setListening] = (0, react_1.useState)(false);
const [vad, setVAD] = (0, react_1.useState)(null);
const userOnFrameProcessed = useEventCallback(vadOptions.onFrameProcessed);
vadOptions.onFrameProcessed = useEventCallback((probs, frame) => {
const isSpeaking = probs.isSpeech > reactOptions.userSpeakingThreshold;
updateUserSpeaking(isSpeaking);
userOnFrameProcessed(probs, frame);
});
const { onSpeechEnd, onSpeechStart, onSpeechRealStart, onVADMisfire } = vadOptions;
const _onSpeechEnd = useEventCallback(onSpeechEnd);
const _onSpeechStart = useEventCallback(onSpeechStart);
const _onVADMisfire = useEventCallback(onVADMisfire);
const _onSpeechRealStart = useEventCallback(onSpeechRealStart);
vadOptions.onSpeechEnd = _onSpeechEnd;
vadOptions.onSpeechStart = _onSpeechStart;
vadOptions.onVADMisfire = _onVADMisfire;
vadOptions.onSpeechRealStart = _onSpeechRealStart;
(0, react_1.useEffect)(() => {
let myvad;
let canceled = false;
const setup = async () => {
try {
myvad = await vad_web_1.MicVAD.new(vadOptions);
if (canceled) {
myvad.destroy();
return;
}
}
catch (e) {
setLoading(false);
if (e instanceof Error) {
setErrored(e.message);
}
else {
setErrored(String(e));
}
return;
}
setVAD(myvad);
setLoading(false);
if (reactOptions.startOnLoad) {
myvad?.start();
setListening(true);
}
};
setup().catch((e) => {
console.log("Well that didn't work");
});
return function cleanUp() {
myvad?.destroy();
canceled = true;
if (!loading && !errored) {
setListening(false);
}
};
}, []);
const pause = () => {
if (!loading && !errored) {
vad?.pause();
setListening(false);
}
};
const start = () => {
if (!loading && !errored) {
vad?.start();
setListening(true);
}
};
const toggle = () => {
if (listening) {
pause();
}
else {
start();
}
};
return {
listening,
errored,
loading,
userSpeaking,
pause,
start,
toggle,
};
}
exports.useMicVAD = useMicVAD;
const useIsomorphicLayoutEffect = typeof window !== "undefined" &&
typeof window.document !== "undefined" &&
typeof window.document.createElement !== "undefined"
? react_1.default.useLayoutEffect
: react_1.default.useEffect;
//# sourceMappingURL=index.js.map