From cd37af890600186215fd53c0d419c89c562e3e70 Mon Sep 17 00:00:00 2001
From: ‘liusuyi’ <1951119284@qq.com>
Date: 星期六, 23 九月 2023 16:02:06 +0800
Subject: [PATCH] 流媒体增加不转码自动按需拉流
---
ard-work/src/main/resources/templates/mediaMTX.html | 335 +++++--------------------------------------------------
1 files changed, 34 insertions(+), 301 deletions(-)
diff --git a/ard-work/src/main/resources/templates/mediaMTX.html b/ard-work/src/main/resources/templates/mediaMTX.html
index 90c51b4..7b1680a 100644
--- a/ard-work/src/main/resources/templates/mediaMTX.html
+++ b/ard-work/src/main/resources/templates/mediaMTX.html
@@ -1,307 +1,40 @@
<!DOCTYPE html>
-<html lang="en" xmlns:th="http://www.thymeleaf.org">
+<html>
<head>
<meta charset="UTF-8">
- <title>娴嬭瘯椤�</title>
- <script th:src="@{/js/jquery-3.6.4.min.js}"></script>
- <link rel="stylesheet" th:href="@{/css/bootstrap.css}"/>
- <script th:src="@{/js/bootstrap.js}"></script>
- <style>
- .video-container {
- display: inline-block;
- vertical-align: top;
- width: 33%; /* 3涓棰戝钩鍧囧垎閰嶄竴琛岀殑瀹藉害 */
- /*padding: 2px; !* 鍙互鏍规嵁闇�瑕佽皟鏁村唴杈硅窛 *!*/
- box-sizing: border-box;
- }
-
- .video-container video {
- width: 100%;
- height: 100%;
- /*object-fit: cover; !* 瑙嗛濉厖瀹瑰櫒锛屼繚鎸佸楂樻瘮 *!*/
- }
- </style>
+ <title>video.js鎾斁rtmp娴�</title>
+ <!--寮曞叆鎾斁鍣ㄦ牱寮�-->
+ <link href="http://vjs.zencdn.net/5.19/video-js.min.css" rel="stylesheet">
+ <!--寮曞叆鎾斁鍣╦s-->
+ <script src="http://vjs.zencdn.net/5.19/video.min.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/videojs-flash@2/dist/videojs-flash.min.js"></script>
+</head>
<body>
-<div>
- <div class="row">
- <div class="video-container">
- <video id="video1" muted autoplay loop controls></video>
- </div>
- <div class="video-container">
- <video id="video2" muted autoplay loop controls></video>
- </div>
- <div class="video-container">
- <video id="video3" muted autoplay loop controls></video>
- </div>
- <div class="video-container">
- <video id="video4" muted autoplay loop controls></video>
- </div>
- <div class="video-container">
- <video id="video5" muted autoplay loop controls></video>
- </div>
- </div>
-</div>
-<script th:inline="javascript">
- var chanMap = new Map();
- window.onload = function () {
-
- chanMap.set("video1", "http://127.0.0.1:8889/245/");
- chanMap.set("video2", "http://127.0.0.1:8889/164/");
- chanMap.set("video3", "http://127.0.0.1:8889/164/");
- chanMap.set("video4", "http://127.0.0.1:8889/165/");
- chanMap.set("video5", "http://127.0.0.1:8889/165/");
- console.log(chanMap);
- }
- const linkToIceServers = (links) => (
- (links !== null) ? links.split(', ').map((link) => {
- const m = link.match(/^<(.+?)>; rel="ice-server"(; username="(.*?)"; credential="(.*?)"; credential-type="password")?/i);
- const ret = {
- urls: [m[1]],
- };
-
- if (m[3] !== undefined) {
- ret.username = unquoteCredential(m[3]);
- ret.credential = unquoteCredential(m[4]);
- ret.credentialType = "password";
- }
-
- return ret;
- }) : []
- );
- const parseOffer = (offer) => {
- const ret = {
- iceUfrag: '',
- icePwd: '',
- medias: [],
- };
-
- for (const line of offer.split('\r\n')) {
- if (line.startsWith('m=')) {
- ret.medias.push(line.slice('m='.length));
- } else if (ret.iceUfrag === '' && line.startsWith('a=ice-ufrag:')) {
- ret.iceUfrag = line.slice('a=ice-ufrag:'.length);
- } else if (ret.icePwd === '' && line.startsWith('a=ice-pwd:')) {
- ret.icePwd = line.slice('a=ice-pwd:'.length);
- }
- }
-
- return ret;
- };
- const generateSdpFragment = (offerData, candidates) => {
- const candidatesByMedia = {};
- for (const candidate of candidates) {
- const mid = candidate.sdpMLineIndex;
- if (candidatesByMedia[mid] === undefined) {
- candidatesByMedia[mid] = [];
- }
- candidatesByMedia[mid].push(candidate);
- }
-
- let frag = 'a=ice-ufrag:' + offerData.iceUfrag + '\r\n'
- + 'a=ice-pwd:' + offerData.icePwd + '\r\n';
-
- let mid = 0;
-
- for (const media of offerData.medias) {
- if (candidatesByMedia[mid] !== undefined) {
- frag += 'm=' + media + '\r\n'
- + 'a=mid:' + mid + '\r\n';
-
- for (const candidate of candidatesByMedia[mid]) {
- frag += 'a=' + candidate.candidate + '\r\n';
- }
- }
- mid++;
- }
-
- return frag;
- }
-
- class WHEPClient {
- constructor(wurl, videoId) {
- this.video = videoId;
- this.url = new URL('whep', wurl);
- this.pc = null;
- this.restartTimeout = null;
- this.eTag = '';
- this.queuedCandidates = [];
- this.start();
- }
-
- start() {
- console.log("requesting ICE servers");
- fetch(this.url, {
- method: 'OPTIONS',
- })
- .then((res) => this.onIceServers(res))
- .catch((err) => {
- console.log('error: ' + err);
- this.scheduleRestart();
- });
- }
-
- onIceServers(res) {
- this.pc = new RTCPeerConnection({
- iceServers: linkToIceServers(res.headers.get('Link')),
- });
-
- const direction = "sendrecv";
- this.pc.addTransceiver("video", {direction});
- this.pc.addTransceiver("audio", {direction});
-
- this.pc.onicecandidate = (evt) => this.onLocalCandidate(evt);
- this.pc.oniceconnectionstatechange = () => this.onConnectionState();
-
- this.pc.ontrack = (evt) => {
- console.log("new track:", evt.track.kind);
- document.getElementById(this.video).srcObject = evt.streams[0];
- };
-
- this.pc.createOffer()
- .then((offer) => this.onLocalOffer(offer));
- }
-
- onLocalOffer(offer) {
- this.offerData = parseOffer(offer.sdp);
- this.pc.setLocalDescription(offer);
-
- console.log("sending offer");
-
- fetch(this.url, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/sdp',
- },
- body: offer.sdp,
- })
- .then((res) => {
- if (res.status !== 201) {
- throw new Error('bad status code');
- }
- this.eTag = res.headers.get('E-Tag');
- return res.text();
- })
- .then((sdp) => this.onRemoteAnswer(new RTCSessionDescription({
- type: 'answer',
- sdp,
- })))
- .catch((err) => {
- console.log('error: ' + err);
- this.scheduleRestart();
- });
- }
-
- onConnectionState() {
- if (this.restartTimeout !== null) {
- return;
- }
-
- console.log("peer connection state:", this.pc.iceConnectionState);
-
- switch (this.pc.iceConnectionState) {
- case "disconnected":
- this.scheduleRestart();
- }
- }
-
- onRemoteAnswer(answer) {
- if (this.restartTimeout !== null) {
- return;
- }
-
- this.pc.setRemoteDescription(new RTCSessionDescription(answer));
-
- if (this.queuedCandidates.length !== 0) {
- this.sendLocalCandidates(this.queuedCandidates);
- this.queuedCandidates = [];
- }
- }
-
- onLocalCandidate(evt) {
- if (this.restartTimeout !== null) {
- return;
- }
-
- if (evt.candidate !== null) {
- if (this.eTag === '') {
- this.queuedCandidates.push(evt.candidate);
- } else {
- this.sendLocalCandidates([evt.candidate])
- }
- }
- }
-
- sendLocalCandidates(candidates) {
- fetch(this.url, {
- method: 'PATCH',
- headers: {
- 'Content-Type': 'application/trickle-ice-sdpfrag',
- 'If-Match': this.eTag,
- },
- body: generateSdpFragment(this.offerData, candidates),
- })
- .then((res) => {
- if (res.status !== 204) {
- throw new Error('bad status code');
- }
- })
- .catch((err) => {
- console.log('error: ' + err);
- this.scheduleRestart();
- });
- }
-
- scheduleRestart() {
- if (this.restartTimeout !== null) {
- return;
- }
-
- if (this.pc !== null) {
- this.pc.close();
- this.pc = null;
- }
-
- this.restartTimeout = window.setTimeout(() => {
- this.restartTimeout = null;
- this.start();
- }, restartPause);
-
- this.eTag = '';
- this.queuedCandidates = [];
- }
-
- stop() {
- if (this.pc) {
- try {
- this.pc.close();
- } catch (e) {
- console.log("Failure close peer connection:" + e);
- }
- this.pc = null;
- }
- }
- }
-
- let videoMap = new Map();
- $('video').click(function (e) {
- let ID = e.target.id;//鑾峰彇褰撳墠鐐瑰嚮浜嬩欢鐨勫厓绱�
- console.log(ID);
- console.log(videoMap);
- if (videoMap.get(ID) != null) {
- closeVideo(ID);
- } else {
- let stream = chanMap.get(ID);
- let client = new WHEPClient(stream, ID);
- videoMap.set(ID, client);
- }
- });
-
- function closeVideo(id) {
- console.log("鍏抽棴" + id)
- let client = videoMap.get(id);
- client.stop(id);
- videoMap.delete(id);
- }
+<!--vjs-big-play-centered 鎾斁鎸夐挳灞呬腑-->
+<!--poster榛樿鐨勬樉绀虹晫闈紝灏辨槸杩樻病鐐规挱鏀撅紝缁欎綘鏄剧ず鐨勭晫闈�-->
+<!--controls 瑙勫畾娴忚鍣ㄥ簲璇ヤ负瑙嗛鎻愪緵鎾斁鎺т欢-->
+<!--preload="auto" 鏄惁鎻愬墠鍔犺浇-->
+<!--autoplay 鑷姩鎾斁-->
+<!--loop=true 鑷姩寰幆-->
+<!--data-setup='{"example_option":true}' 鍙互鎶婁竴浜涘睘鎬у啓鍒拌繖涓噷闈㈡潵锛屽data-setup={"autoplay":true}-->
+<video id="my-player"
+ class="video-js vjs-default-skin vjs-big-play-centered" controls
+ preload="auto" autoplay="autoplay"
+ poster="images/logo.png" width="500" height="400"
+ data-setup='{}'>
+ <!--src: 瑙勫畾濯掍綋鏂囦欢鐨� URL type:瑙勫畾濯掍綋璧勬簮鐨勭被鍨�-->
+ <source src='rtmp://192.168.1.194:1935/164' type='rtmp/flv' />
+</video>
+<script type="text/javascript">
+ // 璁剧疆flash璺緞,鐢ㄤ簬鍦╲ideojs鍙戠幇娴忚鍣ㄤ笉鏀寔HTML5鎾斁鍣ㄧ殑鏃跺�欒嚜鍔ㄥ敜璧穎lash鎾斁鍣�
+ videojs.options.flash.swf = 'https://cdn.bootcss.com/videojs-swf/5.4.1/video-js.swf';
+ //my-player涓洪〉闈ideo鍏冪礌鐨刬d
+ var player = videojs('my-player');
+ //鎾斁
+ player.play();
+ // 1. 鎾斁 player.play()
+ // 2. 鍋滄 player.pause()
+ // 3. 鏆傚仠 player.pause()
</script>
</body>
-</html>
\ No newline at end of file
+</html>
--
Gitblit v1.9.3