From 10a842b4effc747ff666ca964c01bc2970a69080 Mon Sep 17 00:00:00 2001 From: whm <973418690@qq.com> Date: Thu, 26 Mar 2026 10:22:00 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BC=80=E6=92=AD=E5=8D=A1?= =?UTF-8?q?=E6=AD=A3=E5=9C=A8=E8=BF=9E=E6=8E=A5=EF=BC=9A=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=9C=AA=E5=AE=9A=E4=B9=89=20quality=EF=BC=9B=E7=94=BB?= =?UTF-8?q?=E8=B4=A8=E6=94=B9=E5=AE=98=E7=BD=91=E9=80=89=E6=8B=A9+localSto?= =?UTF-8?q?rage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made-with: Cursor --- admin/src/utils/liveWebRTC.js | 38 ++++++------ admin/src/views/sites/LiveBroadcast.vue | 31 +++------- web/src/utils/liveQuality.js | 9 +++ web/src/views/LiveRoom.vue | 78 ++++++++++++++++++++++++- 4 files changed, 111 insertions(+), 45 deletions(-) create mode 100644 web/src/utils/liveQuality.js diff --git a/admin/src/utils/liveWebRTC.js b/admin/src/utils/liveWebRTC.js index 5074c82..cd99a77 100644 --- a/admin/src/utils/liveWebRTC.js +++ b/admin/src/utils/liveWebRTC.js @@ -1,14 +1,10 @@ /** * 管理后台 WebRTC 开播(需登录 token,与 /api/web/live/ws?role=publish&token= 一致) + * 画质由官网 /live 写入 localStorage(yh_live_capture_quality),同浏览器开播时生效;默认原画约束最少。 */ const apiBase = (import.meta.env.VITE_API_BASE || '').replace(/\/$/, '') -export const LIVE_QUALITY_OPTIONS = [ - { value: 'source', label: '原画(设备默认)' }, - { value: 'high', label: '高清 720p' }, - { value: 'mid', label: '标清 480p' }, - { value: 'low', label: '流畅 360p' } -] +const LIVE_CAPTURE_QUALITY_STORAGE_KEY = 'yh_live_capture_quality' const QUALITY_MEDIA = { source: { video: true, audio: true }, @@ -38,8 +34,16 @@ const QUALITY_MEDIA = { } } -function liveWsURLPublish(token, quality) { - const q = QUALITY_MEDIA[quality] ? quality : 'high' +function effectivePublishQualityKey() { + try { + const v = localStorage.getItem(LIVE_CAPTURE_QUALITY_STORAGE_KEY) + if (v && QUALITY_MEDIA[v]) return v + } catch (_) {} + return 'source' +} + +function liveWsURLPublish(token) { + const q = effectivePublishQualityKey() const path = `/api/web/live/ws?role=publish&token=${encodeURIComponent(token)}&quality=${encodeURIComponent(q)}` if (apiBase) { const base = apiBase.replace(/\/$/, '') @@ -52,7 +56,6 @@ function liveWsURLPublish(token, quality) { 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() @@ -71,7 +74,7 @@ function humanizeGetUserMediaError(err) { return '无法启动摄像头:可能被 Zoom、Teams、腾讯会议、OBS 等占用;或在 Windows「设置 → 隐私和安全性 → 相机」中未允许浏览器/桌面应用访问。请关闭占用软件后刷新页面重试。' } if (name === 'OverconstrainedError') { - return '摄像头不满足当前参数约束,请换用其他摄像头或更新驱动。' + return '摄像头不满足当前参数约束:请到官网「直播」页换一档画质(或选原画)后再开播。' } if (name === 'AbortError') { return '打开摄像头被系统中断,请重试。' @@ -84,25 +87,19 @@ function humanizeGetUserMediaError(err) { * @param {string} opts.token 管理员 JWT * @param {(s: string) => void} [opts.onStatus] * @param {(stream: MediaStream) => void} [opts.onLocalStream] - * @param {'source'|'high'|'mid'|'low'} [opts.quality] 推流画质(约束摄像头采集分辨率) */ export function startPublishing(opts = {}) { - const { - token = '', - quality = 'high', - onStatus = () => {}, - onLocalStream = () => {} - } = opts + const { token = '', onStatus = () => {}, onLocalStream = () => {} } = opts if (!token) { onStatus('未登录,无法开播') return { stop: () => {} } } - const wsUrl = liveWsURLPublish(token, quality) + const publishKey = effectivePublishQualityKey() + const wsUrl = liveWsURLPublish(token) const ws = new WebSocket(wsUrl) const pc = new RTCPeerConnection({ iceServers: defaultIce }) let stream = null - /** 本地主动 stop / 摄像头失败关闭,避免 onclose 覆盖真实错误提示 */ let closedByLocal = false const send = (o) => { @@ -116,8 +113,7 @@ export function startPublishing(opts = {}) { ws.onopen = async () => { onStatus('信令已连接,正在采集摄像头…') try { - // 后台多为 PC:不要用 facingMode:'user',部分机器会直接导致 “Could not start video source” - const cons = QUALITY_MEDIA[quality] || QUALITY_MEDIA.high + const cons = QUALITY_MEDIA[publishKey] || QUALITY_MEDIA.source stream = await navigator.mediaDevices.getUserMedia(cons) onLocalStream(stream) stream.getTracks().forEach((t) => pc.addTrack(t, stream)) diff --git a/admin/src/views/sites/LiveBroadcast.vue b/admin/src/views/sites/LiveBroadcast.vue index 577af39..017f933 100644 --- a/admin/src/views/sites/LiveBroadcast.vue +++ b/admin/src/views/sites/LiveBroadcast.vue @@ -10,17 +10,9 @@ LIVE_PUBLIC_IP(服务器公网 IPv4,与域名一致),并配置 LIVE_ICE_SERVERS(含 TURN)。

{{ status }}

-
- 推流画质 - - - -
+

+ 画质请在官网「直播」页选择(写入本机);与后台开播使用同一浏览器时,开始直播将按该档位采集。 +

开始直播 结束直播 @@ -34,7 +26,7 @@ import { ref, computed, onMounted, onUnmounted } from 'vue' import { onBeforeRouteLeave } from 'vue-router' import { useAuthStore } from '../../stores/auth' -import { startPublishing, LIVE_QUALITY_OPTIONS } from '../../utils/liveWebRTC' +import { startPublishing } from '../../utils/liveWebRTC' const authStore = useAuthStore() const token = computed(() => authStore.getToken() || '') @@ -50,7 +42,6 @@ function start() { status.value = '正在连接…' const { stop } = startPublishing({ token: token.value, - quality: quality.value, onStatus: (s) => { status.value = s }, @@ -108,15 +99,11 @@ onBeforeRouteLeave(() => { margin-bottom: 12px; min-height: 1.5em; } -.quality-row { - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 12px; -} -.quality-label { - font-size: 14px; - color: #606266; +.quality-hint { + font-size: 13px; + line-height: 1.6; + color: #909399; + margin: 0 0 14px; } .actions { margin-bottom: 16px; diff --git a/web/src/utils/liveQuality.js b/web/src/utils/liveQuality.js new file mode 100644 index 0000000..96f61fb --- /dev/null +++ b/web/src/utils/liveQuality.js @@ -0,0 +1,9 @@ +/** 与 admin 开播页约定同一 key,用于「官网选画质 → 同机后台开播按此采集」 */ +export const LIVE_CAPTURE_QUALITY_STORAGE_KEY = 'yh_live_capture_quality' + +export const LIVE_QUALITY_OPTIONS = [ + { value: 'source', label: '原画(设备默认,推荐)' }, + { value: 'high', label: '高清 720p' }, + { value: 'mid', label: '标清 480p' }, + { value: 'low', label: '流畅 360p' } +] diff --git a/web/src/views/LiveRoom.vue b/web/src/views/LiveRoom.vue index f28872f..34f1422 100644 --- a/web/src/views/LiveRoom.vue +++ b/web/src/views/LiveRoom.vue @@ -9,6 +9,15 @@

本站直播(WebRTC)

+
+ + +
+

{{ liveInfoLine }}

{{ watchStatus }}