uni-app App和H5平台上传视频截取视频第一帧生成图片

本文介绍了如何在uni-app的App和H5平台上,借助renderjs进行视频截取第一帧并生成图片的操作。首先,解释了renderjs在uni-app中的作用,它允许在视图层进行DOM操作。接着,详细展示了从选择视频文件、获取视频信息、上传视频到网络,再到利用renderjs在视图层创建canvas并绘制视频第一帧的完整过程。最后,通过canvas的toDataURL方法生成base64图片,并将其上传到服务器,实现视频帧转为线上图片的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

uni-app App和H5平台使用renderjs上传视频截取视频第一帧生成图片

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



前言

因为uni-app App端没有dom概念,不支持dom操作,并且uni-app的canvas不支持绘制video。renderjs完美解决了uni-app App端的基础dom操作。实现效果在最下方!!


一、renderjs简介

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

renderjs的主要作用有2个:

  • 大幅降低逻辑层和视图层的通讯损耗,提供高性能视图交互能力
  • 在视图层操作dom,运行for web的js库

二、创建index.vue文件,下方代码均在index.vue中

1.HTML代码

代码如下(示例):

<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.逻辑层代码

代码如下(示例):

<!-- 逻辑层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.视图层代码

代码如下(示例):

<!-- 视图层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>

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

实现效果

1.base64图片效果

在这里插入图片描述

2.线上图片效果

在这里插入图片描述
在这里插入图片描述

### uni-app 实现扫描二维码功能教程 #### 1. 前置条件 在实现 `uni-app` 的扫描二维码功能之前,需确认项目已配置好基础环境并支持相关 API 调用。对于 H5 平台而言,由于其限制无法直接调用设备摄像头,因此需要借助第三方插件或其他方式来完成此操作[^3]。 #### 2. 使用 `uni.scanCode()` 方法 `uni-app` 提供了一个内置的方法 `uni.scanCode()` 来快速实现扫码功能。该方法适用于非 H5 平台(如微信小程序、App 等),以下是具体代码示例: ```javascript // 调用 uni.scanCode() 进行扫码 uni.scanCode({ success: function(res) { console.log('条码类型:' + res.scanType); console.log('条码内容:' + res.result); // 输出扫码结果 }, fail: function(err) { console.error('扫码失败', err); } }); ``` 上述代码展示了如何通过 `uni.scanCode()` 获取扫码后的数据,并将其打印到控制台上[^1]。 #### 3. 针对 H5 平台的解决方案 H5 平台不支持直接调用原生 API 如 `uni.scanCode()`,此时可以通过引入 HTML5 `<video>` JavaScript 库(例如 QuaggaJS 或 ZXing.js)来模拟扫码行为[^4]。以下是一个简单的实现思路: - **HTML 结构** ```html <view> <button @click="startScan">开始扫码</button> <canvas id="qr-canvas"></canvas> <!-- 显示视频--> </view> ``` - **JavaScript 处理逻辑** ```javascript export default { methods: { startScan() { const canvas = document.getElementById('qr-canvas'); navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } }) .then(stream => { const video = document.createElement('video'); video.srcObject = stream; video.play(); const ctx = canvas.getContext('2d'); setInterval(() => { canvas.width = video.videoWidth; // 设置画布大小匹配视频尺寸 canvas.height = video.videoHeight; ctx.drawImage(video, 0, 0, canvas.width, canvas.height); this.decodeQRCode(canvas.toDataURL()); }, 1000); // 每秒截取一次画面尝试解码 }).catch(error => { console.error('访问摄像头失败:', error); }); }, decodeQRCode(dataURL) { try { let codeReader = new QRCodeDecoder(); // 假设使用了某个库 codeReader.decodeFromImage(dataURL).then(result => { alert(`解析成功! 内容为 ${result}`); }).catch(e => { console.warn('未检测到有效二维码'); }); } catch (e) { console.error('解码错误:', e); } } } }; ``` 以上代码片段实现了基于浏览器的实时扫码功能,其中涉及到了媒体流捕获以及像处理技术。 #### 4. 总结 综上所述,在开发过程中应区分目标运行环境是否允许直接调用硬件资源。如果是 App 或者小程序场景,则优先考虑官方推荐的方式即 `uni.scanCode()`;而对于纯网页应用来说,则可能需要用到额外的技术手段弥补缺失的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值