视频会议
This commit is contained in:
@@ -91,10 +91,6 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 屏幕可见的调试浮层(小程序 WebView 看不到 console,先用这个排查按钮无反应问题) -->
|
|
||||||
<view v-if="debugLines.length" class="debug-panel">
|
|
||||||
<view class="debug-line" v-for="(line, idx) in debugLines" :key="idx">{{ line }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -321,15 +317,6 @@ const startTimer = () => {
|
|||||||
|
|
||||||
const localMediaError = ref('')
|
const localMediaError = ref('')
|
||||||
|
|
||||||
// 屏幕可见的调试日志(小程序 WebView 没法看 console)
|
|
||||||
const debugLines = ref([])
|
|
||||||
const pushDebug = (msg) => {
|
|
||||||
try {
|
|
||||||
const line = `[${new Date().toLocaleTimeString()}] ${msg}`
|
|
||||||
debugLines.value = [...debugLines.value.slice(-29), line]
|
|
||||||
console.log('[CloudLawVideoCall][DEBUG]', line)
|
|
||||||
} catch (e) { /* ignore */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
const joinMeeting = async () => {
|
const joinMeeting = async () => {
|
||||||
if (joining.value) return
|
if (joining.value) return
|
||||||
@@ -392,10 +379,9 @@ const prepareLocalMediaTracks = async (startWithVideo) => {
|
|||||||
}
|
}
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
if (typeof navigator === 'undefined' || !navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
if (typeof navigator === 'undefined' || !navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
||||||
pushDebug('prepare: navigator.mediaDevices 不可用')
|
console.warn('[CloudLawVideoCall] navigator.mediaDevices 不可用,跳过预申请')
|
||||||
return prefs
|
return prefs
|
||||||
}
|
}
|
||||||
pushDebug(`prepare -> getUserMedia(audio:true, video:${startWithVideo})`)
|
|
||||||
try {
|
try {
|
||||||
const constraints = {
|
const constraints = {
|
||||||
audio: true,
|
audio: true,
|
||||||
@@ -406,7 +392,6 @@ const prepareLocalMediaTracks = async (startWithVideo) => {
|
|||||||
const stream = await navigator.mediaDevices.getUserMedia(constraints)
|
const stream = await navigator.mediaDevices.getUserMedia(constraints)
|
||||||
prefs.audioTrack = stream.getAudioTracks()[0] || null
|
prefs.audioTrack = stream.getAudioTracks()[0] || null
|
||||||
prefs.videoTrack = stream.getVideoTracks()[0] || null
|
prefs.videoTrack = stream.getVideoTracks()[0] || null
|
||||||
pushDebug(`prepare 成功 audio=${!!prefs.audioTrack} video=${!!prefs.videoTrack}`)
|
|
||||||
// 如果用户拒了视频,stream 里不会有 video track,自动降级为不开摄像头
|
// 如果用户拒了视频,stream 里不会有 video track,自动降级为不开摄像头
|
||||||
if (startWithVideo && !prefs.videoTrack) {
|
if (startWithVideo && !prefs.videoTrack) {
|
||||||
prefs.startVideo = false
|
prefs.startVideo = false
|
||||||
@@ -415,7 +400,7 @@ const prepareLocalMediaTracks = async (startWithVideo) => {
|
|||||||
prefs.startAudio = false
|
prefs.startAudio = false
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
pushDebug(`prepare 失败: ${err?.name || ''} ${err?.message || err}`)
|
console.error('[CloudLawVideoCall] prepare media failed', err)
|
||||||
localMediaError.value = `预申请音视频失败:${err?.name || ''} ${err?.message || err}`
|
localMediaError.value = `预申请音视频失败:${err?.name || ''} ${err?.message || err}`
|
||||||
// 拿不到也继续走 joinAndEnter,让后端协议建好;用户可以在入会后手动点麦/摄像头按钮重试
|
// 拿不到也继续走 joinAndEnter,让后端协议建好;用户可以在入会后手动点麦/摄像头按钮重试
|
||||||
prefs.startAudio = false
|
prefs.startAudio = false
|
||||||
@@ -469,29 +454,20 @@ const acquireVideoTrack = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onMicToggle = async () => {
|
const onMicToggle = async () => {
|
||||||
pushDebug(`mic点击 loading=${audioLoading.value} on=${audioEnabled.value} producer=${meetingStore.localProducers?.audio || 'null'}`)
|
if (audioLoading.value || leaving.value) return
|
||||||
if (audioLoading.value || leaving.value) {
|
|
||||||
pushDebug('mic 被 loading/leaving 拦住')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
audioLoading.value = true
|
audioLoading.value = true
|
||||||
try {
|
try {
|
||||||
if (meetingStore.localProducers?.audio) {
|
if (meetingStore.localProducers?.audio) {
|
||||||
// 已经有 producer:只 mute/unmute,不释放硬件(关键:WebView 释放后申请会被拒)
|
// 已经有 producer:只 mute/unmute,不释放硬件(WebView 释放后再申请会被拒)
|
||||||
pushDebug(`mic -> setLocalAudioMuted(${audioEnabled.value})`)
|
|
||||||
await meetingStore.setLocalAudioMuted(audioEnabled.value)
|
await meetingStore.setLocalAudioMuted(audioEnabled.value)
|
||||||
pushDebug(`mic mute 切换完成 enabled=${meetingStore.localAudioEnabled}`)
|
|
||||||
} else {
|
} else {
|
||||||
// 没 producer:兜底走完整流程,自己 getUserMedia 拿 track(用户手势作用域内)
|
// 没 producer:兜底走完整流程,在用户手势作用域内 getUserMedia
|
||||||
pushDebug('mic -> getUserMedia(audio)')
|
|
||||||
const track = await acquireAudioTrack()
|
const track = await acquireAudioTrack()
|
||||||
pushDebug(`mic 拿到 track id=${track?.id?.slice(0, 8)} label=${track?.label || ''}`)
|
|
||||||
await meetingStore.startLocalAudio(undefined, track)
|
await meetingStore.startLocalAudio(undefined, track)
|
||||||
pushDebug(`mic start 完成 enabled=${meetingStore.localAudioEnabled}`)
|
|
||||||
}
|
}
|
||||||
localMediaError.value = ''
|
localMediaError.value = ''
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
pushDebug(`mic 报错: ${err?.name || ''} ${err?.message || err}`)
|
console.error('[CloudLawVideoCall] mic toggle failed', err)
|
||||||
localMediaError.value = `麦克风:${err?.message || err}`
|
localMediaError.value = `麦克风:${err?.message || err}`
|
||||||
} finally {
|
} finally {
|
||||||
audioLoading.value = false
|
audioLoading.value = false
|
||||||
@@ -499,27 +475,18 @@ const onMicToggle = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onCamToggle = async () => {
|
const onCamToggle = async () => {
|
||||||
pushDebug(`cam点击 loading=${videoLoading.value} on=${videoEnabled.value} producer=${meetingStore.localProducers?.video || 'null'}`)
|
if (videoLoading.value || leaving.value) return
|
||||||
if (videoLoading.value || leaving.value) {
|
|
||||||
pushDebug('cam 被 loading/leaving 拦住')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
videoLoading.value = true
|
videoLoading.value = true
|
||||||
try {
|
try {
|
||||||
if (meetingStore.localProducers?.video) {
|
if (meetingStore.localProducers?.video) {
|
||||||
pushDebug(`cam -> setLocalVideoMuted(${videoEnabled.value})`)
|
|
||||||
await meetingStore.setLocalVideoMuted(videoEnabled.value)
|
await meetingStore.setLocalVideoMuted(videoEnabled.value)
|
||||||
pushDebug(`cam mute 切换完成 enabled=${meetingStore.localVideoEnabled}`)
|
|
||||||
} else {
|
} else {
|
||||||
pushDebug('cam -> getUserMedia(video)')
|
|
||||||
const track = await acquireVideoTrack()
|
const track = await acquireVideoTrack()
|
||||||
pushDebug(`cam 拿到 track id=${track?.id?.slice(0, 8)} label=${track?.label || ''}`)
|
|
||||||
await meetingStore.startLocalVideo(undefined, track)
|
await meetingStore.startLocalVideo(undefined, track)
|
||||||
pushDebug(`cam start 完成 enabled=${meetingStore.localVideoEnabled}`)
|
|
||||||
}
|
}
|
||||||
localMediaError.value = ''
|
localMediaError.value = ''
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
pushDebug(`cam 报错: ${err?.name || ''} ${err?.message || err}`)
|
console.error('[CloudLawVideoCall] cam toggle failed', err)
|
||||||
localMediaError.value = `摄像头:${err?.message || err}`
|
localMediaError.value = `摄像头:${err?.message || err}`
|
||||||
} finally {
|
} finally {
|
||||||
videoLoading.value = false
|
videoLoading.value = false
|
||||||
@@ -910,24 +877,4 @@ onUnload(() => {
|
|||||||
.clean-video-tile :deep(.tag-host) {
|
.clean-video-tile :deep(.tag-host) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* 屏幕调试浮层 */
|
|
||||||
.debug-panel {
|
|
||||||
position: absolute;
|
|
||||||
left: 12rpx;
|
|
||||||
right: 12rpx;
|
|
||||||
bottom: calc(560rpx + env(safe-area-inset-bottom));
|
|
||||||
z-index: 99;
|
|
||||||
max-height: 360rpx;
|
|
||||||
overflow: auto;
|
|
||||||
background: rgba(0, 0, 0, 0.72);
|
|
||||||
color: #b6f8ff;
|
|
||||||
font-size: 22rpx;
|
|
||||||
line-height: 1.45;
|
|
||||||
padding: 12rpx 16rpx;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.debug-line {
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user