当前位置: 首页 > news >正文

记录---Vue3对接UE,通过MQTT完成通讯

🧑‍💻 写在开头

点赞 + 收藏 === 学会🤣🤣🤣

 

概述

一个基于Vue3的实时视频流显示系统,主要用于连接和显示Unreal Engine (UE) 服务器的实时渲染内容。该页面集成了PixelStreaming技术和MQTT通信协议,提供了完整的视频流控制和交互功能。

主要功能

  • 实时视频流显示:连接UE服务器,显示实时渲染的3D场景
  • 协议支持:支持PixelStreaming连接
  • MQTT通信:通过MQTT协议进行消息通信和控制
  • 连接状态监控:实时显示UE和MQTT连接状态
  • 错误处理与重连:自动处理连接错误并尝试重连

快速开始

安装依赖

npm install @epicgames-ps/lib-pixelstreamingfrontend-ue5.3
npm install @epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.3
npm install mqtt

基本使用

  1. 确保UE服务器运行
  2. 确保MQTT服务器运行

技术架构

核心技术栈

  • 前端框架: Vue 3 (Composition API)
  • 视频流技术: Epic Games PixelStreaming
  • 消息协议: MQTT

连接方式

  1. PixelStreaming链接
  2. MQTT连接(消息通信)

代码详情

1. 页面结构

<template>链接链接<div class="scene-display-container"><!-- 连接状态 --><div class="connection-status"><span>UE: {{ ueStatus }}</span><span>MQTT: {{ mqttStatus }}</span></div><!-- 视频流容器 --><div class="video-container"><div id="streamingVideo" class="streaming-video"></div><!-- 错误状态 --><div v-if="errorMessage" class="error-overlay"><p>{{ errorMessage }}</p><button @click="reconnect">重新连接</button></div></div></div>
</template>

说明:

  • connection-status:显示UE和MQTT的连接状态
  • video-container:视频流显示容器
  • error-overlay:错误状态覆盖层,提供重新连接功能

2. 响应式数据

// 响应式数据
const errorMessage = ref('') // 存储错误信息
const ueStatus = ref('未连接') // UE连接状态
const mqttStatus = ref('未连接') // MQTT连接状态// 实例
let pixelStreaming = null // PixelStreaming实例
let mqttClient = null // MQTT客户端实例

3. UE连接初始化

// 初始化UE连接
const initPixelStreaming = () => {try {const style = new PixelStreamingApplicationStyle();style.applyStyleSheet();Logger.SetLoggerVerbosity(1);const config = new Config({ useUrlParams: false });config.setFlagEnabled(Flags.AutoPlayVideo, true);config.setFlagEnabled(Flags.AutoConnect, true);config.setTextSetting(TextParameters.SignallingServerUrl, "此处输入UE服务器地址");config.setFlagEnabled(Flags.HoveringMouseMode, ControlSchemeType.HoveringMouse);config.setFlagEnabled(Flags.MouseInput, true);config.setFlagEnabled(Flags.KeyboardInput, true);config.setFlagEnabled(Flags.TouchInput, true);config.setFlagEnabled(Flags.GamepadInput, false);config.setFlagEnabled(Flags.XRControllerInput, false);pixelStreaming = new PixelStreaming(config);const application = new Application({stream: pixelStreaming,settingsPanelConfig: { isEnabled: false, visibilityButtonConfig: { creationMode: UIElementCreationMode.Disable } },statsPanelConfig: { isEnabled: false, visibilityButtonConfig: { creationMode: UIElementCreationMode.Disable } },fullScreenControlsConfig: { creationMode: UIElementCreationMode.Disable },xrControlsConfig: { creationMode: UIElementCreationMode.Disable },videoQpIndicatorConfig: { disableIndicator: true },});const container = document.getElementById("streamingVideo");if (container) {container.innerHTML = '';container.appendChild(application.rootElement);}setupPixelStreamingEvents();} catch (error) {errorMessage.value = `UE连接失败: ${error}`;}
}

配置说明:

  • AutoPlayVideo: true:自动播放视频
  • AutoConnect: true:自动连接
  • SignallingServerUrl:信令服务器地址
  • HoveringMouseMode:鼠标悬停模式
  • 各种输入控制:鼠标、键盘、触屏等

4. 事件监听器设置

// 设置PixelStreaming事件监听器
const setupPixelStreamingEvents = () => {if (!pixelStreaming) returnpixelStreaming.addEventListener('streamReady', () => {ueStatus.value = '已连接'errorMessage.value = ''})pixelStreaming.addEventListener('connectionEstablished', () => {ueStatus.value = '已连接'errorMessage.value = ''})pixelStreaming.addEventListener('connectionClose', () => {ueStatus.value = '连接断开'})pixelStreaming.addEventListener('connectionError', (error) => {ueStatus.value = '连接失败'errorMessage.value = `UE连接错误: ${error}`})pixelStreaming.addEventListener('webRTCConnected', () => {ueStatus.value = '已连接'})pixelStreaming.addEventListener('webRTCDisconnected', () => {ueStatus.value = '连接断开'})
}

事件说明:

  • streamReady:视频流准备就绪
  • connectionEstablished:连接建立成功
  • connectionClose:连接关闭
  • connectionError:连接错误
  • webRTCConnected:WebRTC连接成功
  • webRTCDisconnected:WebRTC连接断开

5. MQTT连接初始化

// 初始化MQTT连接
const initMqtt = () => {try {const options = {username: 'admin',password: 'public',clientId: `vue_client_${Math.random().toString(16).substr(2, 8)}`,clean: true,reconnectPeriod: 5000,connectTimeout: 30 * 1000,keepalive: 60,protocolVersion: 4}mqttClient = mqtt.connect('此处输入MQTT地址', options) // 地址末尾需要加:/mqttmqttClient.on('connect', () => {mqttStatus.value = '已连接'mqttClient.subscribe('此处输入订阅主题的路径')})mqttClient.on('error', (error) => {mqttStatus.value = '连接失败'})mqttClient.on('close', () => {mqttStatus.value = '连接断开'})mqttClient.on('message', (topic, message) => {// 处理MQTT消息console.log(`收到MQTT消息 [${topic}]: ${message.toString()}`)})} catch (error) {mqttStatus.value = '初始化失败'}
}

MQTT配置说明:

  • username/password:MQTT认证信息
  • clientId:客户端唯一标识
  • reconnectPeriod:重连间隔(5秒)
  • connectTimeout:连接超时(30秒)
  • keepalive:心跳间隔(60秒)

6. 重新连接功能

const reconnect = () => {errorMessage.value = ''if (pixelStreaming) {try {pixelStreaming.close()} catch (error) {console.warn('PixelStreaming断开连接时出错:', error)}pixelStreaming = null}if (mqttClient) {mqttClient.end()mqttClient = null}ueStatus.value = '未连接'mqttStatus.value = '未连接'setTimeout(() => {initPixelStreaming()initMqtt()}, 1000)
}

重连流程:

  1. 清空错误信息
  2. 关闭现有连接
  3. 重置状态
  4. 延迟1秒后重新初始化

7. 生命周期管理

// 生命周期
onMounted(() => {initPixelStreaming()initMqtt()
})onUnmounted(() => {if (pixelStreaming) {try {pixelStreaming.close()} catch (error) {console.warn('PixelStreaming清理时出错:', error)}}if (mqttClient) {mqttClient.end()}
})

说明:

  • onMounted:组件挂载时初始化连接
  • onUnmounted:组件卸载时清理连接

常见问题及解决方案

1. 连接超时问题
// 检查网络连接
const checkNetworkConnection = () => {const testUrl = 'wss://192.168.110.176'const testSocket = new WebSocket(testUrl)testSocket.onopen = () => {console.log('网络连接正常')testSocket.close()}testSocket.onerror = (error) => {console.log(`网络连接失败: ${error}`)console.log('请检查服务器地址和网络连接')}
}
2. MQTT连接失败
// MQTT连接测试
const testMqttConnection = () => {const testClient = mqtt.connect('ws://192.168.110.176:8083/mqtt', {username: 'admin',password: 'public',clientId: `test_client_${Date.now()}`,clean: true,connectTimeout: 5000})testClient.on('connect', () => {console.log('MQTT连接成功')testClient.end()})testClient.on('error', (error) => {console.log(`MQTT连接失败: ${error.message}`)console.log('请检查MQTT服务器状态和认证信息')testClient.end()})
}

自动重连机制

WebSocket自动重连

nativeWebSocket.onclose = (event) => {console.log(`UE WebSocket连接已关闭 (代码: ${event.code})`)isConnected.value = falseconnectionStatus.type = 'danger'connectionStatus.text = '连接断开'// 自动重连if (event.code !== 1000) { // 不是正常关闭console.log('5秒后尝试重新连接...')setTimeout(() => {if (!isConnected.value) {initNativeWebSocket()}}, 5000)}
}

MQTT自动重连

const mqttOptions = {reconnectPeriod: 5000, // 5秒重连间隔connectTimeout: 30 * 1000, // 30秒连接超时keepalive: 60 // 60秒心跳
}

  

本文转载于:https://juejin.cn/post/7550571202013397043

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

http://www.hskmm.com/?act=detail&tid=7462

相关文章:

  • 《Real-Time Rendering》第一章 介绍
  • C语言基础
  • 公益站Agent Router注册送200刀额度竟然是真的
  • 数据集中valid的作用
  • 深入 RocketMQ 核心源码:从环境搭建到高可用设计的全方位解析
  • 单例模式
  • apache修改默认位置
  • 实用指南:YOLOv11的旋转目标检测改进-(扩展检测头支持旋转框预测,适配遥感场景)
  • 从零到顶会:NLP科研实战手册 - 实践
  • 肝不好能喝酒吗
  • ROS中如何将日志格式设置为行号的形式
  • USB相关的sysfs文件(重要的)【转】
  • 25上第一周
  • 深入解析:RxJava在Android中的应用
  • 模型选择与配置说明
  • 梯度下降算法
  • 002_文本分类任务的问答
  • 车牌识别
  • 告别人工标注瓶颈!Reward-RAG:用 CriticGPT 打造更懂人类偏好的检索模型
  • Latex 中百分号怎么打
  • 文件上传-条件竞争绕过
  • 文件包含漏洞
  • 9.17 CSP-S模拟23/多校A层冲刺NOIP2024模拟赛19 改题记录
  • Java基本语法
  • 在AI技术快速实现创想的时代,挖掘前端学习新需求成为关键——某知名编程教育平台需求洞察
  • 负载均衡层详解part3-lvs
  • 4. MySQL 索引优化实战
  • 算法课第一周作业
  • 线段树懒标记模板
  • 谁在我这位置遗留或丢失了一颗口罩爆珠(好像是桃子味)?