I am trying to bind a camera feed to a video element using Vue 3, but I can not seem to even get a basic example working. Can someone tell me what I am missing?
import { ref, reactive } from 'vue'
let stream: any = reactive({})
let constraints = {
audio: false,
video: {
width: { min: 1024, ideal: 1280, max: 1920 },
height: { min: 576, ideal: 720, max: 1080 },
facingMode: 'environment'
}
}
stream = await navigator.mediaDevices.getUserMedia(constraints)
Then in my template I have tried both of the following ways to bind
<video :srcObject.prop="stream" width="300" height="200" autoplay></video>
<video :srcObject.prope.camel="stream" autoplay playsinline></video>
Your code overwrites stream
with the result of getUserMedia()
, which effectively removes the original reactive()
instance from the component's context.
Make stream
a ref
instead of reactive
, and set its value
property to the result of getUserMedia()
.
Also, to ensure the user's resources are activated only when necessary, call getUserMedia()
in the component's mounted
hook, and stop the stream in the beforeUnmount
hook.
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
const stream = ref(null)
const constraints = {
audio: false,
video: {
width: { min: 1024, ideal: 1280, max: 1920 },
height: { min: 576, ideal: 720, max: 1080 },
facingMode: 'environment',
},
}
onMounted(async () => {
stream.value = await navigator.mediaDevices.getUserMedia(constraints)
})
onBeforeUnmount(() => {
stream.value.getTracks().forEach(track => track.stop())
})
</script>
<template>
<video :srcObject="stream" width="300" height="200" autoplay></video>
</template>