Search code examples
javascriptvue.jswebrtcvuejs2vuex

Alternative for setting the srcObject using VueJS


Setting the "src" attribute of the html video element does not work with Vue.js and Vuex:

<video id="myVideoEl" :src="myStreamSrc" autoplay="autoplay">

myStreamSrc is a computed value and is set in a mutation by an event handler:

AddStream: function (state, plMyStream) {
  state.myRTCPeerConnection.addStream(plMyStream)
  state.myStreamSrc = plMyStream
}

When I run my application with that code, I get the following error:

HTTP “Content-Type” of “text/html” is not supported. Load of media resource http://localhost:8080/[object%20MediaStream] failed.

When I do the following:

state.myVideoEl = document.querySelector('#myVideoEl')
state.myVideoEl.srcObject = payloadWithMyStream

I do not get any error and the stream is shown. The problem is, I can not use the working code snipped because the referenced elements are added later to the DOM. This code snippet does not work when I bind the html video element in a div with a v-if Vuex.js attribute. Then I just get "undefined" as a result (because the div element with the video element did not exist on page load).

Is there a difference between setting the srcObject and setting the src attribute? I thought that when I set srcObject the video element will have a src attribute, but it does not.

Is it possible to set the srcObject in the video html attribute?

For more info, please visit my theard in the Vue.js forum: https://forum.vuejs.org/t/reference-elements-when-they-rendered-with-v-if/16474/13


Solution

  • Have you tried

    <video v-if="myStreamSrc" id="myVideoEl" :srcObject ="myStreamSrc" autoplay="autoplay"> ?
    

    Otherwise i would recommend you to write a component for that case:

    var videoComponent = {
      template: '<video ref="myVideoEl" :srcObject ="myStreamSrc" autoplay="autoplay">'
      props: ['myStreamSrc']
    }
    Vue.component("video-component", videoComponent)
    

    In the parent template

    <video-component v-if="myStreamSrc" :myStreamSrc="myStreamSrc"></video-component>
    

    OR in the parent you can just put a watcher for the srcObject which i assume to be equal to false until the correct video source gets loaded. In this case you can wait till the source target is set and then do it in the working way.

    ...
    watchers:{
        myStreamSrc: function (newValue, oldValue) {
          if(!oldValue && !!newValue){
            this.nextTick(function () {
              state.myVideoEl = document.querySelector('#myVideoEl')
              state.myVideoEl.srcObject = payloadWithMyStream
            })
          }
      }
    }
    

    Hint: You can use $refs.myVideoEl instead of document.querySelector('#myVideoEl') when you set ref="myVideoEl" to the html-element instead of id="myVideoEl". This is just a sort of taste.

    PS: I wrote the code in stackoverflow directly without an spellchecker...