Browse Source

增加拉取多流demo
Signed-off-by: caner <5658514@qq.com>

caner 3 years ago
parent
commit
6622b31d1d
4 changed files with 289 additions and 13 deletions
  1. 5 0
      README.md
  2. 124 0
      SRSWebRtcPlayer.ts
  3. 147 0
      index_mute.vue
  4. 13 13
      index_only_one.vue

+ 5 - 0
README.md

@@ -1,2 +1,7 @@
 # srs-webrtc-demo
 # srs-webrtc-demo
 srs webrtc video demo
 srs webrtc video demo
+
+1. index_only_one.vue
+    拉取单流
+2. index_mute
+    拉去多流

+ 124 - 0
SRSWebRtcPlayer.ts

@@ -0,0 +1,124 @@
+import { number } from "echarts"
+
+/**
+ * srs webrtc palyer
+ * auth Caner
+ */
+class WebRtcPlayer {
+    private Peer: any
+    private TIMER: any
+    constructor(option = { HOST: '', TOKEN: '', UUID: '', PROFILE: number, PORT: number, DOM: HTMLElement }) {
+        this.initWebRtc(option.HOST, option.PORT, option.TOKEN, option.UUID, option.PROFILE, option.DOM).then(res => {
+            this.Peer = res
+        }).catch(() => {
+            this.Peer = null
+        })
+    }
+
+    /**
+     * 初始化webrtc
+     * @param HOST 媒体服务器地址
+     * @param TOKEN 用户token
+     * @param UUID 摄像头uuid
+     * @param PROFILE 码流
+     * @param DOM video节点
+     * @returns 
+     */
+    private async initWebRtc(HOST: string, PORT: number, TOKEN: string, UUID: string, PROFILE: number, DOM: HTMLElement | any | null) {
+        try {
+            const Peer = new RTCPeerConnection() as any
+            Peer.addTransceiver('video', { direction: 'recvonly' })
+            const offer = await Peer.createOffer()
+            await Peer.setLocalDescription(offer)
+
+            // 监听视频=播放
+            Peer.ontrack = (event: Event | any) => {
+                if (DOM) {
+                    const { streams } = event
+                    DOM.srcObject = streams[0]
+                    console.log('track', event)
+                }
+            }
+
+            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 params = {
+                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/${UUID + PROFILE}?token=${TOKEN}&uuid=${UUID}&stream=${UUID + PROFILE}&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) {
+            console.warn('webRtcInit:', error);
+            return null
+        }
+    }
+
+    /**
+     * 云台控制
+     * @param URL 
+     * @param UUID 
+     * @param TOKEN 
+     * @param command 指令:数字键盘1-9去掉5,10:焦距放大,11:焦距缩小 12:亮度,13:色彩饱和度,14:对比度,15:清晰度
+     * @param number [云台速度|焦距参数|色彩饱和度]等值  亮度值 0-100
+     * @returns 
+     */
+    public contrl(URL: string, UUID: string, TOKEN: string, command: number, number: number) {
+        if (!UUID) return
+        if (this.TIMER !== null) clearTimeout(this.TIMER)
+        this.TIMER = setTimeout(() => {
+            window.fetch(URL, {
+                method: 'POST',
+                headers: { 'Content-Type': 'application/json' },
+                body: JSON.stringify({
+                    code: 'cloudcontrol.control',
+                    token: TOKEN,
+                    body: {
+                        uuid: UUID,
+                        command,
+                        number
+                    }
+                })
+            })
+        }, 500);
+    }
+
+    /**
+     * 关闭webrtc
+     */
+    public async close() {
+        if (this.Peer) this.Peer.close()
+        if (this.TIMER) clearTimeout(this.TIMER)
+    }
+
+}
+
+export default WebRtcPlayer

+ 147 - 0
index_mute.vue

@@ -0,0 +1,147 @@
+<template>
+  <div class="videoBox">
+    <div class="box">
+      <div class="list">
+        <ul>
+          <li
+            v-for="(item, index) in cList"
+            :key="index"
+            @click="play(item.uuid)"
+          >
+            {{ item.name }}
+          </li>
+        </ul>
+      </div>
+      <video
+        id="test"
+        crossorigin="anonymous"
+        autoplay
+        playsinline
+        muted
+        controls
+      />
+    </div>
+
+    <div class="contrl">
+      <n-button @click="contrl(8)">
+        上
+      </n-button>
+      <n-button @click="contrl(2)">
+        下
+      </n-button>
+      <n-button @click="contrl(4)">
+        左
+      </n-button>
+      <n-button @click="contrl(6)">
+        右
+      </n-button>
+      <n-button @click="contrl(10)">
+        放大
+      </n-button>
+      <n-button @click="contrl(11)">
+        缩小
+      </n-button>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import axios from '@/utils/axios'
+import { onMounted, ref } from 'vue'
+import WebRtcPlayer from '@/utils/SRSWebRtcPlayer'
+
+const TOKEN = '833cd2ff8851509d0c4b2cab0dbdb74d'
+const cList = ref()
+const CUUID = ref('')
+let play1 = null as any
+
+// 获取摄像头播放地址
+const getCamer = async () => {
+  const { data } = await axios.post('http://20.20.20.9:8089', {
+    code: 'categorycamera.list',
+    token: TOKEN,
+    body: {}
+  })
+  // 35可控
+  cList.value = data.filter((el: { name: string }) => (el.name.includes('35')))
+  console.log('摄像头列表', cList.value)
+}
+
+// 播放
+const play = async (uuid:string) => {
+  if (play1) play1.close()
+  CUUID.value = uuid
+  play1 = new WebRtcPlayer({
+    HOST: '20.20.20.9',
+    TOKEN,
+    UUID: uuid,
+    PROFILE: 0,
+    PORT: 1985,
+    DOM: document.getElementById('test') as any
+  })
+}
+
+/**
+ * 云台控制
+ * @param command 指令:数字键盘1-9去掉5,10:焦距放大,11:焦距缩小 12:亮度,13:色彩饱和度,14:对比度,15:清晰度
+ * @param number [云台速度|焦距参数|色彩饱和度]等值  亮度值 0-100
+ */
+const contrl = (command: number, number = 1) => {
+  if (!play1) return
+  play1.contrl('http://20.20.20.9:8089', CUUID.value, TOKEN, command, number)
+}
+
+// 获取目录
+// const proList = async () => {
+//   const { data } = await axios.post('http://20.20.20.9:8089', {
+//     code: 'category.list',
+//     token: '833cd2ff8851509d0c4b2cab0dbdb74d',
+//     body: {}
+//   })
+//   // 零食取一个测试
+//   console.log(666, data)
+// }
+
+onMounted(() => {
+  getCamer()
+})
+
+</script>
+<style lang="less" scoped>
+.videoBox {
+  .box {
+    display: flex;
+    justify-content: center;
+
+    .list {
+      width: 150px;
+      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>

+ 13 - 13
index.vue → index_only_one.vue

@@ -23,29 +23,29 @@
     </div>
     </div>
 
 
     <div class="contrl">
     <div class="contrl">
-      <button @click="contrl(8)">
+      <n-button @click="contrl(8)">
-      </button>
-      <button @click="contrl(2)">
+      </n-button>
+      <n-button @click="contrl(2)">
-      </button>
-      <button @click="contrl(4)">
+      </n-button>
+      <n-button @click="contrl(4)">
-      </button>
-      <button @click="contrl(6)">
+      </n-button>
+      <n-button @click="contrl(6)">
-      </button>
-      <button @click="contrl(10)">
+      </n-button>
+      <n-button @click="contrl(10)">
         放大
         放大
-      </button>
-      <button @click="contrl(11)">
+      </n-button>
+      <n-button @click="contrl(11)">
         缩小
         缩小
-      </button>
+      </n-button>
     </div>
     </div>
   </div>
   </div>
 </template>
 </template>
 <script setup lang="ts">
 <script setup lang="ts">
-import axios from 'axios'
+import axios from '@/utils/axios'
 import { onMounted, onUnmounted, ref } from 'vue'
 import { onMounted, onUnmounted, ref } from 'vue'
 let webRtc: any = null
 let webRtc: any = null
 const TOKEN = '833cd2ff8851509d0c4b2cab0dbdb74d'
 const TOKEN = '833cd2ff8851509d0c4b2cab0dbdb74d'