From 7f5ee58fbb3023cbdc3c1196944103f8af45175d Mon Sep 17 00:00:00 2001 From: acgist <289547414@qq.com> Date: Sat, 3 Dec 2022 14:02:11 +0800 Subject: [PATCH] =?UTF-8?q?[*]=20mesh=E5=A4=9A=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +- docs/sequence/{MCU.iuml => Moon.iuml} | 0 docs/sequence/SFU.iuml | 32 --- pom.xml | 10 +- taoyao-boot/src/main/resources/banner.txt | 3 + .../acgist/taoyao/meeting/MeetingManager.java | 2 +- taoyao-server/pom.xml | 6 - .../src/main/resources/application.yml | 14 +- .../resources/static/javascript/taoyao.js | 256 +++++++++++------- .../src/main/resources/static/meeting.html | 19 +- .../acgist/taoyao}/annotation/CostedTest.java | 2 +- .../CostedTestTestExecutionListener.java | 2 +- .../acgist/taoyao}/annotation/TaoyaoTest.java | 2 +- .../taoyao/boot/service/IdServiceTest.java | 4 +- .../com/acgist/taoyao/signal/SignalTest.java | 2 +- .../signal/protocol/ScriptProtocolTest.java | 2 +- .../signal/protocol/ShutdownProtocolTest.java | 2 +- taoyao-signal/README.md | 6 +- taoyao-test/pom.xml | 27 -- taoyao-webrtc/README.md | 12 +- 20 files changed, 197 insertions(+), 218 deletions(-) rename docs/sequence/{MCU.iuml => Moon.iuml} (100%) delete mode 100644 docs/sequence/SFU.iuml rename {taoyao-test/src/main/java/com/acgist/taoyao/test => taoyao-server/src/test/java/com/acgist/taoyao}/annotation/CostedTest.java (94%) rename {taoyao-test/src/main/java/com/acgist/taoyao/test => taoyao-server/src/test/java/com/acgist/taoyao}/annotation/CostedTestTestExecutionListener.java (97%) rename {taoyao-test/src/main/java/com/acgist/taoyao/test => taoyao-server/src/test/java/com/acgist/taoyao}/annotation/TaoyaoTest.java (95%) delete mode 100644 taoyao-test/pom.xml diff --git a/README.md b/README.md index 5922bec..0417f5d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ |taoyao|桃夭|桃之夭夭灼灼其华| |taoyao-boot|基础|基础模块| |taoyao-live|直播|直播、连麦、本地视频同看| -|taoyao-test|测试|测试模块| |taoyao-media|媒体|录制
音频(降噪、混音、变声)
视频(水印、美颜、AI识别)| |taoyao-signal|信令|信令服务| |taoyao-server|服务|启动服务| @@ -29,9 +28,9 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | taoyao-media | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| taoyao-moon | | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ taoyao-mesh + -| taoyao-kurento | | +| taoyao-webrtc-moon | | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ taoyao-webrtc-mesh + +| taoyao-webrtc-kurento | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | taoyao-signal | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -50,9 +49,9 @@ #### 功能简介 * ~~直播~~ -* 会议:一对一、~~多对多~~ * ~~媒体:降噪、变声、美颜录制、等等~~ -* 可能需要自己搭建`coturn`服务实现`STUN`/`TURN`内网穿透功能 +* 可能需要自己搭建`coturn`服务实现`STUN`/`TURN`功能 +* 终端和终端之间各自建立一个独立媒体连接 ### Moon @@ -65,3 +64,4 @@ * 需要安装[KMS服务](./docs/Deploy.md#kmskurento-media-server) * 提供混音、变声、美颜、录制等等媒体功能 * 终端推送给服务端最高质量媒体,再由服务端根据订阅终端按配置分流。 +* 终端和服务器之间建立两个媒体连接,一个本地媒体,一个远程媒体。 diff --git a/docs/sequence/MCU.iuml b/docs/sequence/Moon.iuml similarity index 100% rename from docs/sequence/MCU.iuml rename to docs/sequence/Moon.iuml diff --git a/docs/sequence/SFU.iuml b/docs/sequence/SFU.iuml deleted file mode 100644 index 2138d47..0000000 --- a/docs/sequence/SFU.iuml +++ /dev/null @@ -1,32 +0,0 @@ -@startuml - -title WebRTC-Mesh - -actor ClientA as ClientA -participant "Signal" as Signal -actor ClientB as ClientB -actor ClientC as ClientC - -autonumber - -ClientA -> Signal: 进入房间 -activate ClientA -activate Signal -Signal -> ClientB: ClientA进入房间 -activate ClientB -ClientB -> Signal: 订阅ClientA -Signal -> ClientA: ClientB订阅ClientA -ClientA -> Signal: ClientA发布ClientB -Signal -> ClientB: ClientA发布 -deactivate ClientB -Signal -> ClientC: ClientA进入房间 -activate ClientC -ClientC -> Signal: 订阅ClientA -Signal -> ClientA: ClientC订阅ClientA -ClientA -> Signal: ClientA发布ClientC -Signal -> ClientC: ClientA发布 -deactivate ClientC -deactivate Signal -deactivate ClientA - -@enduml \ No newline at end of file diff --git a/pom.xml b/pom.xml index d254aa6..075be2d 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,6 @@ taoyao-boot taoyao-live - taoyao-test taoyao-media taoyao-signal taoyao-server @@ -113,11 +112,6 @@ taoyao-live ${project.version} - - com.acgist - taoyao-test - ${project.version} - com.acgist taoyao-media @@ -125,12 +119,12 @@ com.acgist - taoyao-signal + taoyao-server ${project.version} com.acgist - taoyao-server + taoyao-signal ${project.version} diff --git a/taoyao-boot/src/main/resources/banner.txt b/taoyao-boot/src/main/resources/banner.txt index 5ca4fe5..f62737c 100644 --- a/taoyao-boot/src/main/resources/banner.txt +++ b/taoyao-boot/src/main/resources/banner.txt @@ -8,3 +8,6 @@ :: Spring Boot : ${spring-boot.formatted-version} :: ${spring.application.name} : https://gitee.com/acgist/taoyao + +中庭地白树栖鸦,冷露无声湿桂花。 +今夜月明人尽望,不知秋思落谁家。 diff --git a/taoyao-meeting/src/main/java/com/acgist/taoyao/meeting/MeetingManager.java b/taoyao-meeting/src/main/java/com/acgist/taoyao/meeting/MeetingManager.java index 233c5e3..1a01356 100644 --- a/taoyao-meeting/src/main/java/com/acgist/taoyao/meeting/MeetingManager.java +++ b/taoyao-meeting/src/main/java/com/acgist/taoyao/meeting/MeetingManager.java @@ -65,7 +65,7 @@ public class MeetingManager { */ public Meeting create(String sn) { final Meeting meeting = new Meeting(); - meeting.setId(this.idService.buildIdToString()); + meeting.setId("1"); meeting.setSns(new CopyOnWriteArrayList<>()); meeting.setCreator(sn); meeting.addSn(sn); diff --git a/taoyao-server/pom.xml b/taoyao-server/pom.xml index c508c24..79b8168 100644 --- a/taoyao-server/pom.xml +++ b/taoyao-server/pom.xml @@ -30,12 +30,6 @@ com.acgist taoyao-meeting - - - com.acgist - taoyao-test - test - diff --git a/taoyao-server/src/main/resources/application.yml b/taoyao-server/src/main/resources/application.yml index f361c15..e28fcb8 100644 --- a/taoyao-server/src/main/resources/application.yml +++ b/taoyao-server/src/main/resources/application.yml @@ -91,19 +91,19 @@ taoyao: # 媒体端口范围 min-port: 45535 max-port: 65535 + # 公共服务 stun: - stun:stun1.l.google.com:19302 - stun:stun2.l.google.com:19302 - stun:stun3.l.google.com:19302 - stun:stun4.l.google.com:19302 - - stun:stun.stunprotocol.org:3478 + # 自己搭建:coturn turn: - - stun:stun1.l.google.com:19302 - - stun:stun2.l.google.com:19302 - - stun:stun3.l.google.com:19302 - - stun:stun4.l.google.com:19302 - - stun:stun.stunprotocol.org:3478 - # KMS服务配置 + - turn:127.0.0.1:8888 + - turn:127.0.0.1:8888 + - turn:127.0.0.1:8888 + - turn:127.0.0.1:8888 + # KMS服务配置:可以部署多个简单实现负载均衡 kms: host: 192.168.1.100 port: 18888 diff --git a/taoyao-server/src/main/resources/static/javascript/taoyao.js b/taoyao-server/src/main/resources/static/javascript/taoyao.js index ec066f8..f3f6c28 100644 --- a/taoyao-server/src/main/resources/static/javascript/taoyao.js +++ b/taoyao-server/src/main/resources/static/javascript/taoyao.js @@ -60,7 +60,7 @@ const defaultRPCConfig = { /** 信令配置 */ const signalConfig = { /** 当前终端SN */ - sn: localStorage.getItem('taoyao.sn') || 'taoyao', + sn: 'taoyao', /** 当前版本 */ version: '1.0.0', // 信令授权 @@ -170,6 +170,7 @@ const signalChannel = { clearTimeout(self.heartbeatTimer); } self.heartbeatTimer = setTimeout(function() { + // 电池:navigator.getBattery() if (self.channel && self.channel.readyState === WebSocket.OPEN) { self.push(signalProtocol.buildProtocol( signalProtocol.client.heartbeat, @@ -341,9 +342,23 @@ const signalChannel = { }, /** 终端默认回调 */ defaultClientConfig: function(data) { - this.taoyao + let self = this; + // 配置终端 + self.taoyao .configMedia(data.body.media.audio, data.body.media.video) .configWebrtc(data.body.webrtc); + // 打开媒体通道 + let videoId = self.taoyao.videoId; + if(videoId) { + self.taoyao.buildLocalMedia() + .then(stream => { + self.taoyao.buildMediaChannel(videoId, stream); + }) + .catch(e => console.error('打开终端媒体失败', e)); + console.debug('自动打开媒体通道', videoId); + } else { + console.debug('没有配置本地媒体信息跳过自动打开媒体通道'); + } }, defaultClientReboot: function(data) { console.info('重启终端'); @@ -355,10 +370,10 @@ const signalChannel = { defaultMediaSubscribe: function(data) { let self = this; const from = data.body.from; - this.taoyao.remoteClientFilter(from, true); - self.taoyao.localMediaChannel.createOffer().then(description => { + const remote = this.taoyao.remoteClientFilter(from, true); + remote.localMediaChannel.createOffer().then(description => { console.debug('Local Create Offer', description); - self.taoyao.localMediaChannel.setLocalDescription(description); + remote.localMediaChannel.setLocalDescription(description); self.push(signalProtocol.buildProtocol( signalProtocol.media.offer, { @@ -374,11 +389,11 @@ const signalChannel = { defaultMediaOffer: function(data) { let self = this; const from = data.body.from; - this.taoyao.remoteClientFilter(from, true); - self.taoyao.remoteMediaChannel.setRemoteDescription(new RTCSessionDescription(data.body.sdp)); - self.taoyao.remoteMediaChannel.createAnswer().then(description => { + const remote = this.taoyao.remoteClientFilter(from, true); + remote.remoteMediaChannel.setRemoteDescription(new RTCSessionDescription(data.body.sdp)); + remote.remoteMediaChannel.createAnswer().then(description => { console.debug('Remote Create Answer', description); - self.taoyao.remoteMediaChannel.setLocalDescription(description); + remote.remoteMediaChannel.setLocalDescription(description); self.push(signalProtocol.buildProtocol( signalProtocol.media.answer, { @@ -392,18 +407,27 @@ const signalChannel = { }); }, defaultMediaAnswer: function(data) { - this.taoyao.localMediaChannel.setRemoteDescription(new RTCSessionDescription(data.body.sdp)); + const from = data.body.from; + const remote = this.taoyao.remoteClientFilter(from, true); + remote.localMediaChannel.setRemoteDescription(new RTCSessionDescription(data.body.sdp)); }, defaultMediaCandidate: function(data) { if(!this.taoyao.checkCandidate(data.body.candidate)) { console.debug('候选缺失要素', data); return; } - console.debug('Set ICE Candidate', this.taoyao.remoteMediaChannel); + console.debug('Set ICE Candidate', data.body); + const from = data.body.from; + const remote = this.taoyao.remoteClientFilter(from, true); if(data.body.type === 'local') { - this.taoyao.remoteMediaChannel.addIceCandidate(new RTCIceCandidate(data.body.candidate)); + remote.remoteMediaChannel.addIceCandidate(new RTCIceCandidate(data.body.candidate)); + } else if(data.body.type === 'remote'){ + remote.localMediaChannel.addIceCandidate(new RTCIceCandidate(data.body.candidate)); + } else if(data.body.type === 'mesh') { + remote.localMediaChannel.addIceCandidate(new RTCIceCandidate(data.body.candidate)); + // remote.remoteMediaChannel.addIceCandidate(new RTCIceCandidate(data.body.candidate)); } else { - this.taoyao.localMediaChannel.addIceCandidate(new RTCIceCandidate(data.body.candidate)); + console.warn('不支持的候选类型', data.body.type); } }, /** 会议默认回调 */ @@ -413,10 +437,14 @@ const signalChannel = { }; /** 终端 */ function TaoyaoClient( + taoyao, sn, + shareMediaChannel, audioEnabled, videoEnabled ) { + /** 桃夭 */ + this.taoyao = taoyao; /** 终端标识 */ this.sn = sn; /** 视频对象 */ @@ -429,6 +457,12 @@ function TaoyaoClient( this.audioStatus = false; this.videoStatus = false; this.recordStatus = false; + /** 本地媒体通道 */ + this.localMediaChannel = null; + /** 远程媒体通道 */ + this.remoteMediaChannel = null; + /** 是否共享媒体通道 */ + this.shareMediaChannel = shareMediaChannel; /** 媒体状态:是否播放 */ this.audioEnabled = audioEnabled == undefined ? true : audioEnabled; this.videoEnabled = videoEnabled == undefined ? true : videoEnabled; @@ -453,6 +487,7 @@ function TaoyaoClient( /** 关闭视频 */ this.close = async function() { await this.video.close(); + // TODO:释放连接 return this; }; /** 设置媒体 */ @@ -474,15 +509,21 @@ function TaoyaoClient( if(track.kind === 'video') { this.buildVideoTrack(track); } - } else { + } else if(stream) { let audioTrack = stream.getAudioTracks(); let videoTrack = stream.getVideoTracks(); + // TODO:验证API试试修改媒体 + // audioTrack.getSettings + // audioTrack.getCapabilities + // audioTrack.applyCapabilities if(audioTrack && audioTrack.length) { audioTrack.forEach(v => this.buildAudioTrack(v)); } if(videoTrack && videoTrack.length) { videoTrack.forEach(v => this.buildVideoTrack(v)); } + } else { + throw new Error('无效媒体信息'); } console.debug('设置媒体', this.video, this.stream, this.audioTrack, this.videoTrack); await this.load(); @@ -509,13 +550,53 @@ function TaoyaoClient( this.stream.addTrack(track); } }; + /** 打开媒体通道 */ + this.openMediaChannel = function() { + if(this.shareMediaChannel) { + this.localMediaChannel = this.taoyao.localMediaChannel; + this.remoteMediaChannel = this.taoyao.remoteMediaChannel; + } else { + let self = this; + // 本地通道 + let mediaChannel = new RTCPeerConnection(defaultRPCConfig); + self.taoyao.localClient.audioTrack.forEach(v => mediaChannel.addTrack(v, self.taoyao.localClient.stream)); + self.taoyao.localClient.videoTrack.forEach(v => mediaChannel.addTrack(v, self.taoyao.localClient.stream)); + mediaChannel.ontrack = function(e) { + console.debug('Mesh Media Track', self.sn, e); + let remote = self.taoyao.remoteClientFilter(self.sn); + remote.buildStream(remote.sn, e.streams[0], e.track); + }; + mediaChannel.onicecandidate = function(e) { + // TODO:判断给谁 + let to = self.taoyao.remoteClient.map(v => v.sn)[0]; + if(!self.taoyao.checkCandidate(e.candidate)) { + console.debug('Send Mesh ICE Candidate Fail', e); + return; + } + console.debug('Send Mesh ICE Candidate', to, e); + self.taoyao.push(signalProtocol.buildProtocol( + signalProtocol.media.candidate, + { + to: to, + type: 'mesh', + candidate: e.candidate + } + )); + }; + this.localMediaChannel = mediaChannel; + this.remoteMediaChannel = mediaChannel; + } + }; } /** 桃夭 */ function Taoyao( + videoId, webSocket, localClientAudioEnabled, localClientVideoEnabled ) { + /** 本地视频ID */ + this.videoId = videoId; /** WebRTC配置 */ this.webrtc = null; /** WebSocket地址 */ @@ -538,6 +619,8 @@ function Taoyao( /** 远程终端 */ this.remoteClient = []; this.remoteMediaChannel = null; + /** 是否共享媒体通道 */ + this.shareMediaChannel = true; /** 信令通道 */ this.signalChannel = null; /** 媒体配置 */ @@ -551,6 +634,7 @@ function Taoyao( this.configWebrtc = function(config = {}) { this.webrtc = config; this.webSocket = this.webrtc.signal.address; + this.shareMediaChannel = this.webrtc.framework === 'MOON'; defaultRPCConfig.iceServers = this.webrtc.stun.map(v => ({'urls': v})); console.debug('WebRTC配置', this.webrtc, defaultRPCConfig); return this; @@ -560,8 +644,8 @@ function Taoyao( signalChannel.taoyao = this; this.signalChannel = signalChannel; // 不能直接this.push = this.signalChannel.push这样导致this对象错误 - this.push = function(data, callback) { - this.signalChannel.push(data, callback) + this.push = function(data, pushCallback) { + this.signalChannel.push(data, pushCallback); }; return this.signalChannel.connect(this.webSocket, callback); }; @@ -607,11 +691,6 @@ function Taoyao( }) .then(resolve) .catch(reject); - // 兼容旧版 - // navigator.getUserMedia({ - // audio: self.audioConfig, - // video: self.videoConfig - // }, resolve, reject); }) .catch(e => { console.error('检查终端设备异常', e); @@ -625,12 +704,17 @@ function Taoyao( }; /** 远程终端过滤 */ this.remoteClientFilter = function(sn, autoBuild) { + if(sn === signalConfig.sn) { + console.warn('远程终端等于本地终端'); + return this.localClient; + } let array = this.remoteClient.filter(v => v.sn === sn); let remote = null; if(array.length > 0) { remote = array[0]; } else if(autoBuild) { - remote = new TaoyaoClient(sn); + remote = new TaoyaoClient(this, sn, this.shareMediaChannel); + remote.openMediaChannel(); this.remoteClient.push(remote); } return remote; @@ -647,86 +731,60 @@ function Taoyao( this.buildMediaChannel = async function(localVideoId, stream) { let self = this; // 本地视频 - this.localClient = new TaoyaoClient(signalConfig.sn, this.localClientAudioEnabled, this.localClientVideoEnabled); + this.localClient = new TaoyaoClient(this, signalConfig.sn, this.shareMediaChannel, this.localClientAudioEnabled, this.localClientVideoEnabled); await this.localClient.buildStream(localVideoId, stream); - // 本地通道 - this.localMediaChannel = new RTCPeerConnection(defaultRPCConfig); - this.localClient.audioTrack.forEach(v => this.localMediaChannel.addTrack(v, this.localClient.stream)); - this.localClient.videoTrack.forEach(v => this.localMediaChannel.addTrack(v, this.localClient.stream)); - this.localMediaChannel.ontrack = function(e) { - console.debug('Local Media Track', e); - }; - this.localMediaChannel.ondatachannel = function(channel) { - channel.onopen = function() { - console.debug('Local DataChannel Open'); - } - channel.onmessage = function(data) { - console.debug('Local DataChannel Message', data); - } - channel.onclose = function() { - console.debug('Local DataChannel Close'); - } - channel.onerror = function(e) { - console.debug('Local DataChannel Error', e); - } - }; - this.localMediaChannel.onicecandidate = function(e) { - // TODO:判断给谁 - let to = self.remoteClient.map(v => v.sn)[0]; - if(!self.checkCandidate(e.candidate)) { - console.debug('Send Local ICE Candidate Fail', e); - return; - } - console.debug('Send Local ICE Candidate', to, e); - self.push(signalProtocol.buildProtocol( - signalProtocol.media.candidate, - { - to: to, - type: 'local', - candidate: e.candidate + if(this.shareMediaChannel) { + // 本地通道 + this.localMediaChannel = new RTCPeerConnection(defaultRPCConfig); + this.localClient.audioTrack.forEach(v => this.localMediaChannel.addTrack(v, this.localClient.stream)); + this.localClient.videoTrack.forEach(v => this.localMediaChannel.addTrack(v, this.localClient.stream)); + this.localMediaChannel.ontrack = function(e) { + console.debug('Local Media Track', e); + }; + this.localMediaChannel.onicecandidate = function(e) { + // TODO:判断给谁 + let to = self.remoteClient.map(v => v.sn)[0]; + if(!self.checkCandidate(e.candidate)) { + console.debug('Send Local ICE Candidate Fail', e); + return; } - )); - }; - // 远程通道 - this.remoteMediaChannel = new RTCPeerConnection(defaultRPCConfig); - this.remoteMediaChannel.ontrack = function(e) { - console.debug('Remote Media Track', e); - // TODO:匹配 - let remote = self.remoteClient[0]; - remote.buildStream(remote.sn, e.streams[0], e.track); - }; - this.remoteMediaChannel.ondatachannel = function(channel) { - channel.onopen = function() { - console.debug('Remote DataChannel Open'); - } - channel.onmessage = function(data) { - console.debug('Remote DataChannel Message', data); - } - channel.onclose = function() { - console.debug('Remote DataChannel Close'); - } - channel.onerror = function(e) { - console.debug('Remote DataChannel Error', e); - } - }; - this.remoteMediaChannel.onicecandidate = function(e) { - // TODO:判断给谁 - let to = self.remoteClient.map(v => v.sn)[0]; - if(!self.checkCandidate(e.candidate)) { - console.debug('Send Remote ICE Candidate Fail', e); - return; - } - console.debug('Send Remote ICE Candidate', to, e); - self.push(signalProtocol.buildProtocol( - signalProtocol.media.candidate, - { - to: to, - type: 'remote', - candidate: e.candidate + console.debug('Send Local ICE Candidate', to, e); + self.push(signalProtocol.buildProtocol( + signalProtocol.media.candidate, + { + to: to, + type: 'local', + candidate: e.candidate + } + )); + }; + // 远程通道 + this.remoteMediaChannel = new RTCPeerConnection(defaultRPCConfig); + this.remoteMediaChannel.ontrack = function(e) { + console.debug('Remote Media Track', e); + // TODO:匹配 + let remote = self.remoteClient[0]; + remote.buildStream(remote.sn, e.streams[0], e.track); + }; + this.remoteMediaChannel.onicecandidate = function(e) { + // TODO:判断给谁 + let to = self.remoteClient.map(v => v.sn)[0]; + if(!self.checkCandidate(e.candidate)) { + console.debug('Send Remote ICE Candidate Fail', e); + return; } - )); - }; - console.debug('打开媒体通道', this.localMediaChannel, this.remoteMediaChannel); + console.debug('Send Remote ICE Candidate', to, e); + self.push(signalProtocol.buildProtocol( + signalProtocol.media.candidate, + { + to: to, + type: 'remote', + candidate: e.candidate + } + )); + }; + console.debug('打开共享媒体通道', this.localMediaChannel, this.remoteMediaChannel); + } return this; }; /** 校验candidate */ diff --git a/taoyao-server/src/main/resources/static/meeting.html b/taoyao-server/src/main/resources/static/meeting.html index b42237f..2365f92 100644 --- a/taoyao-server/src/main/resources/static/meeting.html +++ b/taoyao-server/src/main/resources/static/meeting.html @@ -51,38 +51,27 @@ }, mounted() { let self = this; - this.taoyao = new Taoyao(); + this.taoyao = new Taoyao('local'); this.remoteClient = this.taoyao.remoteClient; // 打开信令通道 this.taoyao .buildChannel(self.callback) .then(e => console.debug('信令通道连接成功')); - // 打开媒体通道 - this.taoyao.buildLocalMedia() - .then(stream => { - self.taoyao.buildMediaChannel('local', stream); - }) - .catch(e => { - console.error('打开终端媒体失败', e); - // 方便相同电脑测试 - self.taoyao.buildMediaChannel('local', null); - }); }, beforeDestroy() { }, methods: { - // 信令回调:返回true表示已经处理 + // 信令回调:true表示已经处理;false表示没有处理; callback: function(data) { let self = this; switch(data.header.pid) { - case signalProtocol.client.config: - // 如果需要下发配置生效需要在此打开媒体通道 - return false; } return false; }, // 创建会议 create: function(event) { + let sn = prompt('你的账号', signalConfig.sn); + signalConfig.sn = sn; let self = this; this.taoyao.meetingCreate(data => { self.taoyao.meetingEnter(data.body.id); diff --git a/taoyao-test/src/main/java/com/acgist/taoyao/test/annotation/CostedTest.java b/taoyao-server/src/test/java/com/acgist/taoyao/annotation/CostedTest.java similarity index 94% rename from taoyao-test/src/main/java/com/acgist/taoyao/test/annotation/CostedTest.java rename to taoyao-server/src/test/java/com/acgist/taoyao/annotation/CostedTest.java index d350938..a21678f 100644 --- a/taoyao-test/src/main/java/com/acgist/taoyao/test/annotation/CostedTest.java +++ b/taoyao-server/src/test/java/com/acgist/taoyao/annotation/CostedTest.java @@ -1,4 +1,4 @@ -package com.acgist.taoyao.test.annotation; +package com.acgist.taoyao.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/taoyao-test/src/main/java/com/acgist/taoyao/test/annotation/CostedTestTestExecutionListener.java b/taoyao-server/src/test/java/com/acgist/taoyao/annotation/CostedTestTestExecutionListener.java similarity index 97% rename from taoyao-test/src/main/java/com/acgist/taoyao/test/annotation/CostedTestTestExecutionListener.java rename to taoyao-server/src/test/java/com/acgist/taoyao/annotation/CostedTestTestExecutionListener.java index fa9eb10..03d7576 100644 --- a/taoyao-test/src/main/java/com/acgist/taoyao/test/annotation/CostedTestTestExecutionListener.java +++ b/taoyao-server/src/test/java/com/acgist/taoyao/annotation/CostedTestTestExecutionListener.java @@ -1,4 +1,4 @@ -package com.acgist.taoyao.test.annotation; +package com.acgist.taoyao.annotation; import java.lang.reflect.InvocationTargetException; import java.util.concurrent.CountDownLatch; diff --git a/taoyao-test/src/main/java/com/acgist/taoyao/test/annotation/TaoyaoTest.java b/taoyao-server/src/test/java/com/acgist/taoyao/annotation/TaoyaoTest.java similarity index 95% rename from taoyao-test/src/main/java/com/acgist/taoyao/test/annotation/TaoyaoTest.java rename to taoyao-server/src/test/java/com/acgist/taoyao/annotation/TaoyaoTest.java index 8dc269a..02b8fda 100644 --- a/taoyao-test/src/main/java/com/acgist/taoyao/test/annotation/TaoyaoTest.java +++ b/taoyao-server/src/test/java/com/acgist/taoyao/annotation/TaoyaoTest.java @@ -1,4 +1,4 @@ -package com.acgist.taoyao.test.annotation; +package com.acgist.taoyao.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/taoyao-server/src/test/java/com/acgist/taoyao/boot/service/IdServiceTest.java b/taoyao-server/src/test/java/com/acgist/taoyao/boot/service/IdServiceTest.java index 1d9d4c2..dee87d5 100644 --- a/taoyao-server/src/test/java/com/acgist/taoyao/boot/service/IdServiceTest.java +++ b/taoyao-server/src/test/java/com/acgist/taoyao/boot/service/IdServiceTest.java @@ -3,9 +3,9 @@ package com.acgist.taoyao.boot.service; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import com.acgist.taoyao.annotation.CostedTest; +import com.acgist.taoyao.annotation.TaoyaoTest; import com.acgist.taoyao.main.TaoyaoApplication; -import com.acgist.taoyao.test.annotation.TaoyaoTest; -import com.acgist.taoyao.test.annotation.CostedTest; import lombok.extern.slf4j.Slf4j; diff --git a/taoyao-server/src/test/java/com/acgist/taoyao/signal/SignalTest.java b/taoyao-server/src/test/java/com/acgist/taoyao/signal/SignalTest.java index e1d445a..f25edc8 100644 --- a/taoyao-server/src/test/java/com/acgist/taoyao/signal/SignalTest.java +++ b/taoyao-server/src/test/java/com/acgist/taoyao/signal/SignalTest.java @@ -7,8 +7,8 @@ import java.util.concurrent.CountDownLatch; import org.junit.jupiter.api.Test; +import com.acgist.taoyao.annotation.TaoyaoTest; import com.acgist.taoyao.main.TaoyaoApplication; -import com.acgist.taoyao.test.annotation.TaoyaoTest; import lombok.extern.slf4j.Slf4j; diff --git a/taoyao-server/src/test/java/com/acgist/taoyao/signal/protocol/ScriptProtocolTest.java b/taoyao-server/src/test/java/com/acgist/taoyao/signal/protocol/ScriptProtocolTest.java index 7bd8d72..7a62826 100644 --- a/taoyao-server/src/test/java/com/acgist/taoyao/signal/protocol/ScriptProtocolTest.java +++ b/taoyao-server/src/test/java/com/acgist/taoyao/signal/protocol/ScriptProtocolTest.java @@ -7,9 +7,9 @@ import java.util.Map; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import com.acgist.taoyao.annotation.TaoyaoTest; import com.acgist.taoyao.main.TaoyaoApplication; import com.acgist.taoyao.signal.protocol.platform.ScriptProtocol; -import com.acgist.taoyao.test.annotation.TaoyaoTest; @TaoyaoTest(classes = TaoyaoApplication.class) class ScriptProtocolTest { diff --git a/taoyao-server/src/test/java/com/acgist/taoyao/signal/protocol/ShutdownProtocolTest.java b/taoyao-server/src/test/java/com/acgist/taoyao/signal/protocol/ShutdownProtocolTest.java index a300ab6..1a17b53 100644 --- a/taoyao-server/src/test/java/com/acgist/taoyao/signal/protocol/ShutdownProtocolTest.java +++ b/taoyao-server/src/test/java/com/acgist/taoyao/signal/protocol/ShutdownProtocolTest.java @@ -5,9 +5,9 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import com.acgist.taoyao.annotation.TaoyaoTest; import com.acgist.taoyao.main.TaoyaoApplication; import com.acgist.taoyao.signal.protocol.platform.ShutdownProtocol; -import com.acgist.taoyao.test.annotation.TaoyaoTest; @TaoyaoTest(classes = TaoyaoApplication.class) class ShutdownProtocolTest { diff --git a/taoyao-signal/README.md b/taoyao-signal/README.md index c3ab2dd..40dac94 100644 --- a/taoyao-signal/README.md +++ b/taoyao-signal/README.md @@ -395,15 +395,15 @@ Moon模式有效 ### Offer信令(5997) -Offer +WebRTC信令:`Offer` ### Answer信令(5998) -Answer +WebRTC信令:`Answer` ### 候选信令(5999) -IceCandidate +WebRTC信令:`IceCandidate`主要用来解决`NAT`问题 ## 测试 diff --git a/taoyao-test/pom.xml b/taoyao-test/pom.xml deleted file mode 100644 index ada4e9e..0000000 --- a/taoyao-test/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - 4.0.0 - - - com.acgist - taoyao - 1.0.0 - - - taoyao-test - jar - - taoyao-test - 测试:测试工具 - - - - org.springframework.boot - spring-boot-starter-test - true - - - - \ No newline at end of file diff --git a/taoyao-webrtc/README.md b/taoyao-webrtc/README.md index 64aaeef..f7f5598 100644 --- a/taoyao-webrtc/README.md +++ b/taoyao-webrtc/README.md @@ -4,15 +4,15 @@ ``` +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| HTTPS / WSS | | SCTP | SRTP / SRTCP | +| HTTPS / WSS | | SCTP | SRTP / SRTCP | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ICE / SDP / SIP +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| TLS | | DTLS | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-++ -| HTTP / WS | STUN / TURN | | RTP / RTCP | +| TLS | | | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ DTLS +-+-+-+-+-+-+-+-+-+ +| HTTP / WS | NAT / STUN / TURN | | RTP / RTCP | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| TCP | UDP | +| TCP | UDP | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| IPv4 / IPv6 | +| IPv4 / IPv6 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ```