直播:后台 JWT 推流、前台画中画;WebRTC 服务与 Nginx WebSocket 代理
Made-with: Cursor
This commit is contained in:
99
admin/src/views/sites/LiveBroadcast.vue
Normal file
99
admin/src/views/sites/LiveBroadcast.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div class="live-broadcast">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<span>官网视频直播(WebRTC)</span>
|
||||
</template>
|
||||
<p class="tip">
|
||||
仅后台可开播:推流后,官网首页左上角以<strong>画中画</strong>自动展示,用户也可打开官网「直播」全屏页观看。需站点使用
|
||||
<strong>HTTPS</strong>;公网复杂网络请在服务端配置 <code>LIVE_ICE_SERVERS</code>(含 TURN)。
|
||||
</p>
|
||||
<p class="status">{{ status }}</p>
|
||||
<div class="actions">
|
||||
<el-button v-if="!session" type="primary" :disabled="!token" @click="start">开始直播</el-button>
|
||||
<el-button v-else type="danger" @click="stop">结束直播</el-button>
|
||||
</div>
|
||||
<video ref="previewRef" class="preview" playsinline muted autoplay></video>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import { startPublishing } from '../../utils/liveWebRTC'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const token = computed(() => authStore.getToken() || '')
|
||||
const previewRef = ref(null)
|
||||
const status = ref('就绪')
|
||||
const session = ref(null)
|
||||
|
||||
function start() {
|
||||
if (!token.value) {
|
||||
status.value = '请先登录'
|
||||
return
|
||||
}
|
||||
status.value = '正在连接…'
|
||||
const { stop } = startPublishing({
|
||||
token: token.value,
|
||||
onStatus: (s) => {
|
||||
status.value = s
|
||||
},
|
||||
onLocalStream: (stream) => {
|
||||
if (previewRef.value) previewRef.value.srcObject = stream
|
||||
}
|
||||
})
|
||||
session.value = { stop }
|
||||
}
|
||||
|
||||
function stop() {
|
||||
session.value?.stop()
|
||||
session.value = null
|
||||
if (previewRef.value) previewRef.value.srcObject = null
|
||||
status.value = '已停止'
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.title = '视频直播开播 - 管理后台'
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
stop()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.live-broadcast {
|
||||
max-width: 720px;
|
||||
}
|
||||
.tip {
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
color: #606266;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.tip code {
|
||||
font-size: 12px;
|
||||
background: #f4f4f5;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.status {
|
||||
color: #409eff;
|
||||
margin-bottom: 12px;
|
||||
min-height: 1.5em;
|
||||
}
|
||||
.actions {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.preview {
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
border-radius: 8px;
|
||||
background: #000;
|
||||
aspect-ratio: 4 / 3;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user