@orbisk/vue-use-media-recorder
Version:
🪝 Vue Composable around MediaRecorder API
112 lines (111 loc) • 3.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useMediaRecorder = useMediaRecorder;
var _core = require("@vueuse/core");
var _shared = require("@vueuse/shared");
var _defu = require("defu");
var _vue = require("vue");
const defaultOptions = {
constraints: {
audio: false,
video: false
},
mediaRecorderOptions: {},
onStart: () => {},
onPause: () => {},
onResume: () => {},
onStop: () => {},
onError: () => {}
};
function useMediaRecorder(options = {}) {
const data = (0, _vue.ref)([]);
const mediaRecorder = (0, _vue.shallowRef)();
const stream = (0, _vue.shallowRef)();
const isMimeTypeSupported = (0, _vue.computed)(() => {
return (0, _vue.toValue)(options.mediaRecorderOptions)?.mimeType ? MediaRecorder.isTypeSupported((0, _vue.toValue)(options.mediaRecorderOptions)?.mimeType ?? "") : true;
});
const isSupported = (0, _core.useSupported)(() => {
return !!navigator?.mediaDevices?.getUserMedia && isMimeTypeSupported.value;
});
const state = (0, _core.computedWithControl)(() => mediaRecorder.value, () => {
return mediaRecorder.value?.state;
});
const mimeType = (0, _core.computedWithControl)(() => mediaRecorder.value, () => {
return mediaRecorder.value?.mimeType;
});
const {
mediaRecorderOptions,
constraints
} = (0, _defu.defu)(options, defaultOptions);
const setupMediaRecorder = newMediaRecorder => {
newMediaRecorder.ondataavailable = e => {
mimeType.trigger();
data.value.push(e.data);
};
newMediaRecorder.onstop = (...args) => {
stream.value?.getTracks().forEach(t => t.stop());
state.trigger();
mimeType.trigger();
options.onStop?.(...args);
};
newMediaRecorder.onpause = (...args) => {
state.trigger();
mimeType.trigger();
options.onPause?.(...args);
};
newMediaRecorder.onresume = (...args) => {
state.trigger();
mimeType.trigger();
options.onResume?.(...args);
};
newMediaRecorder.onstart = (...args) => {
state.trigger();
mimeType.trigger();
options.onStart?.(...args);
};
newMediaRecorder.onerror = (...args) => {
state.trigger();
mimeType.trigger();
options.onError?.(...args);
};
};
const start = async (timeslice = void 0) => {
if (state.value === "recording") return;
data.value = [];
stream.value = await navigator.mediaDevices.getUserMedia((0, _vue.toValue)(constraints));
const mr = new MediaRecorder(stream.value, (0, _vue.toValue)(mediaRecorderOptions));
setupMediaRecorder(mr);
mediaRecorder.value = mr;
mediaRecorder.value?.start(timeslice);
};
const stop = () => {
if (!state.value || state.value === "inactive") return;
mediaRecorder.value?.stop();
};
const pause = () => {
if (state.value !== "recording") return;
mediaRecorder.value?.pause();
};
const resume = () => {
if (state.value !== "paused") return;
mediaRecorder.value?.resume();
};
(0, _shared.tryOnScopeDispose)(() => {
mediaRecorder.value?.stop();
});
return {
start,
pause,
resume,
stop,
data,
stream,
state,
isSupported,
isMimeTypeSupported,
mimeType: (0, _vue.computed)(() => mimeType.value),
mediaRecorder: (0, _vue.computed)(() => mediaRecorder.value)
};
}