22
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

vue.jsで複数のvideoタグを扱う

Last updated at Posted at 2019-05-14

vue.js+MediaStreamを用いてvideoタグの扱い、および複数のビデオタグを扱う方法について。

vue.jsでvideoタグを使った再生をする場合、src属性を指定する方法やjsからsrcObjectを指定する方法がよく書かれていますが、vue.jsの機能でバインディングする方法があまり書かれていないのでまとめ

結論

:srcObject.propMediaStreamインスタンスを指定する


<template>
  <div>
    <video autoplay :srcObject.prop="stream"></video>
  </div>
</template>

<script>
export default {
  name: 'app',
  data(){
    return {
      stream: undefined
    }
  },
  async created() {
    this.stream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true
    })
  }
}
</script>

参考
Binding to srcObject attribute

src属性による指定

よく出てくる情報はsrc属性を指定する方法です。
単純にvueのバインディングを使えば良いのでシンプルです。

<template>
  <video src=":src" autoplay></video>
</template>

<script>
export default {
  data() {
    return {
      src: "url"
    };
  },
};
</script>

ただ、この方法は映像ファイルのURLが存在する必要があるため、ストリームを使用する場合はURL.createObjectURLを使って変換する必要があります。
ただ、このメソッドが廃止予定となっており、現在ではsrcの代わりにsrcObjectを使うことが推奨されています

srcObjectにバインドする方法

htmlの属性であるsrcと違い、srcObjectはプロパティなので、通常の:srcObject="stream"ではなく、:srcObject.prop="stream"と指定する必要があります。

参考
Binding to srcObject attribute

あとは、このstreamに 映像や音声のストリームデータを格納すればストリームのデータを再生してくれます。


<template>
  <div>
    <video autoplay :srcObject.prop="stream"></video>
  </div>
</template>

<script>
export default {
  name: 'app',
  data(){
    return {
      stream: undefined
    }
  },
  async created() {
    this.stream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true
    })
  }
}
</script>

複数のvideoタグを使う場合

もちろんv-forでvideoタグを複数扱うこともできます。
addボタンを押すと自分の顔がいっぱい並ぶので注意してください

<template>
  <div>
    <div>
      <button @click="add">add</button>
    </div>
    <div>
      <video v-for="(stream, i) in streams" autoplay :key="i" :srcObject.prop="stream"></video>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'app',
    data() {
      return {
        streams: []
      }
    },
    methods: {
      async add() {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: true,
          video: true
        });
        this.streams.push(stream);
      }
    },
  }
</script>

備考:自動再生したい場合

vue.jsなしのJavascriptで扱う場合はよく読み込み後にplayメソッドを叩いて自動再生処理を行いました。こうしないとブラウザのポリシーによっては映像が再生されないので。
Chromeはバージョンによってこの辺のポリシーがコロコロ変わったので、割と振り回されました。

vue.jsのバインディングを利用する場合は以下2つの方法で可能です。

autoplay属性を設定

簡単な方法であればautoplay属性を指定する方法です。
この属性を指定しておけば読み込み後に自動再生してくれます。

<template>
    <video autoplay :srcObject.prop="stream"></video>
</template>

<script>
export default {
  data() {
    return {
      stream: undefined
    };
  },
  async created() {
      this.stream = await navigator.mediaDevices.getUserMedia({audio: true, video: true})
  }
};
</script>

loadeddataイベントで再生

あるいはloadeddataイベントを拾って、playメソッドを叩く方法でも良いです。
再生以外の処理も挟めるので、以前と同じような処理をしたいと考えた場合はこちらの方が良いと思います。


<template>
  <div>
    <video @loadeddata="onloadeddata" :srcObject.prop="stream"></video>
  </div>
</template>

<script>
export default {
  name: 'app',
  data(){
    return {
      stream: undefined
    }
  },
  methods: {
    onloadeddata(ev) {
      ev.target.play();
    },
  },
  async created() {
    this.stream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true
    })
  }
}
</script>

まとめ

vue.jsでvideoタグを扱う方法をまとめました。
WebRTC等を組み合わせればハングアウト等のようなビデオチャットツールが作れると思います。
どちらかというと通信量などのパフォーマンス周りでハマると思いますが。。。

22
23
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?