uni-app App and H5 platform upload video and capture the first frame of video to generate a picture

uni-app App and H5 platform use renderjs to upload video, capture the first frame of video and generate picture

提示:因为uni-app中renderjs仅支持App和H5平台,所以该方案仅支持当前这两个平台。 this.request为本人封装的接口请求方法,可以替换成个人的接口请求方法,如有需要可在下方留言



foreword

Because the uni-app App side has no dom concept and does not support dom operations, and the canvas of uni-app does not support drawing video. renderjs perfectly solves the basic dom operation on the uni-app App side. Achieve the effect at the bottom! !


1. Introduction to renderjs

renderjs是一个运行在视图层的js。它比[WXS](https://uniapp.dcloud.io/tutorial/miniprogram-subject.html#wxs)更加强大。它只支持app-vue和h5。

There are two main functions of renderjs:

  • Significantly reduce the communication loss between the logic layer and the view layer, and provide high-performance view interaction capabilities
  • Operate the dom at the view layer and run the js library for the web

2. Create the index.vue file, the code below is in index.vue

1.HTML code

The code is as follows (example):

<template>
	<view class="content">
		// 逻辑层调用视图层方法,采用监听data中变量改变的方法
		<view id="canvas" class="canvas" :prop="newVal" :change:prop="canvas.create"></view>
		<button @click="choose">chooseVideo</button>
	</view>
</template>

2. Logic layer code

The code is as follows (example):

<!-- 逻辑层script -->
<script>
	export default {
    
    
		data() {
    
    
			return {
    
    
				newVal: null
			};
		},
		methods: {
    
    
			choose(){
    
    
				// 选取视频文件,拿到本地地址
				uni.chooseVideo({
    
    
					sourceType: ['camera', 'album'],
					success:  (blod)=>{
    
    
						// 获取视频信息,拿到宽高信息
						uni.getVideoInfo({
    
    
							src: blod.tempFilePath,
							success: (info) => {
    
    
								// 上传视频到网络地址,当然也可以使用本地地址。App、H5平台本人都测试过,都没问题!!!
								uni.uploadFile({
    
    
									url: 'http://替换成自己个上传文件接口/api/common/upload', //仅为示例,非真实的接口地址
									filePath: blod.tempFilePath,
									name: 'file',
									formData: {
    
    
										'token': uni.getStorageSync('userInfo').token
									},
									success: src => {
    
    
										// fullurl也可以使用本地地址,上传选择文件获取到的 => blod.tempFilePath
										this.newVal = {
    
    fullurl: JSON.parse(src.data).data.fullurl, width: info.width, height: info.height}
										// 这里当时想做个平台区分,但是后面发现H5平台这种调用方式,视图层create接受参数的时候,只能接收到newValue,但是不能接收到event, ownerInstance,所以还是统一使用上方操作
										// 下方方法仅展示,调用还是统一使用上方操作
										// // #ifdef APP-PLUS
										// this.newVal = {fullurl: JSON.parse(src.data).data.fullurl, width: info.width, height: info.height}
										// // #endif
										// // #ifdef H5
										// this.create({fullurl: JSON.parse(src.data).data.fullurl, width: info.width, height: info.height})
										// // #endif
									},
									complete: all => {
    
    
										console.log(JSON.parse(all.data))
									}
								})
							}
						})
					}
				})
			},
			// 逻辑层拿到base64字符串,上传网络图片
			getBase64(options){
    
    
				this.request({
    
    
					url: 'common/base64', //仅为示例,非真实的接口地址
					data: {
    
    
						base64: options.base64
					}
				}).then(res=>{
    
    
					// 拿到上传base64图片的网络图片
					console.log(res)
				})
			},
		}
	}
</script>

3. View layer code

The code is as follows (example):

<!-- 视图层script module对应HTML代码中view的id-->
<script module="canvas" lang="renderjs">
	export default {
    
    
		methods: {
    
    
			// 视图层创建base64图片
			create(newValue, oldValue, ownerInstance){
    
    
				// 第一次进入为空不操作
				if(newValue == null){
    
    
					return
				}
				// 在缓存中创建video标签
				var video = document.createElement("VIDEO")
				// 通过setAttribute给video dom元素添加自动播放的属性,因为视频播放才能获取封面图    
				// 设置video自动播放属性
				video.autoplay = true
				// 该设置方法无效
				// video.setAttribute('autoplay', true)
				// 再添加一个静音的属性,否则自动播放会有声音
				// 该设置方法无效
				// video.setAttribute('muted', true)
				video.muted = true
				// 如果报错Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
				// 可以把下面两行代码加上,因为我用的线上video url,所以可能抛出了异常。大概意思就是跨域了toDataURL()使用了外域资源
				video.setAttribute('crossOrigin', 'anonymous')
				video.crossOrigin = '*'
				// 上面我们只是创建了video标签,视频播放需要内部的source的标签,scr为播放源
				video.innerHTML = '<source src=' + newValue.fullurl + ' type="audio/mp4">'
				// 再创建canvas画布标签
				var canvas = document.createElement('canvas');
				var ctx = canvas.getContext('2d');
				// video注册canplay自动播放事件
				// 防止video不播放,所以手动加个播放操作
				video.play()
				// video播放事件
				video.addEventListener('canplay', ()=>{
    
    
					// 创建画布的宽高属性节点,就是图片的大小,单位PX
					var anw = document.createAttribute("width");
					anw.nodeValue = newValue.width;
					var anh = document.createAttribute("height");
					anh.nodeValue = newValue.height;
					canvas.setAttributeNode(anw);
					canvas.setAttributeNode(anh);
					// 画布渲染
					ctx.drawImage(video, 0, 0, newValue.width, newValue.height);
					// 生成base64图片,指定type为jpeg格式生成的图片base64编码会小很多
					var base64 = canvas.toDataURL('image/jpeg') // 这就是封面图片的base64编码
					// 传递数据给逻辑层
					ownerInstance.callMethod('getBase64',{
    
    
						base64: base64
					})
					// 删除创建的video 、canvas dom,要不然重新选取视频生成图片不生效
					// ps:开始有这个问题,但是后面不知道为什么又没有了,如果发现生成第一次base64之后再选择不生效,可以尝试一下把下方注释打开
					// document.body.removeChild(video)
					// document.body.removeChild(canvas)
				})
			}
		}
	}
</script>

提示:本文由本人原创,转载请注明出处!!! 如果本文对你有帮助,请点个赞吧!

achieve effect

1. base64 image effect

insert image description here

2. Online picture effect

insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/qq_44860866/article/details/125746516