Vue3对接UE,通过MQTT完成通讯
概述
一个基于Vue3的实时视频流显示系统,主要用于连接和显示Unreal Engine (UE) 服务器的实时渲染内容。该页面集成了PixelStreaming技术和MQTT通信协议,提供了完整的视频流控制和交互功能。
主要功能
- 实时视频流显示:连接UE服务器,显示实时渲染的3D场景
- 协议支持:支持PixelStreaming连接
- MQTT通信:通过MQTT协议进行消息通信和控制
- 连接状态监控:实时显示UE和MQTT连接状态
- 错误处理与重连:自动处理连接错误并尝试重连
快速开始
安装依赖
bash
npm install @epicgames-ps/lib-pixelstreamingfrontend-ue5.3
npm install @epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.3
npm install mqtt
基本使用
- 确保UE服务器运行
- 确保MQTT服务器运行
技术架构
核心技术栈
- 前端框架: Vue 3 (Composition API)
- 视频流技术: Epic Games PixelStreaming
- 消息协议: MQTT
连接方式
- PixelStreaming链接
- MQTT连接(消息通信)
代码详情
1. 页面结构
vue
<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. 响应式数据
javascript
// 响应式数据
const errorMessage = ref('') // 存储错误信息
const ueStatus = ref('未连接') // UE连接状态
const mqttStatus = ref('未连接') // MQTT连接状态
// 实例
let pixelStreaming = null // PixelStreaming实例
let mqttClient = null // MQTT客户端实例
3. UE连接初始化
javascript
// 初始化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. 事件监听器设置
javascript
// 设置PixelStreaming事件监听器
const setupPixelStreamingEvents = () => {
if (!pixelStreaming) return
pixelStreaming.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连接初始化
javascript
// 初始化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) // 地址末尾需要加:/mqtt
mqttClient.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. 重新连接功能
javascript
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秒后重新初始化
7. 生命周期管理
javascript
// 生命周期
onMounted(() => {
initPixelStreaming()
initMqtt()
})
onUnmounted(() => {
if (pixelStreaming) {
try {
pixelStreaming.close()
} catch (error) {
console.warn('PixelStreaming清理时出错:', error)
}
}
if (mqttClient) {
mqttClient.end()
}
})
说明:
onMounted
:组件挂载时初始化连接onUnmounted
:组件卸载时清理连接
常见问题及解决方案
1. 连接超时问题
javascript
// 检查网络连接
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连接失败
javascript
// 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自动重连
javascript
nativeWebSocket.onclose = (event) => {
console.log(`UE WebSocket连接已关闭 (代码: ${event.code})`)
isConnected.value = false
connectionStatus.type = 'danger'
connectionStatus.text = '连接断开'
// 自动重连
if (event.code !== 1000) { // 不是正常关闭
console.log('5秒后尝试重新连接...')
setTimeout(() => {
if (!isConnected.value) {
initNativeWebSocket()
}
}, 5000)
}
}
MQTT自动重连
javascript
const mqttOptions = {
reconnectPeriod: 5000, // 5秒重连间隔
connectTimeout: 30 * 1000, // 30秒连接超时
keepalive: 60 // 60秒心跳
}