vue.js+MediaStreamを用いてvideoタグの扱い、および複数のビデオタグを扱う方法について。
vue.jsでvideoタグを使った再生をする場合、src属性を指定する方法やjsからsrcObjectを指定する方法がよく書かれていますが、vue.jsの機能でバインディングする方法があまり書かれていないのでまとめ
結論
:srcObject.prop
でMediaStream
インスタンスを指定する
<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"
と指定する必要があります。
あとは、この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等を組み合わせればハングアウト等のようなビデオチャットツールが作れると思います。
どちらかというと通信量などのパフォーマンス周りでハマると思いますが。。。