uni-app vue3 小程序接入 aliyun-rtc-wx-sdk

安装依赖:

cmd 复制代码
npm install aliyun-rtc-wx-sdk crypto-js

uni-app,新建一个页面,粘贴以下代码

在阿里云实时音视频补充appId、appKey即可,

html 复制代码
<template>
	<view class="container">
		<!-- 用户输入区域 -->
		<view class="input-section" v-if="!isJoined">
			<uni-easyinput
				v-model="channelId"
				placeholder="请输入频道ID"
				:clearable="true"
			/>
			<uni-easyinput
				v-model="userName"
				placeholder="请输入用户名"
				:clearable="true"
			/>
			<uni-easyinput
				v-model="userId"
				placeholder="请输入用户ID"
				:clearable="true"
			/>
			<button @click="joinChannel" type="primary">加入房间</button>
		</view>

		<!-- 直播控制区域 -->
		<view class="control-section" v-if="isJoined">
			<button @click="leaveChannel" type="warn">离开房间</button>
			<button @click="switchCamera">切换摄像头</button>
			<button @click="toggleMic">{{ pusher.enableMic ? '关闭麦克风' : '开启麦克风' }}</button>
			<button @click="toggleCamera">{{ pusher.enableCamera ? '关闭摄像头' : '开启摄像头' }}</button>
		</view>

		<!-- 推流组件 -->
		<live-pusher 
			ref="livePusher"
			:url="pusher.url" 
			:mode="pusher.mode" 
			:autopush="pusher.autopush" 
			:beauty="pusher.beauty"
			:whiteness="pusher.whiteness" 
			:muted="pusher.muted" 
			:mirror="pusher.mirror" 
			:local-mirror="pusher.localMirror"
			:enable-camera="pusher.enableCamera" 
			:enable-mic="pusher.enableMic" 
			:remote-mirror="pusher.remoteMirror"
			:enable-ans="pusher.enableAns" 
			:device-position="pusher.devicePosition" 
			:enable-agc="pusher.enableAgc"
			@statechange="onPusherStateChange" 
			@netstatus="onPusherNetStatus" 
			@error="onPusherError"
			style="width: calc((100vw - 40rpx)); height: calc((100vw - 40rpx)/4*3);" 
			v-if="pusher.url" 
		/>

		拉流组件列表({{ playerList.length }}):
		<view class="player-list" v-if="playerList.length > 0">
			<view v-for="(player, index) in playerList" :key="index" class="player-item">
				<live-player 
					:src="player.src" 
					mode="RTC" 
					autoplay 
					@statechange="onPlayerStateChange" 
					@netstatus="onPlayerNetStatus"
					style="width: calc((50vw - 25rpx)); height: calc((50vw - 25rpx)/4*3);" 
				/>
				<text>{{ player.userName || player.userId }}</text>
			</view>
		</view>

		<!-- 调试信息 -->
		<view class="debug-info">
			<text>房间状态: {{ isJoined ? '已加入' : '未加入' }}</text>
			<text>用户数量: {{ playerList.length }}</text>
		</view>
	</view>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, getCurrentInstance } from 'vue'
import { queryAndGetUserInfo, UserInfo, getUserInfo } from '@/utils/userInfo'
import * as MainApi from './mainApi'
import baseInfo from '@/utils/base'
import { pagesRecords } from '@/hooks/pageRecordsHooks'

// live-pusher  实例,用于切换摄像头
let LivePusher = uni.createLivePusherContext('livePusher')

import AliRtcEngine from "aliyun-rtc-wx-sdk";
import CryptoJS from 'crypto-js';

pagesRecords()

let currentInstance = ref()
const { ctx } = getCurrentInstance() as any

// 响应式数据
const pusher = ref({})
const playerList = ref([])
const isJoined = ref(false)
const userName = ref('')
const userId = ref('')
const appId = ref('')
const appKey = ref('')
const channelId = ref('AliRtcDemo')

let artc: any = null

// 生成Token
const generateToken = (appId: string, appKey: string, channelId: string, userId: string, timestamp: number) => {
	const data = `${appId}${appKey}${channelId}${userId}${timestamp}`;
    const hash = CryptoJS.SHA256(data);
    return hash.toString(CryptoJS.enc.Hex);
}

// 初始化ARTC引擎
const initARTC = async () => {
	try {
		artc = AliRtcEngine.getInstance()
		bindEvents()
		uni.showToast({
			title: 'ARTC引擎初始化成功',
			icon: 'success'
		})
	} catch (error) {
		console.error('ARTC引擎初始化失败:', error)
		uni.showToast({
			title: 'ARTC引擎初始化失败',
			icon: 'error'
		})
	}
}

// 绑定事件监听
const bindEvents = () => {
	// 远程用户上线通知
	artc.on("remoteUserOnLineNotify", (user: any, newPlayerList: any[]) => {		
		uni.showToast({
			title: `${user.displayName || user.userId} 加入了房间`,
			icon: "none",
		})
		playerList.value = newPlayerList
	})

	// 远程用户下线通知
	artc.on("remoteUserOffLineNotify", (user: any, newPlayerList: any[]) => {
		uni.showToast({
			title: `${user.displayName || user.userId} 退出了房间`,
			icon: "none",
		})
		playerList.value = newPlayerList
	})

	// 远程轨道可用通知
	artc.on("remoteTrackAvailableNotify", (user: any, newPlayerList: any[]) => {
		playerList.value = newPlayerList
	})

	// 被踢出房间
	artc.on("bye", () => {
		uni.showToast({
			title: "您已被踢出房间",
			icon: "none",
		})
		pusher.value = {}
		playerList.value = []
		isJoined.value = false
	})
}

// 加入频道
const joinChannel = async () => {
	if (isJoined.value) {
		uni.showToast({
			title: '已在房间中',
			icon: 'none'
		})
		return
	}

	// 检查用户输入
	if (!userName.value.trim()) {
		uni.showToast({
			title: '请输入用户名',
			icon: 'none'
		})
		return
	}

	if (!userId.value.trim()) {
		uni.showToast({
			title: '请输入用户ID',
			icon: 'none'
		})
		return
	}

	uni.showLoading({
		title: '加入房间中...'
	})

	try {
		const timestamp = Math.floor(Date.now() / 1000) + 3600
		const token = generateToken(appId.value, appKey.value, channelId.value, userId.value, timestamp)
		const { pusherAttributes, playerList: newPlayerList } = await artc.joinChannel({
			appId: appId.value,
			appKey: appKey.value,
			channelId: channelId.value,
			userId: userId.value,
			userName: userName.value,
			token: token,
			timestamp: timestamp
		}, userName.value)

		pusher.value = pusherAttributes
		playerList.value = newPlayerList
		isJoined.value = true

		// 开始推流
		artc.getPusherInstance().start()
		uni.hideLoading()
		uni.showToast({
			title: '加入房间成功',
			icon: 'success'
		})
	} catch (error) {
		uni.hideLoading()
		console.error('加入房间失败:', error)
		uni.showToast({
			title: '加入房间失败',
			icon: 'error'
		})
	}
}

// 离开频道
const leaveChannel = async () => {
	if (!isJoined.value) {
		return
	}

	try {
		await artc.leaveChannel()
		pusher.value = {}
		playerList.value = []
		isJoined.value = false
		uni.showToast({
			title: '已离开房间',
			icon: 'success'
		})
	} catch (error) {
		console.error('离开房间失败:', error)
	}
}

// 切换摄像头
const switchCamera = () => {
	LivePusher.switchCamera()
}

// 切换麦克风
const toggleMic = () => {
	pusher.value.enableMic = !pusher.value.enableMic
}

// 切换摄像头
const toggleCamera = () => {
	pusher.value.enableCamera = !pusher.value.enableCamera
}

// live-pusher 状态变化处理
const onPusherStateChange = (e: any) => {
	console.log("live-pusher code: ", e.detail.code)
	artc.handlePusherStateChange(e)
}

// live-pusher 网络状态处理
const onPusherNetStatus = (e: any) => {
	console.log("live-pusher netStatus: ", e.detail.info)
	artc.handlePusherNetStatus(e)
}

// live-pusher 错误处理
const onPusherError = (e: any) => {
	artc.handlePusherError(e)
}

// live-player 状态变化处理
const onPlayerStateChange = (e: any) => {
	console.log("live-player code: ", e.detail.code)
	artc.handlePlayerStateChange(e)
}

// live-player 网络状态处理
const onPlayerNetStatus = (e: any) => {
	console.log("live-player netStatus: ", e.detail.info)
	artc.handlePlayerNetStatus(e)
}

// 生命周期
onMounted(() => {
	initARTC()
})

onUnmounted(() => {
	leaveChannel()
})
</script>

<style scoped lang="scss">
.container {
	padding: 20rpx;
}

.input-section {
	margin-bottom: 30rpx;
	
	.uni-easyinput {
		margin-bottom: 20rpx;
	}
	
	button {
		margin-top: 20rpx;
	}
}

.control-section {
	display: flex;
	flex-wrap: wrap;
	gap: 10rpx;
	margin-bottom: 30rpx;
	
	button {
		font-size: 24rpx;
		flex: 1;
		padding: 0;
	}
}

.player-list {
	display: flex;
	flex-wrap: wrap;
	gap: 10rpx;
	margin-top: 30rpx;
	
	.player-item {
		text-align: center;
		
		text {
			display: block;
			margin-top: 10rpx;
			font-size: 24rpx;
			color: #666;
		}
	}
}

.debug-info {
	margin-top: 30rpx;
	padding: 20rpx;
	background-color: #f5f5f5;
	border-radius: 10rpx;
	
	text {
		display: block;
		margin-bottom: 10rpx;
		font-size: 24rpx;
		color: #333;
	}
}
</style>

userName、userId随便写,不重复即可,想进入同一个频道就让channelId一致,

相关推荐
云起SAAS24 分钟前
躺平发育小游戏微信抖音流量主小程序开源
小程序·躺平发育小游戏微信抖音流
胡斌附体28 分钟前
小程序省市级联组件使用
前端·javascript·小程序·uniapp·picker级联组件
weixin_1772972206911 小时前
短剧小程序系统开发:技术驱动下的内容创新之路
小程序·语音交友
老华带你飞11 小时前
健身管理|基于java的健身管理系统小程序(源码+数据库+文档)
java·数据库·小程序·vue·论文·毕设·健身管理系统小程序
2501_9160088911 小时前
iOS混淆工具有哪些?在集成第三方 SDK 时的混淆策略与工具建议
android·ios·小程序·https·uni-app·iphone·webview
weixin_1772972206911 小时前
盲盒抽卡机小程序系统开发:打造个性化娱乐新平台
小程序·娱乐
个人看法11 小时前
小程序中,给一段富文本字符串文案特殊内容加样式监听点击事件
小程序
2501_9159214311 小时前
Windows 如何上架 iOS 应用?签名上传全流程 + 工具推荐
android·ios·小程序·https·uni-app·iphone·webview
雪芽蓝域zzs13 小时前
uniapp 数组的用法
前端·javascript·uni-app