直播:LIVE_PUBLIC_IP 与 ICE 诊断;摄像头错误中文提示与约束放宽
Made-with: Cursor
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
</template>
|
||||
<p class="tip">
|
||||
仅后台可开播:推流后,官网首页左上角以<strong>画中画</strong>自动展示,用户也可打开官网「直播」全屏页观看。需站点使用
|
||||
<strong>HTTPS</strong>;公网复杂网络请在服务端配置 <code>LIVE_ICE_SERVERS</code>(含 TURN)。
|
||||
<strong>HTTPS</strong>。公网若观众端<strong>黑屏但信令正常</strong>,请在 API 服务环境变量中设置
|
||||
<code>LIVE_PUBLIC_IP</code>(服务器公网 IPv4,与域名一致),并配置 <code>LIVE_ICE_SERVERS</code>(含 TURN)。
|
||||
</p>
|
||||
<p class="status">{{ status }}</p>
|
||||
<div class="actions">
|
||||
|
||||
Reference in New Issue
Block a user