Home > Enterprise >  Binding A Media Feed/ Stream to Video Element - Vue 3 Composition API
Binding A Media Feed/ Stream to Video Element - Vue 3 Composition API

Time:07-29

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>

demo

  • Related