使用 VueJS 设置 srcObject 的替代方法

Alternative for setting the srcObject using VueJS

设置 html 视频元素的 "src" 属性不适用于 Vue.js 和 Vuex:

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

myStreamSrc 是一个计算值,由事件处理程序在突变中设置:

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

当我 运行 我的应用程序使用该代码时,出现以下错误:

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

当我执行以下操作时:

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

我没有收到任何错误,并且显示了流。问题是,我不能使用截断的工作代码,因为引用的元素稍后添加到 DOM。当我使用 v-if Vuex.js 属性绑定 div 中的 html 视频元素时,此代码片段不起作用。然后我得到 "undefined" 作为结果(因为页面加载时不存在带有视频元素的 div 元素)。

设置srcObject和设置src属性有区别吗?我认为当我设置 srcObject 时,视频元素将具有 src 属性,但它没有。

是否可以在视频html属性中设置srcObject

欲了解更多信息,请访问 Vue.js 论坛中的 my theard: https://forum.vuejs.org/t/reference-elements-when-they-rendered-with-v-if/16474/13

你试过了吗

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

否则我会建议你为这种情况编写一个组件:

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

在父模板中

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

或者在父级中,您可以只为 srcObject 设置一个观察器,我假设它等于 false,直到加载正确的视频源。在这种情况下,您可以等到设置源目标,然后按工作方式进行。

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

提示: 当您将 ref="myVideoEl" 设置为 html 元素而不是 id="myVideoEl" 时,您可以使用 $refs.myVideoEl 而不是 document.querySelector('#myVideoEl')。这只是一种品味。

PS: 我直接在Whosebug里写代码,没有拼写检查器...

想配合我的(类似)解决方案。我正在为 Vue 使用 Nuxt 框架。通过 Vuex 设置 MediaStream 对我也不起作用。网络摄像头的开启状态是通过在非子组件中单击按钮启动的,我需要在该其他组件中为视频对象设置媒体流。

在单击按钮切换我的视图以及启动时运行的方法中 navigator.mediaDevices 我最终这样做了(可能不是最干净的?)。

let constraints = (window.constraints = {
        audio: false,
        video: {
          facingMode: "user"
        }
      });

      navigator.mediaDevices
        .getUserMedia(constraints)
        .then((stream) => {
          let videoTracks = stream.getVideoTracks();
          if (this.$store.state.debug) console.log("Got stream with constraints:", constraints);
          if (this.$store.state.debug) console.log("Using video device: " + videoTracks[0].label);
          stream.oninactive = function() {
            if (this.$store.state.debug) console.log("Stream inactive");
          };
          // NOTE: this is done this way because I couldnt set it via Vuex state
          document.getElementById('user-media__source').srcObject = stream;
        })
        .catch((error) => {
          if (error.name === "ConstraintNotSatisfiedError") {
            if (this.$store.state.debug) console.log(`The resolution ${constraints.video.width.exact} "x" ${constraints.video.width.exact} px is not supported by your device.`);
          } else if (error.name === "PermissionDeniedError") {
            if (this.$store.state.debug) console.log(`Permissions have not been granted to use your camera and microphone, you need to allow the page access to your devices in order for the demo to work.`);
          }
        });

因此,由于我需要在其中设置源的组件已经 created/mounted 我刚刚解雇了通常的 document.getElementById('XXXX').srcObject = 并且它按我想要的方式工作。

srcObject 是修饰符而不是 html 属性,所以你需要写

<video :srcObject.prop="myStreamSrc" autoplay/>

有关 2019 年更新,请参阅 Priansh Shah 的回答。

为新版本的 Vue 发布更新的解决方案,以防有人遇到这个问题并遇到与我相同的错误。

2019 年更新:

<video :src-object.prop.camel="stream">

第一个更改是使用 v-bind 绑定到 srcObject,这里是 shorthand 的示例:

<video :srcObject.prop="stream">

但是 srcObject 是驼峰式的,所以在 HTML 中它只是变成 srcobject(小写),这被认为是不同的 属性,因此不会触发视频.

如果您使用的 Vue < 2.1,则必须使用 document.getXXXXX(...).srcObject = stream.

手动启动它

但是,如果您使用的是 Vue v2.1+,那么您很幸运,因为现在还有一个 API 修饰符:

<video :src-object.prop.camel="stream">

.camel 将 kebab-case 转换为驼峰式大小写,因此要获得 srcObject 我们执行相反的操作并获得 src-object.camel。将它与 .propv-bind 结合起来,我们得到上面的语法。