From d83a69c23ac1074cced8f2ec7faa7acd5fbf50ab Mon Sep 17 00:00:00 2001 From: whm <973418690@qq.com> Date: Wed, 25 Mar 2026 16:19:19 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9B=B4=E6=92=AD=EF=BC=9ALIVE=5FPUBLIC=5FIP?= =?UTF-8?q?=20=E4=B8=8E=20ICE=20=E8=AF=8A=E6=96=AD=EF=BC=9B=E6=91=84?= =?UTF-8?q?=E5=83=8F=E5=A4=B4=E9=94=99=E8=AF=AF=E4=B8=AD=E6=96=87=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E4=B8=8E=E7=BA=A6=E6=9D=9F=E6=94=BE=E5=AE=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made-with: Cursor --- admin/src/utils/liveWebRTC.js | 42 ++++++++++++++++++------- admin/src/views/sites/LiveBroadcast.vue | 3 +- server/pkg/weblive/config.go | 20 +++++++++++- web/src/utils/liveWebRTC.js | 38 ++++++++++++++++++++++ web/src/views/LiveRoom.vue | 3 +- 5 files changed, 91 insertions(+), 15 deletions(-) diff --git a/admin/src/utils/liveWebRTC.js b/admin/src/utils/liveWebRTC.js index dacd96d..3686f6a 100644 --- a/admin/src/utils/liveWebRTC.js +++ b/admin/src/utils/liveWebRTC.js @@ -16,6 +16,33 @@ function liveWsURLPublish(token) { const defaultIce = [{ urls: 'stun:stun.l.google.com:19302' }] +/** 将 getUserMedia 异常转为中文说明(含 Edge 英文 “Could not start video source”) */ +function humanizeGetUserMediaError(err) { + const name = err && err.name + const raw = ((err && err.message) || '').toLowerCase() + if (name === 'NotAllowedError' || name === 'PermissionDeniedError') { + return '已拒绝摄像头权限:在浏览器地址栏左侧允许摄像头,并确认本页为 HTTPS。' + } + if (name === 'NotFoundError' || name === 'DevicesNotFoundError') { + return '未检测到摄像头,请检查是否已接入设备或被系统禁用。' + } + if ( + name === 'NotReadableError' || + raw.includes('could not start video source') || + raw.includes('failed to start video source') || + raw.includes('video source') + ) { + return '无法启动摄像头:可能被 Zoom、Teams、腾讯会议、OBS 等占用;或在 Windows「设置 → 隐私和安全性 → 相机」中未允许浏览器/桌面应用访问。请关闭占用软件后刷新页面重试。' + } + if (name === 'OverconstrainedError') { + return '摄像头不满足当前参数约束,请换用其他摄像头或更新驱动。' + } + if (name === 'AbortError') { + return '打开摄像头被系统中断,请重试。' + } + return (err && err.message) || '无法打开摄像头' +} + /** * @param {object} opts * @param {string} opts.token 管理员 JWT @@ -47,10 +74,8 @@ export function startPublishing(opts = {}) { ws.onopen = async () => { onStatus('信令已连接,正在采集摄像头…') try { - stream = await navigator.mediaDevices.getUserMedia({ - video: { facingMode: 'user' }, - audio: false - }) + // 后台多为 PC:不要用 facingMode:'user',部分机器会直接导致 “Could not start video source” + stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false }) onLocalStream(stream) stream.getTracks().forEach((t) => pc.addTrack(t, stream)) const offer = await pc.createOffer() @@ -58,14 +83,7 @@ export function startPublishing(opts = {}) { send({ type: 'offer', sdp: offer.sdp }) onStatus('已发起推流协商,等待服务端应答…') } catch (err) { - const name = err && err.name - let tip = err.message || '无法打开摄像头' - if (name === 'NotAllowedError' || name === 'PermissionDeniedError') { - tip = '已拒绝摄像头权限:请在浏览器地址栏允许摄像头,并确认本页为 HTTPS。' - } else if (name === 'NotFoundError') { - tip = '未检测到摄像头设备。' - } - onStatus(tip) + onStatus(humanizeGetUserMediaError(err)) stop() } } diff --git a/admin/src/views/sites/LiveBroadcast.vue b/admin/src/views/sites/LiveBroadcast.vue index ff2b61f..c4c5fd2 100644 --- a/admin/src/views/sites/LiveBroadcast.vue +++ b/admin/src/views/sites/LiveBroadcast.vue @@ -6,7 +6,8 @@
仅后台可开播:推流后,官网首页左上角以画中画自动展示,用户也可打开官网「直播」全屏页观看。需站点使用
- HTTPS;公网复杂网络请在服务端配置 LIVE_ICE_SERVERS(含 TURN)。
+ HTTPS。公网若观众端黑屏但信令正常,请在 API 服务环境变量中设置
+ LIVE_PUBLIC_IP(服务器公网 IPv4,与域名一致),并配置 LIVE_ICE_SERVERS(含 TURN)。
{{ status }}
- 仅管理后台 → 视频直播开播(需首页编辑权限)可推流;开播后全站左上角画中画自动播放,本页为大屏观看。单房间、进程内转发;公网建议配置服务端
+ 仅管理后台 → 视频直播开播可推流;开播后全站画中画与本页播放。若一直黑屏但状态显示「正在播放」,多为 ICE 未通:服务端需配置
+ LIVE_PUBLIC_IP(公网 IP)与
LIVE_ICE_SERVERS(含 TURN)。
{{ watchStatus }}