|
|
@@ -193,7 +193,26 @@
|
|
|
|
|
|
<!-- 使用跨平台视频播放组件 -->
|
|
|
<!-- #ifdef H5 -->
|
|
|
- <view v-if="isPlaying" class="h5-video-wrapper">
|
|
|
+ <!-- iOS H5:使用 video 直接播放 HLS(绕过 Jessibuca + wss_flv) -->
|
|
|
+ <video
|
|
|
+ v-if="isPlaying && isH5IOS"
|
|
|
+ id="h5IosVideo"
|
|
|
+ class="video-player"
|
|
|
+ :src="getIOSH5StreamUrl"
|
|
|
+ :autoplay="true"
|
|
|
+ :controls="true"
|
|
|
+ :show-center-play-btn="true"
|
|
|
+ :enable-progress-gesture="false"
|
|
|
+ :object-fit="'contain'"
|
|
|
+ @error="onVideoError"
|
|
|
+ @play="onVideoPlay"
|
|
|
+ @pause="onVideoPause"
|
|
|
+ @ended="onVideoEnded"
|
|
|
+ @timeupdate="onTimeUpdate"
|
|
|
+ @fullscreenchange="onFullscreenChange"
|
|
|
+ ></video>
|
|
|
+ <!-- 非 iOS H5:使用 Jessibuca + wss_flv(保持安卓/PC 原有逻辑) -->
|
|
|
+ <view v-else-if="isPlaying && !isH5IOS" class="h5-video-wrapper">
|
|
|
<Jessibuca ref="jessibucaRef" :videoUrl="getH5StreamUrl" :hasAudio="true" @error="onVideoError" />
|
|
|
</view>
|
|
|
<!-- #endif -->
|
|
|
@@ -262,7 +281,7 @@
|
|
|
|
|
|
<view class="control-row bottom-controls">
|
|
|
<!-- 只在播放时显示时间码 -->
|
|
|
- <view v-if="isPlaying" class="video-time">{{ currentTime }}</view>
|
|
|
+ <view v-if="isPlaying && !isH5IOS" class="video-time">{{ currentTime }}</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
@@ -600,6 +619,7 @@ const isFullscreen = ref(false)
|
|
|
const isPlaying = ref(false)
|
|
|
const livePlayerContext = ref(null) // 小程序视频上下文
|
|
|
const appLivePlayerContext = ref(null) // App端视频上下文
|
|
|
+const h5IosVideoContext = ref(null) // H5 iOS video 上下文
|
|
|
const jessibucaRef = ref(null)
|
|
|
|
|
|
const isMuted = ref(false)
|
|
|
@@ -608,6 +628,44 @@ const isVoiceActive = ref(false)
|
|
|
const isGridView = ref(false)
|
|
|
const isZoomMode = ref(false)
|
|
|
const currentTime = ref('14:30:25')
|
|
|
+
|
|
|
+// ===== 平台识别:iPhone / iOS 设备判断 =====
|
|
|
+const isIOSDevice = computed(() => {
|
|
|
+ // #ifdef H5
|
|
|
+ const ua = navigator.userAgent.toLowerCase()
|
|
|
+ return /iphone|ipad|ipod/.test(ua)
|
|
|
+ // #endif
|
|
|
+ // #ifdef APP-PLUS
|
|
|
+ const platform = uni.getSystemInfoSync().platform
|
|
|
+ return platform === 'ios'
|
|
|
+ // #endif
|
|
|
+ return false
|
|
|
+})
|
|
|
+
|
|
|
+const isIPhoneH5 = computed(() => {
|
|
|
+ // #ifdef H5
|
|
|
+ const ua = navigator.userAgent.toLowerCase()
|
|
|
+ return /iphone/.test(ua) && !/ipad|ipod/.test(ua)
|
|
|
+ // #endif
|
|
|
+ return false
|
|
|
+})
|
|
|
+
|
|
|
+const isIPadH5 = computed(() => {
|
|
|
+ // #ifdef H5
|
|
|
+ const ua = navigator.userAgent.toLowerCase()
|
|
|
+ return /ipad/.test(ua)
|
|
|
+ // #endif
|
|
|
+ return false
|
|
|
+})
|
|
|
+
|
|
|
+// H5 iOS 设备(包括 iPhone 和 iPad)
|
|
|
+const isH5IOS = computed(() => {
|
|
|
+ // #ifdef H5
|
|
|
+ const ua = navigator.userAgent.toLowerCase()
|
|
|
+ return /iphone|ipad|ipod/.test(ua)
|
|
|
+ // #endif
|
|
|
+ return false
|
|
|
+})
|
|
|
// 响应式数据
|
|
|
const deviceInfo = reactive({
|
|
|
deviceId: '34020000001110000001',
|
|
|
@@ -619,7 +677,11 @@ const deviceInfo = reactive({
|
|
|
deviceTypeId: null,
|
|
|
streamUrl: '',
|
|
|
channelId: null, // 当前通道ID
|
|
|
- originalStreamUrl: '',
|
|
|
+ // ===== 流地址:分格式保存,不再互相覆盖 =====
|
|
|
+ originalStreamUrl: '', // 兼容旧逻辑
|
|
|
+ wsFlvStreamUrl: '', // wss_flv 流地址(安卓 H5 用)
|
|
|
+ hlsStreamUrl: '', // hls 流地址(iOS H5 / 小程序 / App iOS 用)
|
|
|
+ fmp4StreamUrl: '', // fmp4 流地址(App Android 用)
|
|
|
})
|
|
|
const MOCK_TRACE_DETAILS = {
|
|
|
normal: {
|
|
|
@@ -902,16 +964,34 @@ reportPending: {
|
|
|
document.head.appendChild(script)
|
|
|
// #endif
|
|
|
}
|
|
|
-// 获取H5环境使用的流地址
|
|
|
+// 获取H5环境使用的流地址(非 iOS H5 用 wss_flv)
|
|
|
const getH5StreamUrl = computed(() => {
|
|
|
// 确保使用安全的 WSS 协议
|
|
|
- let url = deviceInfo.originalStreamUrl
|
|
|
+ let url = deviceInfo.wsFlvStreamUrl
|
|
|
if (url && url.startsWith('ws://')) {
|
|
|
console.warn('检测到不安全的 ws:// 协议,自动转换为 wss://')
|
|
|
url = url.replace('ws://', 'wss://')
|
|
|
}
|
|
|
return url
|
|
|
})
|
|
|
+
|
|
|
+ // ===== iOS H5 专用流地址(直接用 HLS,不走 Jessibuca) =====
|
|
|
+ const getIOSH5StreamUrl = computed(() => {
|
|
|
+ // iOS H5 优先使用 HLS 地址
|
|
|
+ const hlsUrl = deviceInfo.hlsStreamUrl
|
|
|
+ console.log('========== [诊断] iOS H5 流地址 ==========')
|
|
|
+ console.log('hlsStreamUrl:', hlsUrl)
|
|
|
+ return hlsUrl || ''
|
|
|
+ })
|
|
|
+
|
|
|
+ // 当前 H5 实际使用的流地址(根据设备类型选择)
|
|
|
+ const getCurrentH5StreamUrl = computed(() => {
|
|
|
+ if (isH5IOS.value) {
|
|
|
+ return getIOSH5StreamUrl.value
|
|
|
+ } else {
|
|
|
+ return getH5StreamUrl.value
|
|
|
+ }
|
|
|
+ })
|
|
|
function resolveStateKey(opts) {
|
|
|
const raw = (opts?.state || opts?.batchState || opts?.scene || '').toString().trim()
|
|
|
if (!raw) return 'normal'
|
|
|
@@ -948,10 +1028,15 @@ onLoad((opts) => {
|
|
|
|
|
|
// #ifdef H5
|
|
|
loadJessibucaScript()
|
|
|
+ setTimeout(() => {
|
|
|
+ h5IosVideoContext.value = uni.createVideoContext('h5IosVideo')
|
|
|
+ console.log('H5 iOS 视频上下文已创建')
|
|
|
+ }, 500)
|
|
|
// #endif
|
|
|
})
|
|
|
// 根据设备id获取通道列表
|
|
|
const queryChannels = () => {
|
|
|
+ console.log('========== [诊断] queryChannels 被调用 ==========')
|
|
|
getChannels(deviceInfo.deviceId)
|
|
|
.then(response => {
|
|
|
console.log('获取通道列表:', response)
|
|
|
@@ -960,6 +1045,15 @@ onLoad((opts) => {
|
|
|
const channels = res.data.list
|
|
|
deviceInfo.channelId = channels[0].deviceId
|
|
|
deviceInfo.status = channels[0].status
|
|
|
+ console.log('通道信息:', { channelId: deviceInfo.channelId, status: deviceInfo.status })
|
|
|
+
|
|
|
+ // ===== 诊断日志:调用 playStart 前 =====
|
|
|
+ console.log('========== [诊断] 准备调用 playStart ==========')
|
|
|
+ console.log('deviceId:', deviceInfo.deviceId)
|
|
|
+ console.log('channelId:', deviceInfo.channelId)
|
|
|
+ console.log('isH5IOS:', isH5IOS.value)
|
|
|
+ console.log('isIPhoneH5:', isIPhoneH5.value)
|
|
|
+
|
|
|
playStart(deviceInfo.deviceId, deviceInfo.channelId).then(res => {
|
|
|
if (res.data.code !== 0) {
|
|
|
console.error('播放开始失败:', res.message)
|
|
|
@@ -969,32 +1063,65 @@ onLoad((opts) => {
|
|
|
})
|
|
|
return
|
|
|
}
|
|
|
- console.log('播放开始:', res)
|
|
|
-
|
|
|
+ console.log('playStart 返回数据:', res.data.data)
|
|
|
+ console.log('playStart 可用流地址:', Object.keys(res.data.data || {}))
|
|
|
+
|
|
|
+ // ===== 诊断日志:playStart 成功,保存各格式流地址 =====
|
|
|
+ console.log('========== [诊断] 保存各格式流地址 ==========')
|
|
|
+
|
|
|
// #ifdef H5
|
|
|
- let streamUrl = res.data.data.wss_flv
|
|
|
-
|
|
|
- if (streamUrl) {
|
|
|
- const urlObj = new URL(streamUrl)
|
|
|
- // 替换 hostname
|
|
|
+ // H5 环境:分别保存 wss_flv 和 hls
|
|
|
+ const rawWsFlv = res.data.data.wss_flv
|
|
|
+ const rawHls = res.data.data.hls
|
|
|
+
|
|
|
+ // 非 iOS H5:走 wss_flv + Jessibuca,保留 URL 替换逻辑
|
|
|
+ if (!isH5IOS.value && rawWsFlv) {
|
|
|
+ const urlObj = new URL(rawWsFlv)
|
|
|
urlObj.hostname = 'nxy.gbdfarm.com'
|
|
|
- // 替换端口
|
|
|
urlObj.port = '9000'
|
|
|
-
|
|
|
- deviceInfo.originalStreamUrl = urlObj.toString()
|
|
|
- console.log("queryChannels - deviceInfo.originalStreamUrl", deviceInfo.originalStreamUrl)
|
|
|
- } else {
|
|
|
- console.warn('未获取到 wss_flv 流地址')
|
|
|
+ deviceInfo.wsFlvStreamUrl = urlObj.toString()
|
|
|
+ console.log('H5 非iOS - wsFlvStreamUrl:', deviceInfo.wsFlvStreamUrl)
|
|
|
+ } else if (!isH5IOS.value) {
|
|
|
+ console.warn('H5 非iOS - 未获取到 wss_flv')
|
|
|
+ }
|
|
|
+
|
|
|
+ // iOS H5:直接用 HLS,不做 URL 替换
|
|
|
+ if (isH5IOS.value && rawHls) {
|
|
|
+ deviceInfo.hlsStreamUrl = rawHls // 直接使用原始 HLS 地址,不替换域名
|
|
|
+ console.log('H5 iOS - hlsStreamUrl (不替换域名):', deviceInfo.hlsStreamUrl)
|
|
|
+ } else if (isH5IOS.value) {
|
|
|
+ console.warn('H5 iOS - 未获取到 hls,使用 wss_flv 兜底')
|
|
|
+ // iOS 没有 HLS 时,尝试用 wss_flv(可能也会黑屏,但至少有尝试)
|
|
|
+ deviceInfo.hlsStreamUrl = rawWsFlv || ''
|
|
|
}
|
|
|
+
|
|
|
+ // 兼容旧逻辑
|
|
|
+ deviceInfo.originalStreamUrl = isH5IOS.value
|
|
|
+ ? deviceInfo.hlsStreamUrl
|
|
|
+ : deviceInfo.wsFlvStreamUrl
|
|
|
+ console.log('H5 - originalStreamUrl (兼容):', deviceInfo.originalStreamUrl)
|
|
|
// #endif
|
|
|
-
|
|
|
+
|
|
|
// #ifdef MP-WEIXIN
|
|
|
- deviceInfo.originalStreamUrl = res.data.data.hls || deviceInfo.originalStreamUrl
|
|
|
+ deviceInfo.hlsStreamUrl = res.data.data.hls || deviceInfo.hlsStreamUrl
|
|
|
+ deviceInfo.originalStreamUrl = deviceInfo.hlsStreamUrl
|
|
|
+ console.log("queryChannels - 小程序 hlsStreamUrl:", deviceInfo.hlsStreamUrl)
|
|
|
// #endif
|
|
|
-
|
|
|
+
|
|
|
// #ifdef APP-PLUS || APP-HARMONY
|
|
|
- deviceInfo.originalStreamUrl = res.data.data.fmp4 || deviceInfo.originalStreamUrl
|
|
|
+ deviceInfo.fmp4StreamUrl = res.data.data.fmp4 || deviceInfo.fmp4StreamUrl
|
|
|
+ deviceInfo.hlsStreamUrl = res.data.data.hls || deviceInfo.hlsStreamUrl
|
|
|
+ deviceInfo.originalStreamUrl = deviceInfo.fmp4StreamUrl
|
|
|
+ console.log("queryChannels - App fmp4StreamUrl:", deviceInfo.fmp4StreamUrl)
|
|
|
+ console.log("queryChannels - App hlsStreamUrl:", deviceInfo.hlsStreamUrl)
|
|
|
// #endif
|
|
|
+
|
|
|
+ // ===== 最终诊断日志 =====
|
|
|
+ console.log('========== [诊断] 流地址保存完成 ==========')
|
|
|
+ console.log('wsFlvStreamUrl:', deviceInfo.wsFlvStreamUrl)
|
|
|
+ console.log('hlsStreamUrl:', deviceInfo.hlsStreamUrl)
|
|
|
+ console.log('fmp4StreamUrl:', deviceInfo.fmp4StreamUrl)
|
|
|
+ console.log('originalStreamUrl (兼容):', deviceInfo.originalStreamUrl)
|
|
|
}).catch(err => {
|
|
|
console.error('播放开始失败:', err)
|
|
|
})
|
|
|
@@ -1028,13 +1155,16 @@ const loadData = async (batchId) => {
|
|
|
}
|
|
|
// 视频播放错误处理
|
|
|
const onVideoError = (e) => {
|
|
|
+ console.error('========== [诊断] 视频播放错误 ==========')
|
|
|
console.error('视频播放错误:', e)
|
|
|
-
|
|
|
+
|
|
|
let errorMsg = '视频加载失败'
|
|
|
-
|
|
|
+
|
|
|
// 微信小程序video组件错误码
|
|
|
if (e && e.detail) {
|
|
|
const errCode = e.detail.errCode
|
|
|
+ console.error('微信错误码:', errCode)
|
|
|
+ console.error('微信错误信息:', e.detail.errMsg)
|
|
|
switch(errCode) {
|
|
|
case 10001:
|
|
|
errorMsg = '网络错误,请检查网络连接'
|
|
|
@@ -1051,9 +1181,16 @@ const loadData = async (batchId) => {
|
|
|
default:
|
|
|
errorMsg = `播放失败(错误码:${errCode})`
|
|
|
}
|
|
|
- console.error('视频错误详情:', e.detail)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ // ===== 诊断日志:当前环境信息 =====
|
|
|
+ // #ifdef H5
|
|
|
+ console.log('========== [诊断] H5 错误上下文 ==========')
|
|
|
+ console.log('isH5IOS:', isH5IOS.value)
|
|
|
+ console.log('getH5StreamUrl (非iOS):', getH5StreamUrl.value)
|
|
|
+ console.log('getIOSH5StreamUrl (iOS):', getIOSH5StreamUrl.value)
|
|
|
+ // #endif
|
|
|
+
|
|
|
uni.showToast({
|
|
|
title: errorMsg,
|
|
|
icon: 'none',
|
|
|
@@ -1063,12 +1200,12 @@ const loadData = async (batchId) => {
|
|
|
isPlaying.value = false
|
|
|
|
|
|
// #ifdef H5
|
|
|
+ // 只对非 iOS H5 做 Jessibuca 重试
|
|
|
setTimeout(() => {
|
|
|
- if (isPlaying.value && jessibucaRef.value) {
|
|
|
+ if (isPlaying.value && !isH5IOS.value && jessibucaRef.value) {
|
|
|
console.log('尝试重新加载视频流')
|
|
|
- if (deviceInfo.originalStreamUrl !== config.streamServer.wsFlvServer) {
|
|
|
- deviceInfo.streamUrl = config.streamServer.wsFlvServer
|
|
|
- }
|
|
|
+ } else if (isH5IOS.value) {
|
|
|
+ console.log('【诊断】iOS H5 播放失败,hlsStreamUrl:', deviceInfo.hlsStreamUrl)
|
|
|
}
|
|
|
}, 3000)
|
|
|
// #endif
|
|
|
@@ -1086,10 +1223,31 @@ const loadData = async (batchId) => {
|
|
|
}
|
|
|
// 播放/暂停切换
|
|
|
const togglePlayState = () => {
|
|
|
+ console.log('========== [诊断] togglePlayState 被调用 ==========')
|
|
|
+ console.log('当前 isPlaying:', isPlaying.value)
|
|
|
+ console.log('isH5IOS:', isH5IOS.value)
|
|
|
+
|
|
|
if (!isPlaying.value) {
|
|
|
+ // 开始播放
|
|
|
isPlaying.value = true
|
|
|
-
|
|
|
+
|
|
|
+ // ===== 诊断日志:播放链路选择 =====
|
|
|
+ // #ifdef H5
|
|
|
+ if (isH5IOS.value) {
|
|
|
+ console.log('========== [诊断] H5 iOS 播放链路 ==========')
|
|
|
+ console.log('使用 iOS H5 专用流地址')
|
|
|
+ console.log('getIOSH5StreamUrl:', getIOSH5StreamUrl.value)
|
|
|
+ } else {
|
|
|
+ console.log('========== [诊断] H5 非iOS 播放链路 ==========')
|
|
|
+ console.log('使用 Jessibuca + wss_flv')
|
|
|
+ console.log('getH5StreamUrl:', getH5StreamUrl.value)
|
|
|
+ }
|
|
|
+ // #endif
|
|
|
+
|
|
|
// #ifdef MP-WEIXIN
|
|
|
+ console.log('========== [诊断] 微信小程序播放链路 ==========')
|
|
|
+ console.log('使用 video + hls')
|
|
|
+ console.log('getAppStreamUrl:', getAppStreamUrl.value)
|
|
|
setTimeout(() => {
|
|
|
if (livePlayerContext.value) {
|
|
|
livePlayerContext.value.play()
|
|
|
@@ -1097,8 +1255,11 @@ const loadData = async (batchId) => {
|
|
|
}
|
|
|
}, 300)
|
|
|
// #endif
|
|
|
-
|
|
|
+
|
|
|
// #ifdef APP-PLUS || APP-HARMONY
|
|
|
+ console.log('========== [诊断] App 播放链路 ==========')
|
|
|
+ console.log('使用 video + fmp4/hls')
|
|
|
+ console.log('getAppStreamUrl:', getAppStreamUrl.value)
|
|
|
setTimeout(() => {
|
|
|
if (appLivePlayerContext.value) {
|
|
|
appLivePlayerContext.value.play()
|
|
|
@@ -1108,36 +1269,31 @@ const loadData = async (batchId) => {
|
|
|
// #endif
|
|
|
|
|
|
// #ifdef H5
|
|
|
- setTimeout(() => {
|
|
|
- playStart(deviceInfo.deviceId, deviceInfo.channelId).then(res => {
|
|
|
- if (res.data.code !== 0) {
|
|
|
- console.error('播放开始失败:', res.message)
|
|
|
- uni.showToast({
|
|
|
- title: '播放失败: ' + res.message,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
- console.log('播放开始:', res)
|
|
|
-
|
|
|
- // 使用 wss_flv 并替换域名和端口
|
|
|
- let streamUrl = res.data.data.wss_flv
|
|
|
- if (streamUrl) {
|
|
|
- const urlObj = new URL(streamUrl)
|
|
|
- urlObj.hostname = 'nxy.gbdfarm.com'
|
|
|
- urlObj.port = '9000'
|
|
|
- deviceInfo.originalStreamUrl = urlObj.toString()
|
|
|
- console.log("togglePlayState - deviceInfo.originalStreamUrl", deviceInfo.originalStreamUrl)
|
|
|
+ // 【最小修复】不再重复调用 playStart,直接使用 queryChannels 中已保存的流地址
|
|
|
+ console.log('【修复】togglePlayState 不再调用 playStart,使用已保存的流地址')
|
|
|
+ console.log('H5 实际播放 URL:', getCurrentH5StreamUrl.value)
|
|
|
+
|
|
|
+ // iOS H5 需要手动调用 video.play()
|
|
|
+ if (isH5IOS.value) {
|
|
|
+ setTimeout(() => {
|
|
|
+ if (h5IosVideoContext.value) {
|
|
|
+ h5IosVideoContext.value.play()
|
|
|
+ console.log('H5 iOS video.play() 已调用')
|
|
|
}
|
|
|
- }).catch(err => {
|
|
|
- console.error('播放开始失败:', err)
|
|
|
- })
|
|
|
- uni.vibrateShort()
|
|
|
- }, 300)
|
|
|
+ }, 300)
|
|
|
+ }
|
|
|
+
|
|
|
+ uni.vibrateShort()
|
|
|
// #endif
|
|
|
} else {
|
|
|
// #ifdef H5
|
|
|
- if (jessibucaRef.value) {
|
|
|
+ // iOS H5 的 video 暂停
|
|
|
+ if (isH5IOS.value && h5IosVideoContext.value) {
|
|
|
+ h5IosVideoContext.value.pause()
|
|
|
+ console.log('H5 iOS video.pause() 已调用')
|
|
|
+ }
|
|
|
+ // 非 iOS H5 的 Jessibuca 暂停
|
|
|
+ if (!isH5IOS.value && jessibucaRef.value) {
|
|
|
jessibucaRef.value.pause()
|
|
|
}
|
|
|
// #endif
|
|
|
@@ -1466,10 +1622,30 @@ const loadData = async (batchId) => {
|
|
|
}
|
|
|
// 获取App(安卓/鸿蒙)环境使用的流地址
|
|
|
const getAppStreamUrl = computed(() => {
|
|
|
- // 优先使用 fmp4 格式(微信小程序和App都支持)
|
|
|
- if (deviceInfo.originalStreamUrl) {
|
|
|
- console.log("当前视频流地址:", deviceInfo.originalStreamUrl)
|
|
|
- return deviceInfo.originalStreamUrl
|
|
|
+ // ===== 诊断日志 =====
|
|
|
+ console.log('========== [诊断] getAppStreamUrl ==========')
|
|
|
+ console.log('fmp4StreamUrl:', deviceInfo.fmp4StreamUrl)
|
|
|
+ console.log('hlsStreamUrl:', deviceInfo.hlsStreamUrl)
|
|
|
+
|
|
|
+ // App iOS 优先使用 HLS
|
|
|
+ // #ifdef APP-PLUS
|
|
|
+ const platform = uni.getSystemInfoSync().platform
|
|
|
+ console.log('App 平台:', platform)
|
|
|
+ if (platform === 'ios') {
|
|
|
+ if (deviceInfo.hlsStreamUrl) {
|
|
|
+ console.log('App iOS 优先使用 hlsStreamUrl')
|
|
|
+ return deviceInfo.hlsStreamUrl
|
|
|
+ } else if (deviceInfo.fmp4StreamUrl) {
|
|
|
+ console.log('App iOS 无 hls,使用 fmp4 兜底')
|
|
|
+ return deviceInfo.fmp4StreamUrl
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // #endif
|
|
|
+
|
|
|
+ // App Android / 鸿蒙:优先使用 fmp4
|
|
|
+ if (deviceInfo.fmp4StreamUrl) {
|
|
|
+ console.log('App 使用 fmp4StreamUrl')
|
|
|
+ return deviceInfo.fmp4StreamUrl
|
|
|
}
|
|
|
|
|
|
// 如果没有流地址,返回空字符串
|