目录
使用了 video.js 视频播放器
视频抽帧 base64格式
<template>
<div class="box">
<a-select ref="select" v-model:value="videoSrc" style="width: 120px" @change="changeSelect">
<a-select-option :value="item.src" v-for="item in selectValue" :key="item.key"> 视频 - {{ item.key }}</a-select-option></a-select
>
<video ref="videoRef" class="video-js vjs-default-skin" width="600" height="400" controls @canplay="canplay()" @ended="ended()">
<!-- <source src="" type="application/x-mpegURL" /> -->
不支持动态
</video>
<div v-if="imgList.length">
<img class="img" v-for="(item, i) in imgList" :key="i" :src="item" alt="" />
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import videojs from 'video.js'
const videoRef = ref()
const myVideo = ref()
const videoSrc = ref()
const selectValue = reactive([
{
key: 1,
src: require('@/assets/video/video.mp4'),
},
{
key: 2,
src: 'https://haokan.baidu.com/04156719-993e-4735-a67e-0e0f22f534a0',
},
{
key: 3,
src: 'http://10.8.21.32:8080/webdav/ombot/demo/file/display/店内小孩and推走购物车.mp4',
},
])
const imgList = ref([])
const changeSelect = () => {
const videoType = videoSrc.value.slice(videoSrc.value.length - 4, videoSrc.value.length)
// myVideo.value.src([{ type: 'application/x-mpegURL', src: videoSrc.value }])
if (videoType.includes('m3u8')) {
myVideo.value.src([{ type: 'application/x-mpegURL', src: videoSrc.value }])
} else {
console.log(' mp4视频')
myVideo.value.src([{ type: 'video/mp4', src: videoSrc.value }])
}
}
let imgInternal
const canplay = () => {
console.log('videoRef ', videoRef.value.videoWidth, videoRef.value.videoHeight) // 视频的真实宽高
imgInternal = setInterval(() => {
captureVideo()
}, 2000)
}
const ended = () => {
clearInterval(imgInternal)
}
const initVideo = () => {
const options = {
autoplay: true, // 自动播放
muted: true, // 静音(为true是,自动播放生效)
}
myVideo.value = videojs(videoRef.value, options)
videoRef.value.addEventListener('canplaytype', val => {
console.log(' 触发', val)
})
}
// 视频抽帧
const captureVideo = () => {
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
canvas.width = videoRef.value.videoWidth
canvas.height = videoRef.value.videoHeight
// let img = document.createElement('img')
ctx.drawImage(videoRef.value, 0, 0, canvas.width, canvas.height) // 第一个参数是要绘制的图片资源
// if (w == 1) return
imgList.value.push(canvas.toDataURL('image/png'))
console.log('图片地址 ', canvas.toDataURL('image/png')) // base64组成的图片的源数据、可以直接赋值给图片的src属性
}
onMounted(() => {
initVideo()
captureVideo()
})
</script>
<style scoped>
.box {
margin: 100px;
}
.img {
display: inline-block;
width: 200px;
height: 100px;
}
</style>
抽帧的图片会在播放器下方同步显示
前端展示base64的图片
要加上 data:image/*;base64,'
<img class="chat-content-img" :src="'data:image/*;base64,' + item.image_base64" alt="" />
压缩base 64 大小
const compressImg = (base64: string, type: string, rate: number, callback: Function) => {
// 声明一个Image对象
const _img = new Image()
// 将图片的地址赋予这个Image
_img.src = base64
// 在图片加载完成后
_img.onload = function () {
// 创建canvas标签
const _canvas = document.createElement('canvas')
// 根据压缩比例设置canvas画布的宽高属性
// this 指的是当前Image对象
const w: any = _img.width * rate
const h: any = _img.height * rate
_canvas.setAttribute('width', w)
_canvas.setAttribute('height', h)
// 将图片渲染到canvas画布上 并设置渲染图片的宽高与画布的宽高一致
;(_canvas.getContext('2d') as any).drawImage(_img, 0, 0, w, h)
// 将canvas画布转换成对应类型的base64
var base64 = _canvas.toDataURL(type)
// 将结果通过回调函数传递给方法的调用者
callback(base64)
}
}
未压缩之前是6.8MB 压缩完成后为 2.9 MB
mp4 跨域问题
百度说是视频跨域问题
解决方法 crossOrigin="Anonymous"