uniapp H5 对接 声网,截图

news2025/1/5 15:20:31

文章目录

  • 安装依赖
  • 创建容器
    • 容器样式
  • javascript代码
    • ImageDataToBlob 方法
  • 控制控制台LOG输出

安装依赖

  • 版本"agora-rtc-sdk-ng": "^4.22.0",

创建容器

<template>
	<view class="videoValue " id="videoValue">
		<u-toast ref="uToast"></u-toast>
		<view @click="screenshot()">
			截图
		</view>
	</view>
</template>

容器样式

Hbuilder X 默认支持 less 语法

<style lang="less" scoped>
	.videoValue {
		width: 100%;
		height: 100%;
	}
</style>

javascript代码

  • 导入 agora-rtc-sdk-ng
  • 创建声网视频实例 AgoraRTC.createClient
<script>
	import AgoraRTC from 'agora-rtc-sdk-ng';
	import {
		wuRenJiApi
	} from '@/api/wu-ren-ji.js'
	// 机场直播声网
	const client = AgoraRTC.createClient({
		codec: 'vp9',// codec 设置支持 "vp8" (VP8)、"h264"(H.264) 具体差别自行研究
		mode: 'live', // "rtc"(通信场景) 和 "live"(直播场景)
		mediaType: 'video',
	});
	
	let userClient;
	// 当远端用户成功发布音视频轨道之后,SDK 会触发 user-published 事件。
	// 这个事件携带两个参数:远端用户对象 (user) 和远端发布的媒体类型 (mediaType)。
	// 此时,你可以调用 AgoraRTCClient.subscribe 发起订阅。
	client.on('user-published', async (user, mediaType) => {
		await client.subscribe(user, mediaType)
		if (mediaType === 'video') {
			await user.videoTrack.play('videoValue');
			userClient = user.videoTrack // 获取当前渲染的视频帧数据
		}
	});

	export default {
		data() {
			return {
				snObj: null,
				videoUser: null,
				shootErrorCount: 0, // 拍摄错误次数
				screenShotCount: 30,
				screenShotTimer: null
			}
		},
		mounted() {
			let snObj = uni.getStorageSync('snObj')
			// snObj 主要包含1个关键参数 deviceSn
			/**
				{
				    "createName": null,
				    "createDatetime": "2024-10-30 10:57:36",
				    "updateName": null,
				    "deviceSn": "7CTxxxxxx1",
				}
			*/
			
			this.snObj = snObj
			this.playVideo()
		},
		methods: {
			playVideo() {
				this.openJiChangZhiBo()
			},

			// 机场
			async openJiChangZhiBo() {
				let option = uni.getStorageSync('option')
				// option 包含3个关键参数 deviceSn
			/**
				{
				    "token":"++/a1oP903NnBxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxACwS3Nn",
				    "appId": "fcb7ca994xxxxxxxxxxxxxxx08b",
				    "channel": "7Cxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-0"
				}
			*/
				await this.startDockerLive(1) // 连接设备
				if (option.appId && option.channel && option.token) {
					// 这一步可有可无,(离开频道),一般用于在切换页面的时候,
					// 也就是路由改变离开频道不会导致视频一直在播放,从而减少消耗费用
					await this.leave(); 
					// // 获得token渲染直播画面 连接声网实例视频
					const uid = await client.join(
						option.appId,
						option.channel,
						option.token,
						null // 设置null 或者不设置 自动分配数字 UID
					);
				} else {
					console.error('option', option);
				}
			},
			// 控制机场直播 0断开 1连接
			async startDockerLive(op = 0) {
				try {
					const data = await api.startLive({
						dockSN: this.snObj.deviceSn,
						op: op,
					}).catch(err => {
						throw new Error('控制机场直播 断开/连接抛异常' + err)
					});
					if (op === 1) {
						return data;
					}

				} catch (error) {
					console.error(error);
				}
			},
			async level() {
				await client.leave();
			},
			// 截图
			async screenshot() {
				try {
					if (this.shootErrorCount >= 5) {
					// uview框架
						this.$refs.uToast.show({
							message: `拍摄错误超过5次,请等待${this.screenShotCount}s后重试`
						})
						this.createInteVal()
						return
					}
					this.$refs.uToast.show({
						loading: true,
						message: '拍摄中...',
						type: "loading",
						duration: 1000 * 10
					})
					const resImg = await userClient.getCurrentFrameData()
					const blobData = await ImageDataToBlob(resImg) // 自行写个js文件吧代码粘过去引入

					// 创建一个 FileReader 对象
					const reader = new FileReader();
					// 定义读取完成后的回调
					reader.onloadend = async () => {
						// 获取转换后的 Base64 编码数据 
						// 这里已经是base64了,在浏览器可以直接打开看,
						// 但是因为url限制,无法看全,可以直接存到服务器,
						// 然后范围服务器的图片地址,或者是转File文件流传输到服务器
						const base64String = reader.result;
						let fileUrl = await this.uploadFile(base64String) // 这里我是把文件上传到服务器
						const data = await api.screenshot({
							fileName: fileUrl,
							deviceSn: this.snObj.deviceSn,
						}).catch(err => {
							this.shootErrorCount += 1
							this.$refs.uToast.show({
								message: "拍摄上传抛异常,原因:" + JSON.stringify(err),
								duration: 1000 * 3
							})
							throw new Error('上传抛异常' + JSON.stringify(err));
						})
						if (data.code === 200) {
							this.$refs.uToast.show({
								message: "拍摄成功,请前往我的相册查看",
								position: "center",
								duration: 1000 * 1.5
							})
						} else {
							this.$refs.uToast.show({
								message: "拍摄失败,原因:" + JSON.stringify(data.msg),
								duration: 1000 * 3
							})
							this.shootErrorCount += 1
						}
					};
					reader.readAsDataURL(blobData)
				} catch (e) {
					this.shootErrorCount += 1
					this.$refs.uToast.show({
						message: "拍摄失败,原因:" + JSON.stringify(data.msg),
						duration: 1000 * 3
					})
					console.error(e)
				}
			},
			clearInterval() {
				if (this.screenShotTimer) {
					return
				}
				this.screenShotCount -= 1
				this.screenShotTimer = setInterval(() => {
					if (this.screenShotCount > 0) {
						this.screenShotCount -= 1
					} else {
						clearInterval(this.screenShotTimer)
						this.screenShotTimer = null
						this.shootErrorCount = 0
					}
				}, 1000)
			}
		},
	}
</script>


ImageDataToBlob 方法

// Uint8ClampedArray 转blob
export function ImageDataToBlob(imageData) {
	let w = imageData.width;
	let h = imageData.height;
	let canvas = document.createElement('canvas');
	canvas.width = w;
	canvas.height = h;
	let ctx = canvas.getContext('2d');
	ctx.putImageData(imageData, 0, 0);
	return new Promise((resolve) => {
		canvas.toBlob(resolve);
	});
};

控制控制台LOG输出

AgoraRTC.setLogLevel(Number)
SDK 日志输出级别。按照输出日志最全到最少排列:

  • 0: DEBUG。输出所有的 SDK 日志。
  • 1: INFO。输出 INFO、WARNING 和 ERROR 级别的日志。
  • 2: WARNING。输出 WARNING 和 ERROR 级别的日志。
  • 3: ERROR。输出 ERROR 级别的日志。
  • 4: NONE。不输出日志。
    例如,如果你输入代码 AgoraRTC.setLogLevel(2);,就可以只看到WARNING 和 ERROR 级别的日志信息。

创建实例之前设置log

<script>
		AgoraRTC.setLogLevel(2)
		// 航线直播声网
		const client = AgoraRTC.createClient({
			codec: 'vp9',
			mode: 'live',
		});
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2270243.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

go项目使用gentool生成model的gen.go问题

Gen Tool 是一个没有依赖关系的二进制文件&#xff0c;可以用来从数据库生成结构。 使用方法&#xff1a; go install gorm.io/gen/tools/gentoollatest在项目根目录,执行连接的数据库中指定某几张表结构生成数据库model层 gentool -dsn "root:123456tcp(localhost:330…

家政上门小程序如何创建?家政服务怎么能少了小程序帮手

在如今这个“忙到没时间打扫”的时代&#xff0c;家政服务变得越来越受欢迎。为了提高效率、减少沟通成本&#xff0c;很多家政公司都已经开始借助小程序的力量。那么&#xff0c;家政上门小程序到底该如何创建呢?小程序又是如何帮助家政服务更好地满足客户需求的呢?本文将为…

破解密码

rhel8/centos8 重置 root 密码 方法 1 &#xff1a; rd.break 第 1 步 重启系统&#xff0c;在下图所示界面按 e 键 第2步 找到linux这行&#xff0c;末尾空格后 输入 rd.break 第3步 查看&#xff0c;可选步骤 这里 sysroot 是以只读的形式挂载的&#xff0c;所以要以可读可…

本地小主机安装HomeAssistant开源智能家居平台打造个人AI管家

文章目录 前言1. 添加镜像源2. 部署HomeAssistant3. HA系统初始化配置4. HA系统添加智能设备4.1 添加已发现的设备4.2 添加HACS插件安装设备 5. 安装cpolar内网穿透5.1 配置HA公网地址 6. 配置固定公网地址 前言 大家好&#xff01;今天我要向大家展示如何将一台迷你的香橙派Z…

自学记录鸿蒙API 13:实现多目标识别Object Detection

起步&#xff1a;什么叫多目标识别&#xff1f; 无论是生活中的动物识别、智能相册中的场景分类&#xff0c;还是工业领域的检测任务&#xff0c;都能看到多目标识别的身影。这次&#xff0c;我决定通过学习HarmonyOS最新的Object Detection API&#xff08;API 13&#xff09…

javaEE-多线程进阶-JUC的常见类

juc:指的是java.util.concurrent包&#xff0c;该包中加载了一些有关的多线程有关的类。 目录 一、Callable接口 FutureTask类 参考代码&#xff1a; 二、ReentrantLock 可重入锁 ReentrantLock和synchronized的区别&#xff1a; 1.ReentantLock还有一个方法&#xff1a…

fpga系列 HDL:ModelSim显示模拟波形+十进制格式数值(临时方法和设置持久化的默认值)

模拟波形 FPGA中使用数字滤波器时&#xff0c;可通过观察模拟波形更好地查看滤波效果。可以通过ModelSim中的波形格式设置来实现更直观的波形显示。右键波形->Format-> Analog 效果 数值格式显示 不同的数值格式显示&#xff1a;右键波形->Radix-> Decimal 效果…

Linux 中 sysctl 和 systemctl 有什么区别?

sysctl 和 systemctl 是两个不同的命令行工具&#xff0c;它们在 Linux 系统中分别用于不同的目的。理解这两个命令的区别对于系统管理和配置非常重要。 1. sysctl 功能 用途&#xff1a;sysctl 用于动态地修改内核参数&#xff0c;这些参数控制着操作系统的某些行为。配置文…

【ArcGISPro/GeoScenePro】检查并处理高程数据

数据 https://arcgis.com/sharing/rest/content/items/535efce0e3a04c8790ed7cc7ea96d02d/data 数字高程模型 (DEM) 是一种栅格,可显示地面或地形的高程。 数字表面模型 (DSM) 是另一种高程栅格,可显示表面的高度,例如建筑物或树冠的顶部。 您需要准备 DEM 和 DSM 以供分析…

Redis数据库主要数据结构类型

Redis数据库提供了丰富多样的数据结构类型&#xff0c;以满足不同场景下的数据存储需求。以下是Redis中的主要数据结构类型&#xff1a; 一、五种基础数据结构 字符串&#xff08;String&#xff09; 简介&#xff1a;字符串是Redis最基本的数据类型&#xff0c;可以存储字符串…

基于Springboot + vue实现的校园周边美食探索及分享平台

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(1):Oracle Dataguard 概述

Oracle Dataguard&#xff08;主库为 Oracle 11g 单节点&#xff09;配置详解&#xff08;1&#xff09;&#xff1a;Oracle Dataguard 概述 目录 Oracle Dataguard&#xff08;主库为 Oracle 11g 单节点&#xff09;配置详解&#xff08;1&#xff09;&#xff1a;Oracle Data…

mapbox基础,测面功能实现

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️Turf 框架二、🍀测面功能实现1. ☘️实现思路2. ☘️代码样例一、🍀…

基于下垂控制的构网变换器功率控制【微电网变流器】【Simulink】

目录 主要内容 理论研究 整体模型 PQ计算模块 功率控制模块 PWM反馈模块 结果一览 下载链接 主要内容 该仿真针对微电网中分布式电源接入后产生的谐波影响&#xff0c;除了污染网络外&#xff0c;还会恶化微电网变流器输出电流&#xff0c;为了消除谐波影响&a…

2025差旅平台推荐:一体化降本30%

医药行业因其高度专业化的特点&#xff0c;同时在运营过程中又极为依赖供应链和销售网络&#xff0c;因此差旅管理往往成为成本控制的重要环节。本期&#xff0c;我们以差旅平台分贝通签约伙伴——某知名药企为例&#xff0c;探讨企业如何通过差旅一体化管理&#xff0c;在全流…

【漫话机器学习系列】027.混淆矩阵(confusion matrix)

混淆矩阵&#xff08;Confusion Matrix&#xff09; 混淆矩阵是机器学习中评估分类模型性能的一种工具&#xff0c;特别是在多类别分类问题中。它通过对比模型预测结果和真实标签&#xff0c;帮助我们理解模型的分类效果。 1. 混淆矩阵的结构 混淆矩阵通常是一个二维表格&am…

【AIGC】 ChatGPT实战教程:如何高效撰写学术论文引言

&#x1f4a5; 欢迎来到我的博客&#xff01;很高兴能在这里与您相遇&#xff01; 首页&#xff1a;GPT-千鑫 – 热爱AI、热爱Python的天选打工人&#xff0c;活到老学到老&#xff01;&#xff01;&#xff01;导航 - 人工智能系列&#xff1a;包含 OpenAI API Key教程, 50个…

redis的学习(二)

4 哈希表 哈希类型中的映射关系通常称为field-value&#xff0c;⽤于区分Redis整体的键值对&#xff08;key-value&#xff09;&#xff0c; 注意这⾥的value是指field对应的值&#xff0c;不是键&#xff08;key&#xff09;对应的值&#xff0c; 4.1 操作命令 hset&#xff…

IT运维的365天--024 闲置路由器关闭了dhcp,如何知道它的IP是啥

有时候各种原因&#xff0c;我们关闭了路由器的Dhcp&#xff0c;比如需要获取的无线IP和有线同一个网段的情况。时间久了&#xff0c;如果没做标记&#xff0c;大部分时候就会忘了路由器原来设置的是什么IP&#xff0c;没有路由器的对应IP&#xff0c;自然也无法进路由器后台去…

统信系统设置代理的问题

统信系统设置代理的问题 问题表现方式一方式二 问题表现 统信系统下有系统代理和应用代理两个代理。设置系统代理时&#xff0c;git不能经过代理拉取代码。但是设置应用代理时&#xff0c;可以用git通过代理拉代码。 这是系统代理&#xff0c;在这里设置 ip 端口&#xff0c;…