Browse Source

增加历史播放流demo
Signed-off-by: caner <5658514@qq.com>

caner 3 years ago
parent
commit
e5b616ee3e
3 changed files with 193 additions and 7 deletions
  1. 3 1
      README.md
  2. 14 6
      SRSWebRtcPlayer.ts
  3. 176 0
      index.vue

+ 3 - 1
README.md

@@ -4,4 +4,6 @@ srs webrtc video demo
 1. index_only_one.vue
 1. index_only_one.vue
     拉取单流
     拉取单流
 2. index_mute
 2. index_mute
-    拉去多流
+    拉去多流
+3. index
+    拉取历史流

+ 14 - 6
SRSWebRtcPlayer.ts

@@ -2,11 +2,12 @@
  * srs webrtc palyer
  * srs webrtc palyer
  * auth Caner
  * auth Caner
  */
  */
+import MD5 from 'js-md5'
 class WebRtcPlayer {
 class WebRtcPlayer {
     private Peer: any
     private Peer: any
     private TIMER: any
     private TIMER: any
-    constructor(option: { HOST: string; TOKEN: string; UUID: string; PROFILE: number; PORT: number; DOM: HTMLVideoElement }) {
-        this.initWebRtc(option.HOST, option.PORT, option.TOKEN, option.UUID, option.PROFILE, option.DOM).then(res => {
+    constructor(option: { HOST: string; TOKEN: string; UUID: string; PROFILE: number; PORT: number; DOM: HTMLVideoElement; starttime?: number; endtime?: number }) {
+        this.initWebRtc(option.HOST, option.PORT, option.TOKEN, option.UUID, option.PROFILE, option.DOM, option.starttime, option.endtime).then(res => {
             this.Peer = res
             this.Peer = res
         }).catch(() => {
         }).catch(() => {
             this.Peer = null
             this.Peer = null
@@ -28,7 +29,7 @@ class WebRtcPlayer {
      * @param DOM video节点
      * @param DOM video节点
      * @returns 
      * @returns 
      */
      */
-    private async initWebRtc(HOST: string, PORT: number, TOKEN: string, UUID: string, PROFILE: number, DOM: HTMLVideoElement) {
+    private async initWebRtc(HOST: string, PORT: number, TOKEN: string, UUID: string, PROFILE: number, DOM: HTMLVideoElement, STIME?: number, ETIME?: number) {
         try {
         try {
             const Peer = new RTCPeerConnection() as any
             const Peer = new RTCPeerConnection() as any
             Peer.addTransceiver('video', { direction: 'recvonly' })
             Peer.addTransceiver('video', { direction: 'recvonly' })
@@ -58,12 +59,19 @@ class WebRtcPlayer {
                 console.log('连接状态', state)
                 console.log('连接状态', state)
             }
             }
 
 
-            // SDP SRS params
-            const params = {
+            // SDP SRS params 区分历史与实时
+            const STREAM = STIME && ETIME ? MD5(UUID + PROFILE) : UUID + PROFILE
+            const params = STIME && ETIME ? {
                 api: `http://${HOST}:${PORT}/rtc/v1/play/?token=${TOKEN}&uuid=${UUID}&stream=${UUID + PROFILE}&profile=${PROFILE}`,
                 api: `http://${HOST}:${PORT}/rtc/v1/play/?token=${TOKEN}&uuid=${UUID}&stream=${UUID + PROFILE}&profile=${PROFILE}`,
                 clientip: null,
                 clientip: null,
                 sdp: offer.sdp,
                 sdp: offer.sdp,
-                streamurl: `webrtc://${HOST}/live/${UUID + PROFILE}?token=${TOKEN}&uuid=${UUID}&stream=${UUID + PROFILE}&profile=${PROFILE}`,
+                streamurl: `webrtc://${HOST}/replay/${STREAM}?token=${TOKEN}&starttime=${STIME}&endtime=${ETIME}&uuid=${UUID}&stream=${STREAM}&profile=${PROFILE}`,
+                tid: Number(Math.floor(new Date().getTime() * Math.random() * 100)).toString(16).slice(0, 7)
+            } : {
+                api: `http://${HOST}:${PORT}/rtc/v1/play/?token=${TOKEN}&uuid=${UUID}&stream=${UUID + PROFILE}&profile=${PROFILE}`,
+                clientip: null,
+                sdp: offer.sdp,
+                streamurl: `webrtc://${HOST}/live/${STREAM}?token=${TOKEN}&uuid=${UUID}&stream=${STREAM}&profile=${PROFILE}`,
                 tid: Number(Math.floor(new Date().getTime() * Math.random() * 100)).toString(16).slice(0, 7)
                 tid: Number(Math.floor(new Date().getTime() * Math.random() * 100)).toString(16).slice(0, 7)
             }
             }
             console.log('params', params)
             console.log('params', params)

+ 176 - 0
index.vue

@@ -0,0 +1,176 @@
+<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>