截取视频帧
方式:多媒体 + 画布 video+canvas
function captureVideo() {const video:any = document.getElementById('video');const canvas = document.createElement('canvas');const ctx:any = canvas.getContext('2d');ctx.drawImage(video, 0, 0, video.clientHeight, video.clientWidth);// 获取 base64const dataUrl = canvas.toDataURL('image/png');// 处理成File对象const file = dataUrlToFile(dataUrl, '封面图.png');file.then((res) => uploadFile(res));}// 上传文件对象到服务器const uploadFile = async (file) => {try {// 创建FormData对象const form = new FormData();// 文件对象form.append('fileData', file);const data = await request(‘xxxx.json’, {method: 'post',name: "Filedata",data: form,});console.log(data);} catch (error) {message.error(error.message || '上传失败,请重试');}}// base64转成File对象export async function dataUrlToFile(dataUrl: string, fileName: string): Promise {const res: Response = await fetch(dataUrl);const blob: Blob = await res.blob();return new File([blob], fileName, { type: 'image/png' });}
canvas.toDataURL()报错

原因:受限于 CORS 策略,会存在跨域问题,虽然可以使用图像(比如append到页面上)但是绘制到画布上会污染画布,一旦一个画布被污染,就无法提取画布的数据,比如无法使用使用画布toBlob(),toDataURL(),或getImageData()方法;当使用这些方法的时候 会抛出一个上面的安全错误
解决方式:给img或者video添加属性 crossOrigin:’anonymous’
img.setAttribute(‘crossOrigin’, ‘anonymous’);
Or
video.setAttribute(‘crossOrigin’, ‘anonymous’);
preload = ‘auto’
最好给video元素加上preload属性
视频裁剪
除了截取视频帧之外,还需根据特定比例对视频的进行裁剪
功能点:
1、裁剪实现
2、裁剪后预览
裁剪比例:
3 / 4 = 0.75
裁剪工具选择
react-rnd:https://github.com/bokuweb/react-rnd
在使用该工具过程中遇到了一个问题:如果使用缩放功能,边界控制会有问题(如下图);固定选择框宽高则无此问题,使用时需注意
裁剪后预览
通过reactRnd可以很方便的拿到裁剪参数,然后要根据这些参数,将裁剪后的区域在页面上展示
处理方案:CSS -> transform
使用transform后,裁剪区域的展示不成问题,但会有另一个问题出现:
多媒体播放器控制按钮的位置会随着裁剪区域变化而变化
目标:不管裁剪区域怎么变化,控制按钮位置不变,这就需要对控制按钮样式进行处理
/* step1:给父元素设置overflow:hidden样式,隐藏video超出区域 *//* 父元素样式 */.videoBox {width: 256px;display: flex;justify-content: center;align-items: center;overflow: hidden;:global {video {width: 100%;max-height: 341px;}}}
// halfScreenVideo: 获取多媒体播放器const halfScreenVideo = document.querySelector('.half_screen');// startY: 裁剪区y坐标const { startY } = videoCutInfo;/*** 1.33: 缩放比 1 / 0.75* 341: 预览高度,按宽度计算得到的值 256 / 0.75* 35: 控制播放控制器位置*/// step2:改变转换原点 -> tophalfScreenVideo.style.transformOrigin = 'top';// step3:根据比例先放大,根据裁剪区y坐标调整位置halfScreenVideo.style.transform = `translateY(${-(341 * startY * 1.33)}px) scale(1.33)`;// step4:每次插入都会保留上一次插入的,因此需要先删除上一次插入的,保证只有一条样式规则document.styleSheets[0].cssRules.length && document.styleSheets[0].deleteRule(0);// step5:缩放到正常大小,设置多媒体控制器位置始终不变document.styleSheets[0].insertRule(`.half_screen::-webkit-media-controls{transform: translateY(${341 * startY - 35}px) scale(0.75)}`,0,);
