| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- <template>
- <div class="videoBox">
- <div class="box">
- <div class="list">
- <ul>
- <li
- v-for="(item, index) in cList"
- :key="index"
- :style="`color: ${index === cIndex ? 'red':''}`"
- @click="play(item.uuid,index)"
- >
- {{ item.name }}
- </li>
- </ul>
- </div>
- <video
- id="test"
- crossorigin="anonymous"
- autoplay
- playsinline
- muted
- controls
- />
- </div>
- <div class="contrl">
- <n-button>
- 播放
- </n-button>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import axios from '@/utils/axios'
- import { onMounted, onUnmounted, ref } from 'vue'
- import MD5 from 'js-md5'
- let webRtc: any = null
- const TOKEN = '2fc01ae175e8676b6a3edc32d2d76cb3'
- const cList = ref()
- const cUUID = ref('')
- const cIndex = ref(-1)
- /**
- * rtc 初始化
- * @param HOST
- * @param token
- * @param uuid
- * @param callBack
- * @param profile 0 主 1 子
- */
- const initWebRtc = async (HOST: String, token: String, uuid: string, callBack: Function, profile:number, startTime:number, endTime:number) => {
- try {
- // init RTC
- const Peer = new RTCPeerConnection() as any
- // Peer.addTransceiver('audio', { direction: 'recvonly' })
- Peer.addTransceiver('video', { direction: 'recvonly' })
- const offer = await Peer.createOffer()
- await Peer.setLocalDescription(offer)
- // 监听视频
- Peer.ontrack = callBack
- Peer.oniceconnectionstatechange = () => {
- const state = Peer.iceConnectionState
- console.log('ICE状态', state)
- }
- Peer.onicegatheringstatechange = () => {
- console.log('GatheringState: ', Peer.iceGatheringState)
- }
- Peer.onconnectionstatechange = () => {
- const state = Peer.connectionState
- console.log('连接状态', state)
- }
- // SDP SRS params
- const stream = MD5(uuid + profile)
- const params = {
- api: `http://${HOST}:1985/rtc/v1/play/?token=${token}&uuid=${uuid}&stream=${uuid + profile}&profile=${profile}`,
- clientip: null,
- sdp: offer.sdp,
- streamurl: `webrtc://${HOST}/replay/${stream}?token=${token}&starttime=${startTime}&endtime=${endTime}&uuid=${uuid}&stream=${stream}&profile=${profile}`,
- tid: Number(Math.floor(new Date().getTime() * Math.random() * 100)).toString(16).slice(0, 7)
- }
- console.log('params', params)
- // 发送offer
- const res = await window.fetch(params.api, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(params)
- })
- // 接收 answer
- const { sdp } = await res.json()
- if (sdp) await Peer.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp }))
- return Peer
- } catch (error) {
- return null
- }
- }
- /**
- * 播放
- * @param uuid
- */
- const play = async (uuid: string, index:number) => {
- if (!uuid) return
- if (uuid === cUUID.value) return
- if (webRtc) webRtc.close()
- cUUID.value = uuid
- cIndex.value = index
- webRtc = await initWebRtc('47.108.192.202', TOKEN, uuid, (event: any) => {
- const dom = document.getElementById('test') as any
- const { streams } = event
- dom.srcObject = streams[0]
- console.log('track', event)
- }, 1, 1667836800000, 1667923199000)
- }
- // 获取摄像头播放地址
- const getCamer = async () => {
- const { data } = await axios.post('http://47.108.192.202:8089', {
- code: 'categorycamera.list',
- token: TOKEN,
- body: {}
- })
- // 35可控
- cList.value = data.filter((el: { name: string }) => (el.name.includes('卡哈洛')))
- console.log('摄像头列表', cList.value)
- }
- onMounted(() => {
- getCamer()
- })
- onUnmounted(() => {
- if (webRtc) webRtc.close()
- })
- </script>
- <style lang="less" scoped>
- .videoBox {
- .box {
- display: flex;
- justify-content: center;
- .list {
- color: white;
- li {
- padding: 10px;
- &:hover {
- color: aqua;
- cursor: pointer;
- }
- }
- }
- video {
- width: 800px;
- height: 500px;
- background: none;
- object-fit: fill;
- font-size: 0;
- }
- }
- .contrl {
- margin-top: 10px;
- text-align: center;
- button {
- margin-left: 10px;
- }
- }
- }
- </style>
|