Skip to content

Commit

Permalink
feat(useUserMedia)!: add constraints - remove deviceIds (#2032)
Browse files Browse the repository at this point in the history
  • Loading branch information
mango-martin authored and antfu committed Mar 4, 2023
1 parent 313477d commit 8f2a3c4
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 17 deletions.
2 changes: 1 addition & 1 deletion packages/core/useUserMedia/demo.vue
Expand Up @@ -13,7 +13,7 @@ const { videoInputs: cameras } = useDevicesList({
const video = ref<HTMLVideoElement>()
const { stream, enabled } = useUserMedia({
videoDeviceId: currentCamera,
constraints: { video: { deviceId: currentCamera } },
})
watchEffect(() => {
Expand Down
6 changes: 4 additions & 2 deletions packages/core/useUserMedia/index.md
Expand Up @@ -41,7 +41,9 @@ const currentCamera = computed(() => cameras.value[0]?.deviceId)
const currentMicrophone = computed(() => microphones.value[0]?.deviceId)

const { stream } = useUserMedia({
videoDeviceId: currentCamera,
audioDeviceId: currentMicrophone,
constraints: {
video: { deviceId: currentCamera },
audio: { deviceId: currentMicrophone, }
}
})
```
51 changes: 37 additions & 14 deletions packages/core/useUserMedia/index.ts
Expand Up @@ -14,7 +14,7 @@ export interface UseUserMediaOptions extends ConfigurableNavigator {
*/
enabled?: MaybeRef<boolean>
/**
* Recreate stream when the input devices id changed
* Recreate stream when deviceIds or constraints changed
*
* @default true
*/
Expand All @@ -26,6 +26,7 @@ export interface UseUserMediaOptions extends ConfigurableNavigator {
* Pass `false` or "none" to disabled video input
*
* @default undefined
* @deprecated in favor of constraints
*/
videoDeviceId?: MaybeRef<string | undefined | false | 'none'>
/**
Expand All @@ -35,8 +36,16 @@ export interface UseUserMediaOptions extends ConfigurableNavigator {
* Pass `false` or "none" to disabled audi input
*
* @default undefined
* @deprecated in favor of constraints
*/
audioDeviceId?: MaybeRef<string | undefined | false | 'none'>
/**
* MediaStreamConstraints to be applied to the requested MediaStream
* If provided, the constraints will override videoDeviceId and audioDeviceId
*
* @default {}
*/
constraints?: MaybeRef<MediaStreamConstraints>
}

/**
Expand All @@ -50,32 +59,46 @@ export function useUserMedia(options: UseUserMediaOptions = {}) {
const autoSwitch = ref(options.autoSwitch ?? true)
const videoDeviceId = ref(options.videoDeviceId)
const audioDeviceId = ref(options.audioDeviceId)
const constraints = ref(options.constraints)
const { navigator = defaultNavigator } = options
const isSupported = useSupported(() => navigator?.mediaDevices?.getUserMedia)

const stream: Ref<MediaStream | undefined> = shallowRef()

function getDeviceOptions(device: Ref<string | undefined | false | 'none'>) {
if (device.value === 'none' || device.value === false)
return false
if (device.value == null)
return true
return {
deviceId: device.value,
function getDeviceOptions(type: 'video' | 'audio') {
switch (type) {
case 'video': {
if (constraints.value)
return constraints.value.video || false
if (videoDeviceId.value === 'none' || videoDeviceId.value === false)
return false
if (videoDeviceId.value == null)
return true
return { deviceId: videoDeviceId.value }
}
case 'audio': {
if (constraints.value)
return constraints.value.audio || false
if (audioDeviceId.value === 'none' || audioDeviceId.value === false)
return false
if (audioDeviceId.value == null)
return true
return { deviceId: audioDeviceId.value }
}
}
}

async function _start() {
if (!isSupported.value || stream.value)
return
stream.value = await navigator!.mediaDevices.getUserMedia({
video: getDeviceOptions(videoDeviceId),
audio: getDeviceOptions(audioDeviceId),
video: getDeviceOptions('video'),
audio: getDeviceOptions('audio'),
})
return stream.value
}

async function _stop() {
function _stop() {
stream.value?.getTracks().forEach(t => t.stop())
stream.value = undefined
}
Expand All @@ -102,14 +125,13 @@ export function useUserMedia(options: UseUserMediaOptions = {}) {
(v) => {
if (v)
_start()
else
_stop()
else _stop()
},
{ immediate: true },
)

watch(
[videoDeviceId, audioDeviceId],
[videoDeviceId, audioDeviceId, constraints],
() => {
if (autoSwitch.value && stream.value)
restart()
Expand All @@ -125,6 +147,7 @@ export function useUserMedia(options: UseUserMediaOptions = {}) {
restart,
videoDeviceId,
audioDeviceId,
constraints,
enabled,
autoSwitch,
}
Expand Down

0 comments on commit 8f2a3c4

Please sign in to comment.