Vue-video-player 與 Video.js 雖然能顯示 HLS,但卻沒提供 Capture Image 功能,我們必須使用 HTML 5 的 Canvas 才能達成需求。
Version
macOS Catalina 10.15.4
WebStorm 2020.1.1
Vue 2.6.11
Vue-video-player 5.0.2
Vue
<template>
<div>
<video-player class="video-player" ref="videoPlayer" :options="playerOptions"></video-player>
<button @click="captureImage">Capture</button>
</div>
</template>
<script>
import 'video.js/dist/video-js.css'
let captureImage = function() {
let id = this.$refs.videoPlayer.player.player().id()
let video = document.getElementById(`${ id }_html5_api`)
let canvas = document.createElement('canvas')
canvas.width = video.videoWidth
canvas.height = video.videoHeight
canvas.getContext('2d').drawImage(video, 0, 0)
let img = canvas.toDataURL()
console.log(img)
}
export default {
name: 'App',
data: () => ({
playerOptions: {
sources: [{
type: 'application/x-mpegURL',
src: 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8'
}],
}
}),
methods: {
captureImage,
},
}
</script>
第 3 行
<video-player class="video-player" ref="videoPlayer" :options="playerOptions"></video-player>
在 <video-player>
加上 ref
,稍後將透過 ref
取得 <video>
的 id
。
因為
<video>
的id
是動態的,因此必須透過ref
動態取得
第 4 行
<button @click="captureImage">Capture</button>
加上 <button>
執行 captureImage()
。
12 行
let id = this.$refs.videoPlayer.player.player().id()
let video = document.getElementById(`${id}_html5_api`)
目的要透過 getElementById()
取得 <video-player>
的 <video>
tag,但其 id
為動態並不固定,因此只能透過 $ref()
一層一層取得 <video>
tag 的動態 id
。
15 行
let canvas = document.createElement('canvas')
canvas.width = video.videoWidth
canvas.height = video.videoHeight
canvas.getContext('2d').drawImage(video, 0, 0)
為了擷取 image,我們會將 <video>
寫入 <canvas>
。
因為 <canvas>
目的只是產生 Base64 String 而不是用在顯示,因此不必在 HTML template 使用 <canvas>
,使用 document.createElement()
動態建立 <canvas>
即可。
建立 <canvas>
必須指定其 width
與 height
,因此由 video
的 videoWith
與 videoHeight
建立 canvas。
若要將 <video>
的 image 寫入 <canvas>
,首先進入 2d
context,再使用 drawImage()
寫入 image,傳入 video
element 與 top left 的 x 軸與 y 軸,因此為 0, 0
。
21 行
let img = canvas.toDataURL()
console.log(img)
呼叫 <canvas>
的 toDataUrl()
產生 Base64 String,如此就能傳入 API 做相關應用。
Conclusion
- 若覺得要抓 Vue-video-player 的
<video>
id 很 tricky,也可參考 Video.js 官網的 Video.js and Vue Integration 自行包裝 component,如此id
即可固定不變 - HTML 5 的 Canvas 是關鍵,透過
drawImage()
就能將<video>
寫入<canvas>
達成擷取 image
Reference
Manu Bhardwaj, JavaScript: How to Capture Image from Video ?
MDN, CanvasRenderingContext2D.drawImage()
Video.js, Video.js and Vue Integration