修复web和微信小程序的通话

This commit is contained in:
2026-05-30 21:40:52 +08:00
parent a05f8f29c6
commit 68dba6bec9
2 changed files with 83 additions and 10 deletions

View File

@@ -389,9 +389,16 @@ watchEffect(() => {
// 监听小程序流,初始化 FLV 播放器
let flvPlayer: flvjs.Player | null = null
let currentFlvUrl: string | null = null // 跟踪当前播放的 FLV URL
let chaseFrameTimer: number | null = null // 追帧定时器(解决累积延迟问题)
// 清理 FLV 播放器的辅助函数
function cleanupFlvPlayer() {
// 清理追帧定时器
if (chaseFrameTimer) {
clearInterval(chaseFrameTimer)
chaseFrameTimer = null
}
if (flvPlayer) {
try {
// @ts-ignore - flv.js Player 内部属性
@@ -448,6 +455,31 @@ watch(
console.log('[CallWindow] 初始化 FLV 播放器:', newFlvUrl)
flvPlayer = props.initFlvPlayer(flvVideoRef.value, 0)
currentFlvUrl = newFlvUrl
// 启动追帧定时器(解决累积延迟问题)
if (flvVideoRef.value) {
// 先清理可能存在的旧定时器
if (chaseFrameTimer) {
clearInterval(chaseFrameTimer)
}
chaseFrameTimer = window.setInterval(() => {
if (!flvPlayer || !flvVideoRef.value) return
const video = flvVideoRef.value
// 检查缓冲区是否有数据
if (video.buffered.length > 0) {
const end = video.buffered.end(0) // 缓冲区末尾时间
const current = video.currentTime // 当前播放时间
const diff = end - current // 延迟时长
// 如果延迟超过 1.5 秒,执行追帧
if (diff > 1.5) {
console.log(`[CallWindow] 检测到延迟 ${diff.toFixed(2)}s执行追帧...`)
video.currentTime = end - 0.1 // 跳到缓冲区末尾附近
}
}
}, 1500) // 每 1.5 秒检查一次
}
}
},
{ immediate: true, deep: true }

View File

@@ -209,6 +209,15 @@ export function useWebRTC(
} else {
console.log('[WebRTC] RTMP 模式:等待 FLV 流')
}
// 延迟刷新房间流信息,确保小程序推流成功后能获取到 FLV 地址
// 小程序推流成功需要时间(通常 2-3 秒),所以延迟刷新
setTimeout(() => {
if (call.active && call.miniprogramStreams.length === 0 && currentRoomId) {
console.log('[WebRTC] 📡 通话建立后延迟刷新房间信息...')
refreshRoomStreams()
}
}, 2000)
} else if (signal === 'offer') {
// WebRTC 模式才处理 offerRTMP 模式不使用 WebRTC 信令)
@@ -251,27 +260,37 @@ export function useWebRTC(
pull_url: content.pull_url
})
// 如果有 FLV 地址,添加或更新小程序流列表
if (content.flv_url && content.user_id) {
// 获取 FLV 地址(优先使用 flv_url兼容 pull_url 转换)
let flvUrl = content.flv_url || ''
// 如果有 FLV 地址或用户 ID添加或更新小程序流列表
if (flvUrl && content.user_id) {
const existingIndex = call.miniprogramStreams.findIndex(s => s.userId === content.user_id)
if (existingIndex >= 0) {
// 更新现有流的地址(重要:当用户重新加入时使用新的流地址)
const oldFlvUrl = call.miniprogramStreams[existingIndex].flvUrl
call.miniprogramStreams[existingIndex].flvUrl = content.flv_url
call.miniprogramStreams[existingIndex].flvUrl = flvUrl
console.log('[WebRTC] 🔄 更新小程序流地址:', content.user_id)
console.log('[WebRTC] 旧地址:', oldFlvUrl)
console.log('[WebRTC] 新地址:', content.flv_url)
console.log('[WebRTC] 新地址:', flvUrl)
} else {
// 添加新的小程序流
call.miniprogramStreams.push({
userId: content.user_id,
flvUrl: content.flv_url
flvUrl: flvUrl
})
console.log('[WebRTC] ✅ 添加小程序流:', content.user_id, content.flv_url)
console.log('[WebRTC] ✅ 添加小程序流:', content.user_id, flvUrl)
}
console.log('[WebRTC] 📺 当前小程序流列表:', call.miniprogramStreams)
} else {
console.log('[WebRTC] ⚠️ participant_joined 没有 FLV 地址')
} else if (content.user_id && !flvUrl) {
// 兼容性处理:如果没有 FLV 地址,尝试延迟获取
console.log('[WebRTC] ⚠️ participant_joined 没有 FLV 地址1秒后尝试刷新房间信息')
setTimeout(() => {
if (call.active && currentRoomId && call.miniprogramStreams.length === 0) {
console.log('[WebRTC] 📡 延迟刷新房间信息...')
refreshRoomStreams()
}
}, 1000)
}
// 如果当前没有小程序流,尝试重新获取房间信息
@@ -615,6 +634,14 @@ export function useWebRTC(
console.log('[WebRTC] 📤 发送 accepted 信令给:', currentReceiverUserId)
sendSignal('accepted', undefined, currentReceiverUserId)
// 延迟刷新房间流信息,确保小程序推流成功后能获取到 FLV 地址
setTimeout(() => {
if (call.active && call.miniprogramStreams.length === 0 && currentRoomId) {
console.log('[WebRTC] 📡 接听后延迟刷新房间信息...')
refreshRoomStreams()
}
}, 2000)
} catch (error) {
console.error('[WebRTC] ❌ 接听失败:', error)
endCall()
@@ -1033,16 +1060,30 @@ export function useWebRTC(
isLive: true,
hasAudio: true,
hasVideo: true,
cors: true, // 允许跨域
}, {
enableWorker: false,
enableStashBuffer: false,
enableStashBuffer: false, // 关闭堆积缓存,减少延迟
stashInitialSize: 128,
lazyLoad: false,
lazyLoadMaxDuration: 0.2, // 极短的懒加载时间
autoCleanupSourceBuffer: true, // 自动清理缓存防止内存泄漏
})
player.attachMediaElement(videoElement)
player.load()
player.play()
// 自动播放失败时静音重试(兼容浏览器自动播放策略)
player.play().catch(async (e) => {
console.warn('[WebRTC] 自动播放失败,尝试静音播放:', e)
videoElement.muted = true
try {
await player.play()
console.log('[WebRTC] 静音播放成功')
} catch (e2) {
console.error('[WebRTC] 静音播放也失败:', e2)
}
})
// 监听错误
player.on(flvjs.Events.ERROR, (errorType, errorDetail, errorInfo) => {