前端H5实现视频上传,并截取封面
前端实现视频上传,并截取第一帧作为封面。
写的过程中出现的问题:
- 在微信内ios系统无法上传视频,无法触发
addEventListener
的loadedmetadata
- 解决完1问题后,ios截取视频第一帧作为封面有问题,获取的宽度高度为0。
解决完上述两个问题后,最后完整版代码:
getCoverAndUploadVideo
入参是视频资源videoFile
,通过oss上传或者后台上传接口。
最终抛出的是视频的url,封面的url。
关于前端实现oss上传可以访问这个文章👉:vue3使用阿里oss上传资源文件
function getCoverAndUploadVideo (videoFile) {if (!videoFile) {return Promise.reject('Please upload a video file.');}return new Promise((rs, rj) => {const video = document.createElement('video');const url = URL.createObjectURL(videoFile);video.src = url;function addVideoLoadListener() {video.addEventListener('loadedmetadata', function() {setTimeout(() => {try {// 设置video的尺寸,确保能够获取整个视频帧video.width = video.videoWidth;video.height = video.videoHeight;// 在视频准备好后,将currentTime设置为0尝试获取第一帧video.currentTime = 0;video.addEventListener('seeked', function() {// 使用canvas绘制当前帧const canvas = document.createElement('canvas');canvas.width = video.videoWidth;canvas.height = video.videoHeight;const ctx = canvas.getContext('2d');ctx.drawImage(video, 0, 0, canvas.width, canvas.height);// 从canvas导出图片,例如导出为base64的图片const mimeType = 'image/png';const imageData = canvas.toDataURL(mimeType);const blob = base64ToBlob(imageData.split(',')[1], mimeType)const coverFileName = videoFile.name.split('.')[0] + '_cover.png';const coverFile = new File([blob], coverFileName, { type: mimeType });const resources = await Promise.all([// 通过oss上传// window.globalOSSClient.put(videoFile.name,videoFile),// window.globalOSSClient.put(coverFileName, coverFile),// or // 后端给的接口,上传后,返回的url// ...]).catch(rj);rs({videoUrl: resources[0].url,coverUrl: resources[1].url,});// 释放视频URL对象URL.revokeObjectURL(url);}, { once: true });} catch (err) {rj(err);}}, 100) });}// 解决微信浏览器下,ios上传视频,出现的问题 if ((window as any).WeixinJSBridge && /(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {window.WeixinJSBridge.invoke('getNetworkType', {}, () => {video.muted = true;video.playsInline = true;video['webkit-playsinline'] = true;addVideoLoadListener()video.play().then(() => video.pause());});} else {addVideoLoadListener();}});
}function base64ToBlob(base64, mimeType) {const byteString = atob(base64);const ab = new ArrayBuffer(byteString.length);const ia = new Uint8Array(ab);for (let i = 0; i < byteString.length; i++ ) {ia[i] = byteString.charCodeAt(i);}const blob = new Blob([ab], { type: mimeType });return blob;
}