uniapp H5 对接 声网,截图

文章目录

  • 安装依赖
  • 创建容器
    • 容器样式
  • 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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Vue】vue-router使用addRoute动态加载路由后刷新页面404

场景&#xff1a;动态加载路由&#xff0c;点击菜单路由跳转正常&#xff0c;但刷新页面报404 原因&#xff1a;使用404做异常路由捕获 刷新页面会导致路由丢失&#xff0c;重建路由时先加载了静态路由&#xff08;包含异常路由捕获404&#xff09;&#xff0c;此时动态路由还未…

USB射频微波功率计的功能与优势-盛铂科技

USB射频功率计是一种用于测量射频信号&#xff08;RF&#xff09;功率的仪器&#xff0c;它通过USB接口与计算机或其他设备连接&#xff0c;以便于进行数据采集、处理和显示。 主要功能 功率测量&#xff1a;能够测量射频信号的功率&#xff0c;通常以毫瓦&#xff08;mW&…

【Vim Masterclass 笔记01】Section 1:Course Overview + Section 2:Vim Quickstart

文章目录 Section 1&#xff1a;Course Introduction 课程概述S01L01 Course Overview 课程简介课程概要 S01L02 Course Download 课程资源下载S01L03 What Vim Is and Why You Should Learn It 何为 Vim&#xff1f;学来干啥&#xff1f;1 何为 Vim2 为何学 Vim Section 2&…

Elasticsearch JavaRestClient版

文章目录 初始化RestHighLeveClient&#xff08;必要条件&#xff09;索引库操作1.创建索引库&#xff08;4步&#xff09;2.删除索引库&#xff08;3步&#xff09;3.判断索引库是否存在&#xff08;3步&#xff09;4.总结&#xff1a;四步走 文档操作1.创建文档&#xff08;4…

基于Pytorch和yolov8n手搓安全帽目标检测的全过程

一.背景 还是之前的主题&#xff0c;使用开源软件为公司搭建安全管理平台&#xff0c;从视觉模型识别安全帽开始。主要参考学习了开源项目 https://github.com/jomarkow/Safety-Helmet-Detection&#xff0c;我是从运行、训练、标注倒过来学习的。由于工作原因&#xff0c;抽空…

driftingblues6靶机

打开靶场 查看页面源代码&#xff0c;最下面有一个注释&#xff0c;提供了一个网址 vmlist.github.io&#xff0c;我们去访问一下 这里是一个github页面&#xff0c;提供攻防虚拟机的下载&#xff0c;对我们解题并没有什么有用的信息&#xff0c;我们再去扫描端口 发现只有80端…

python学习笔记—12—布尔类型、if语句

1. 布尔类型 (1) 定义 (2) 比较运算符 (3) 代码演示 1. 手动定义 bool_1 True bool_2 False print(f"bool_1的内容是&#xff1a;{bool_1}, 类型是&#xff1a;{type(bool_1)}") print(f"bool_2的内容是&#xff1a;{bool_2}, 类型是&#xff1a;{type(bool…

EasyExcel自定义动态下拉框(附加业务对象转换功能)

全文直接复制粘贴即可&#xff0c;测试无误 一、注解类 1、ExcelSelected.java 设置下拉框 Documented Target({ElementType.FIELD})//用此注解用在属性上。 Retention(RetentionPolicy.RUNTIME)//注解不仅被保存到class文件中&#xff0c;jvm加载class文件之后&#xff0c…

Fetch处理大模型流式数据请求与解析

为什么有的大模型可以一次返回多个 data&#xff1f; Server-Sent Events (SSE)&#xff1a;允许服务器连续发送多个 data: 行&#xff0c;每个代表一个独立的数据块。 流式响应&#xff1a;大模型服务通常以流式响应方式返回数据&#xff0c;提高响应速度。 批量处理&#x…

开源低代码平台-Microi吾码-一键安装使用(CentOS一键安装MySql+Redis+MinIO+MongoDB+Watchtower脚本)

开源低代码平台-Microi吾码-一键安装使用 前言CentOS7一键安装脚本注意事项&#xff1a;安装成功预览图安装过程图安装结果docker脚本代码【有点东西&#xff1a;&#xff09;】踩过的坑开源低代码平台Microi吾码-系列文档 前言 有小伙伴提出他并不想在本地编译代码、打包镜像、…

Ubuntu 24.04 LTS 解决网络连接问题

1. 问题描述 现象&#xff1a;ens33 网络接口无法获取 IPv4 地址&#xff0c;导致网络不可用。初步排查&#xff1a; 运行 ip a&#xff0c;发现 ens33 接口没有分配 IPv4 地址。运行 ping www.baidu.com&#xff0c;提示“网络不可达”。查看 NetworkManager 日志&#xff0c…

Docker--Docker Container(容器) 之 操作实例

容器的基本操作 容器的操作步骤其实很简单&#xff0c;根据拉取的镜像&#xff0c;进行启动&#xff0c;后可以查看容器&#xff0c;不用时停止容器&#xff0c;删除容器。 下面简单演示操作步骤 1.创建并运行容器 例如&#xff0c;创建一个名为"my-nginx"的交互…

大模型WebUI:Gradio全解系列8——Additional Features:补充特性(上)

大模型WebUI&#xff1a;Gradio全解系列8——Additional Features&#xff1a;补充特性&#xff08;上&#xff09; 前言本篇摘要8. Additional Features&#xff1a;补充特性8.1 队列8.1.1 使用方法8.1.2 配置队列演示 8.2 输入输出流8.2.1 输出流1. 生成器yield2. 流媒体 8.2…

leetcode 2658. 网格图中鱼的最大数目

题目如下 数据范围 使用并查集来做这道题。 其实按照题目的意思就是让我们求每一个联通的水域可以捞到的最大权值。 我们可以从前往后遍历这个二维数组只需要判断前一个水域和上一个水域是否和当前的(i, j)联通如果有则合并水域&#xff0c;同时用一个weight数组保存每一个联…

【go每日一题】golang异常、错误 {源码、实践、总结}

错误与异常在golang中区分 Go 的错误处理设计与其他语言的异常不同。Go 中的 error 就是一个普通的值对象&#xff0c;而其他语言如 Java 中的 Exception 将会造成程序控制流的终止和其他行为&#xff0c;Exception 与普通的值不同。虽然 Go 也有类似的异常机制 —— panic&am…

大模型 Fine-Tuning 技术解析

引言 在大型语言模型&#xff08;LLMs, Large Language Models&#xff09;的发展历程中&#xff0c;预训练模型和微调&#xff08;Fine-tuning&#xff09;技术起到了至关重要的作用。这些技术使得模型不仅能够学习到丰富的语言特征&#xff0c;还能根据具体任务进行优化调整…

LabVIEW开发中常见硬件通讯接口快速识别

在 LabVIEW 开发中&#xff0c;与硬件进行通讯是实现数据采集与控制的重要环节。准确判断通讯接口类型和协议&#xff0c;可以提高开发效率&#xff0c;减少调试时间。本文结合 LabVIEW 的实际应用&#xff0c;详细介绍如何识别和判断常见硬件通讯接口的定义&#xff0c;并提供…

抖音短视频矩阵系统源码开发全流程解析

在项目开发过程中&#xff0c;调整配置文件至关重要&#xff0c;这些文件包括数据库连接、API密钥及全局参数等。通过正确配置这些信息&#xff0c;可确保应用程序的稳定性和安全性。灵活调整配置以适应具体需求有助于短视频矩阵系统项目的顺利推进。 在开发环境中&#xff0c…

Unity功能模块一对话系统(4)实现个性文本标签

本期我们将了解如何在TMPro中自定义我们的标签样式&#xff0c;并实现两种有趣的效果。 一.需求描述 1.定义<float>格式的标签&#xff0c;实现标签处延迟打印功能 2.定义<r" "></r>格式的标签&#xff0c;实现标签区间内文本片段的注释显示功能…

深度学习实战自动驾驶目标识别

本文采用YOLOv8作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv8以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对BDD100K自动驾驶目标数据集进行训练和优化&#xff0c;该数据集包含丰富的自动驾…