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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```