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>
CodePudding user response:
Your code overwrites stream
with the result of getUserMedia()
, which effectively removes the original reactive()
instance from the component's context.
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.
Solution
Make stream
a ref
instead of reactive
, and set its value
property to the result of getUserMedia()
:
<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>
Then, bind stream
directly to <video>.srcObject
:
<template>
<video :srcObject="stream" width="300" height="200" autoplay></video>
</template>