[*] 删除房间
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# 桃夭
|
# 桃夭
|
||||||
|
|
||||||
桃夭是套`WebRTC`信令服务,使用`Mediasoup`提供媒体服务,支持直播会议两种场景。
|
桃夭是套基于`Mediasoup`开发的`WebRTC`音视频信令服务
|
||||||
|
|
||||||
## 模块
|
## 模块
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|:--|:--|:--|
|
|:--|:--|:--|
|
||||||
|taoyao-client|终端示例|Web端终端示例|
|
|taoyao-client|终端示例|Web端终端示例|
|
||||||
|taoyao-media-server|媒体服务|Mediasoup媒体服务|
|
|taoyao-media-server|媒体服务|Mediasoup媒体服务|
|
||||||
|taoyao-signal-server|信令服务|直播会议业务逻辑|
|
|taoyao-signal-server|信令服务|信令业务逻辑|
|
||||||
|
|
||||||
## 部署
|
## 部署
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
* 录制(Recorder)
|
* 录制(Recorder)
|
||||||
* 音频:降噪、混音、变声
|
* 音频:降噪、混音、变声
|
||||||
* 视频:水印、美颜、AI识别
|
* 视频:水印、美颜、AI识别
|
||||||
* 一个信令服务多个媒体服务
|
|
||||||
* 信令服务集群
|
|
||||||
* 信令直传
|
* 信令直传
|
||||||
|
* 信令服务集群
|
||||||
* 媒体交互式启动
|
* 媒体交互式启动
|
||||||
|
* 一个信令服务多个媒体服务
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Signal -> ClientA: 关闭ClientA通道
|
|||||||
deactivate ClientA
|
deactivate ClientA
|
||||||
Signal -> ClientB: ClientA下线
|
Signal -> ClientB: ClientA下线
|
||||||
Signal -> ClientC: ClientA下线
|
Signal -> ClientC: ClientA下线
|
||||||
Signal -> Signal: 释放ClientA资源(直播、会议、媒体)
|
Signal -> Signal: 释放ClientA资源(会议、媒体)
|
||||||
deactivate Signal
|
deactivate Signal
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -1,34 +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
|
|
||||||
@@ -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
|
|
||||||
@@ -21,9 +21,6 @@ input[type=text]:focus,textarea:focus,input[type=text]:hover,textarea:hover{bord
|
|||||||
input::-webkit-calendar-picker-indicator{color:#1155AA;background:none;}
|
input::-webkit-calendar-picker-indicator{color:#1155AA;background:none;}
|
||||||
/**容器*/
|
/**容器*/
|
||||||
.taoyao{text-align:center;}
|
.taoyao{text-align:center;}
|
||||||
/**直播*/
|
|
||||||
.taoyao .live > .video{width:100%;height:100%;}
|
|
||||||
.taoyao .live .handler{position:fixed;width:100%;bottom:2rem;font-size:2rem;}
|
|
||||||
/**会议*/
|
/**会议*/
|
||||||
.taoyao .handler a{cursor:pointer;}
|
.taoyao .handler a{cursor:pointer;}
|
||||||
.taoyao > .handler{font-size:2rem;padding:1rem 0;width:100%;}
|
.taoyao > .handler{font-size:2rem;padding:1rem 0;width:100%;}
|
||||||
|
|||||||
@@ -2,17 +2,127 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>桃夭</title>
|
<title>会议</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="./css/font.min.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="./css/style.css" />
|
<link rel="stylesheet" type="text/css" href="./css/style.css" />
|
||||||
|
<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
|
||||||
<script type="text/javascript" src="./javascript/taoyao.js"></script>
|
<script type="text/javascript" src="./javascript/taoyao.js"></script>
|
||||||
<style type="text/css">
|
|
||||||
a{width:50%;height:100%;position:fixed;text-align:center;line-height:100%;font-size:4rem;display:flex;align-items:center;justify-content:center;}
|
|
||||||
a:last-child{left:50%;}
|
|
||||||
a:hover{color:#fff;background:#060;}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a href="./live.html">直播</a>
|
<div class="taoyao" id="app">
|
||||||
<a href="./meeting.html">会议</a>
|
<div class="handler">
|
||||||
|
<a class="create icon-make-group" title="创建会议" @click="create"></a>
|
||||||
|
<a class="invite icon-address-book" title="邀请会议" @click="invite"></a>
|
||||||
|
<a class="enter icon-enter" title="进入会议" @click="enter"></a>
|
||||||
|
<a class="leave icon-exit" title="离开会议" @click="leave"></a>
|
||||||
|
<a class="close icon-switch" title="关闭会议" @click="close"></a>
|
||||||
|
</div>
|
||||||
|
<div class="list">
|
||||||
|
<div class="meeting me">
|
||||||
|
<div class="video">
|
||||||
|
<video id="local"></video>
|
||||||
|
</div>
|
||||||
|
<div class="handler">
|
||||||
|
<a class="audio icon-volume-medium" title="音频状态" @click="audioSelf"></a>
|
||||||
|
<a class="video icon-play2" title="视频状态" @click="videoSelf"></a>
|
||||||
|
<a class="record icon-radio-checked" title="录制视频" @click="recordSelf"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="meeting" v-for="client in this.remoteClient" :key="client.sn">
|
||||||
|
<div class="video">
|
||||||
|
<video v-bind:id="client.sn"></video>
|
||||||
|
</div>
|
||||||
|
<div class="handler">
|
||||||
|
<a class="audio" title="音频状态" v-bind:class="client.audioStatus?'icon-volume-medium':'icon-volume-mute2'" @click="audio(client.sn)"></a>
|
||||||
|
<a class="video" title="视频状态" v-bind:class="client.videoStatus?'icon-play2':'icon-stop'" @click="video(client.sn)"></a>
|
||||||
|
<a class="record icon-radio-checked" title="录制视频" v-bind:class="client.recordStatus?'active':''" @click="record(client.sn)"></a>
|
||||||
|
<a class="expel icon-cancel-circle" title="踢出会议" @click="expel(client.sn)"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
const vue = new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data: {
|
||||||
|
taoyao: null,
|
||||||
|
remoteClient: [],
|
||||||
|
meetingId: null
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 设置帐号
|
||||||
|
let sn = prompt('你的账号', signalConfig.sn);
|
||||||
|
signalConfig.sn = sn;
|
||||||
|
// 加载桃夭
|
||||||
|
let self = this;
|
||||||
|
this.taoyao = new Taoyao('local');
|
||||||
|
this.remoteClient = this.taoyao.remoteClient;
|
||||||
|
// 打开信令通道
|
||||||
|
this.taoyao
|
||||||
|
.buildChannel(self.callback)
|
||||||
|
.then(e => console.debug('信令通道连接成功'));
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 信令回调:true表示已经处理;false表示没有处理;
|
||||||
|
callback: function(data) {
|
||||||
|
let self = this;
|
||||||
|
switch(data.header.pid) {
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
// 创建会议
|
||||||
|
create: function(event) {
|
||||||
|
let self = this;
|
||||||
|
this.taoyao.meetingCreate(data => {
|
||||||
|
self.taoyao.meetingEnter(data.body.id);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 会议邀请
|
||||||
|
invite: function(sn) {
|
||||||
|
},
|
||||||
|
// 进入会议
|
||||||
|
enter: function(sn) {
|
||||||
|
let id = prompt('房间标识');
|
||||||
|
let password = prompt('房间密码');
|
||||||
|
if(id) {
|
||||||
|
this.taoyao.meetingEnter(id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 离开会议
|
||||||
|
leave: function(sn) {
|
||||||
|
},
|
||||||
|
// 关闭会议
|
||||||
|
close: function(sn) {
|
||||||
|
},
|
||||||
|
// 控制音频
|
||||||
|
audio: function(sn) {
|
||||||
|
this.client(sn).audio = !this.client(sn).audio;
|
||||||
|
},
|
||||||
|
// 控制视频
|
||||||
|
video: function(sn) {
|
||||||
|
this.client(sn).video = !this.client(sn).video;
|
||||||
|
},
|
||||||
|
// 录制视频
|
||||||
|
record: function(sn) {
|
||||||
|
this.client(sn).record = !this.client(sn).record;
|
||||||
|
},
|
||||||
|
// 踢出会议
|
||||||
|
expel: function(sn) {
|
||||||
|
},
|
||||||
|
// 控制音频
|
||||||
|
audioSelf: function(sn) {
|
||||||
|
},
|
||||||
|
// 控制视频
|
||||||
|
videoSelf: function(sn) {
|
||||||
|
},
|
||||||
|
// 录制视频
|
||||||
|
recordSelf: function(sn) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -69,9 +69,6 @@ const signalConfig = {
|
|||||||
};
|
};
|
||||||
/** 信令协议 */
|
/** 信令协议 */
|
||||||
const signalProtocol = {
|
const signalProtocol = {
|
||||||
/** 直播信令 */
|
|
||||||
live: {
|
|
||||||
},
|
|
||||||
/** 媒体信令 */
|
/** 媒体信令 */
|
||||||
media: {
|
media: {
|
||||||
/** 发布 */
|
/** 发布 */
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>直播</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./css/font.min.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="./css/style.css" />
|
|
||||||
<script type="text/javascript" src="./javascript/taoyao.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="taoyao" id="taoyao">
|
|
||||||
<div class="live">
|
|
||||||
<div class="video">
|
|
||||||
</div>
|
|
||||||
<div class="handler">
|
|
||||||
<a class="audio icon-volume-medium" title="音频状态"></a>
|
|
||||||
<a class="video icon-play2" title="视频状态"></a>
|
|
||||||
<a class="record icon-radio-checked" title="录制视频"></a>
|
|
||||||
<a class="kick icon-cancel-circle" title="退出直播"></a>
|
|
||||||
<a class="close icon-switch" title="关闭直播"></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">
|
|
||||||
const live = document.getElementById('taoyao');
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>会议</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./css/font.min.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="./css/style.css" />
|
|
||||||
<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
|
|
||||||
<script type="text/javascript" src="./javascript/taoyao.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="taoyao" id="app">
|
|
||||||
<div class="handler">
|
|
||||||
<a class="create icon-make-group" title="创建会议" @click="create"></a>
|
|
||||||
<a class="invite icon-address-book" title="邀请会议" @click="invite"></a>
|
|
||||||
<a class="enter icon-enter" title="进入会议" @click="enter"></a>
|
|
||||||
<a class="leave icon-exit" title="离开会议" @click="leave"></a>
|
|
||||||
<a class="close icon-switch" title="关闭会议" @click="close"></a>
|
|
||||||
</div>
|
|
||||||
<div class="list">
|
|
||||||
<div class="meeting me">
|
|
||||||
<div class="video">
|
|
||||||
<video id="local"></video>
|
|
||||||
</div>
|
|
||||||
<div class="handler">
|
|
||||||
<a class="audio icon-volume-medium" title="音频状态" @click="audioSelf"></a>
|
|
||||||
<a class="video icon-play2" title="视频状态" @click="videoSelf"></a>
|
|
||||||
<a class="record icon-radio-checked" title="录制视频" @click="recordSelf"></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="meeting" v-for="client in this.remoteClient" :key="client.sn">
|
|
||||||
<div class="video">
|
|
||||||
<video v-bind:id="client.sn"></video>
|
|
||||||
</div>
|
|
||||||
<div class="handler">
|
|
||||||
<a class="audio" title="音频状态" v-bind:class="client.audioStatus?'icon-volume-medium':'icon-volume-mute2'" @click="audio(client.sn)"></a>
|
|
||||||
<a class="video" title="视频状态" v-bind:class="client.videoStatus?'icon-play2':'icon-stop'" @click="video(client.sn)"></a>
|
|
||||||
<a class="record icon-radio-checked" title="录制视频" v-bind:class="client.recordStatus?'active':''" @click="record(client.sn)"></a>
|
|
||||||
<a class="expel icon-cancel-circle" title="踢出会议" @click="expel(client.sn)"></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">
|
|
||||||
const vue = new Vue({
|
|
||||||
el: "#app",
|
|
||||||
data: {
|
|
||||||
taoyao: null,
|
|
||||||
remoteClient: [],
|
|
||||||
meetingId: null
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
// 设置帐号
|
|
||||||
let sn = prompt('你的账号', signalConfig.sn);
|
|
||||||
signalConfig.sn = sn;
|
|
||||||
// 加载桃夭
|
|
||||||
let self = this;
|
|
||||||
this.taoyao = new Taoyao('local');
|
|
||||||
this.remoteClient = this.taoyao.remoteClient;
|
|
||||||
// 打开信令通道
|
|
||||||
this.taoyao
|
|
||||||
.buildChannel(self.callback)
|
|
||||||
.then(e => console.debug('信令通道连接成功'));
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 信令回调:true表示已经处理;false表示没有处理;
|
|
||||||
callback: function(data) {
|
|
||||||
let self = this;
|
|
||||||
switch(data.header.pid) {
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
// 创建会议
|
|
||||||
create: function(event) {
|
|
||||||
let self = this;
|
|
||||||
this.taoyao.meetingCreate(data => {
|
|
||||||
self.taoyao.meetingEnter(data.body.id);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 会议邀请
|
|
||||||
invite: function(sn) {
|
|
||||||
},
|
|
||||||
// 进入会议
|
|
||||||
enter: function(sn) {
|
|
||||||
let id = prompt('房间标识');
|
|
||||||
let password = prompt('房间密码');
|
|
||||||
if(id) {
|
|
||||||
this.taoyao.meetingEnter(id);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 离开会议
|
|
||||||
leave: function(sn) {
|
|
||||||
},
|
|
||||||
// 关闭会议
|
|
||||||
close: function(sn) {
|
|
||||||
},
|
|
||||||
// 控制音频
|
|
||||||
audio: function(sn) {
|
|
||||||
this.client(sn).audio = !this.client(sn).audio;
|
|
||||||
},
|
|
||||||
// 控制视频
|
|
||||||
video: function(sn) {
|
|
||||||
this.client(sn).video = !this.client(sn).video;
|
|
||||||
},
|
|
||||||
// 录制视频
|
|
||||||
record: function(sn) {
|
|
||||||
this.client(sn).record = !this.client(sn).record;
|
|
||||||
},
|
|
||||||
// 踢出会议
|
|
||||||
expel: function(sn) {
|
|
||||||
},
|
|
||||||
// 控制音频
|
|
||||||
audioSelf: function(sn) {
|
|
||||||
},
|
|
||||||
// 控制视频
|
|
||||||
videoSelf: function(sn) {
|
|
||||||
},
|
|
||||||
// 录制视频
|
|
||||||
recordSelf: function(sn) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -11,13 +11,21 @@
|
|||||||
|taoyao-signal|信令|信令服务|
|
|taoyao-signal|信令|信令服务|
|
||||||
|taoyao-server|服务|启动服务|
|
|taoyao-server|服务|启动服务|
|
||||||
|
|
||||||
### 直播
|
### 会议模式
|
||||||
|
|
||||||
直播、连麦、监控、视频同看
|
所有人员均能视频通话对讲
|
||||||
|
|
||||||
### 会议
|
### 对讲模式
|
||||||
|
|
||||||
会议模式、广播模式、单人对讲
|
两个人员之间对讲
|
||||||
|
|
||||||
|
### 广播模式
|
||||||
|
|
||||||
|
单个人员能够讲话并且能够听到其他人员讲话,其他人员之间不能讲话。
|
||||||
|
|
||||||
|
### 本地视频模式
|
||||||
|
|
||||||
|
使用本地文件作为音频视频信息
|
||||||
|
|
||||||
## 模块关系
|
## 模块关系
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<url>https://gitee.com/acgist/taoyao</url>
|
<url>https://gitee.com/acgist/taoyao</url>
|
||||||
<name>taoyao</name>
|
<name>taoyao</name>
|
||||||
<description>桃夭:桃夭是套`WebRTC`信令服务,使用`Mediasoup`提供媒体服务,支持直播会议两种场景。</description>
|
<description>桃夭:桃夭是套基于`Mediasoup`开发的`WebRTC`音视频信令服务</description>
|
||||||
<inceptionYear>2022</inceptionYear>
|
<inceptionYear>2022</inceptionYear>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -36,16 +36,7 @@ public class SpringDocAutoConfiguration {
|
|||||||
private Integer port;
|
private Integer port;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TaoyaoProperties taoyaoProperties;
|
private TaoyaoProperties taoyaoProperties;
|
||||||
|
|
||||||
@Bean
|
|
||||||
public GroupedOpenApi liveApi() {
|
|
||||||
return GroupedOpenApi.builder()
|
|
||||||
.group("live")
|
|
||||||
.displayName("直播")
|
|
||||||
.packagesToScan("com.acgist.taoyao.live")
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public GroupedOpenApi meetingApi() {
|
public GroupedOpenApi meetingApi() {
|
||||||
return GroupedOpenApi.builder()
|
return GroupedOpenApi.builder()
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
package com.acgist.taoyao.media.live;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 直播
|
|
||||||
*
|
|
||||||
* @author acgist
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Schema(title = "直播", description = "直播")
|
|
||||||
public class Live {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 直播标识
|
|
||||||
*/
|
|
||||||
@Schema(title = "直播标识", description = "直播标识")
|
|
||||||
private String id;
|
|
||||||
/**
|
|
||||||
* 直播名称
|
|
||||||
*/
|
|
||||||
@Schema(title = "直播名称", description = "直播名称")
|
|
||||||
private String name;
|
|
||||||
/**
|
|
||||||
* 直播密码
|
|
||||||
*/
|
|
||||||
@Schema(title = "直播密码", description = "直播密码")
|
|
||||||
private String password;
|
|
||||||
/**
|
|
||||||
* 终端会话标识列表
|
|
||||||
*/
|
|
||||||
@Schema(title = "终端会话标识列表", description = "终端会话标识列表")
|
|
||||||
private List<String> sns;
|
|
||||||
/**
|
|
||||||
* 创建终端标识
|
|
||||||
*/
|
|
||||||
@Schema(title = "创建终端标识", description = "创建终端标识")
|
|
||||||
private String creator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增终端会话标识
|
|
||||||
*
|
|
||||||
* @param sn 终端会话标识
|
|
||||||
*/
|
|
||||||
public void addSn(String sn) {
|
|
||||||
synchronized (this.sns) {
|
|
||||||
if(this.sns.contains(sn)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.sns.add(sn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.acgist.taoyao.media.live;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
import com.acgist.taoyao.signal.event.ApplicationEventAdapter;
|
|
||||||
import com.acgist.taoyao.signal.listener.ApplicationListenerAdapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 直播事件监听适配器
|
|
||||||
*
|
|
||||||
* @param <E> 事件泛型
|
|
||||||
*
|
|
||||||
* @author acgist
|
|
||||||
*/
|
|
||||||
public abstract class LiveListenerAdapter<E extends ApplicationEventAdapter> extends ApplicationListenerAdapter<E> {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected LiveManager liveManager;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.acgist.taoyao.media.live;
|
|
||||||
|
|
||||||
import com.acgist.taoyao.boot.annotation.Manager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 直播管理
|
|
||||||
*
|
|
||||||
* @author acgist
|
|
||||||
*/
|
|
||||||
@Manager
|
|
||||||
public class LiveManager {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package com.acgist.taoyao.media.live.controller;
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import com.acgist.taoyao.boot.model.Message;
|
|
||||||
import com.acgist.taoyao.media.live.Live;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 直播
|
|
||||||
*
|
|
||||||
* @author acgist
|
|
||||||
*/
|
|
||||||
@Tag(name = "直播", description = "直播管理")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/live")
|
|
||||||
public class LiveController {
|
|
||||||
|
|
||||||
@Operation(summary = "直播列表", description = "直播列表")
|
|
||||||
@GetMapping("/list")
|
|
||||||
@ApiResponse(content = @Content(schema = @Schema(implementation = Live.class)))
|
|
||||||
public Message list() {
|
|
||||||
return Message.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "直播状态", description = "直播状态")
|
|
||||||
@GetMapping("/status/{id}")
|
|
||||||
public Message status(@PathVariable String id) {
|
|
||||||
return Message.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operation(summary = "直播终端列表", description = "直播终端列表")
|
|
||||||
@GetMapping("/list/client")
|
|
||||||
public Message listClient() {
|
|
||||||
return Message.success();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -281,20 +281,6 @@
|
|||||||
|
|
||||||
响应所有终端状态列表
|
响应所有终端状态列表
|
||||||
|
|
||||||
## 直播信令(3000~3999)
|
|
||||||
|
|
||||||
### 开启直播信令(3000)
|
|
||||||
|
|
||||||
### 关闭直播信令(3001)
|
|
||||||
|
|
||||||
### 直播广播信令(3002)
|
|
||||||
|
|
||||||
### 直播终端列表信令(3997)
|
|
||||||
|
|
||||||
### 直播状态信令(3998)
|
|
||||||
|
|
||||||
### 直播列表信令(3999)
|
|
||||||
|
|
||||||
## 会议信令(4000~4999)
|
## 会议信令(4000~4999)
|
||||||
|
|
||||||
### 创建会议信令(4000)
|
### 创建会议信令(4000)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import com.acgist.taoyao.signal.protocol.client.ClientOnlineProtocol;
|
|||||||
/**
|
/**
|
||||||
* 终端注册监听
|
* 终端注册监听
|
||||||
*
|
*
|
||||||
* TODO:如果已经在会议、直播中,自动推流。
|
* TODO:如果已经在会议中,自动推流。
|
||||||
*
|
*
|
||||||
* @author acgist
|
* @author acgist
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ import com.acgist.taoyao.signal.event.ApplicationEventAdapter;
|
|||||||
/**
|
/**
|
||||||
* 信令
|
* 信令
|
||||||
*
|
*
|
||||||
|
* TODO:改为字符
|
||||||
|
*
|
||||||
* 1000~1999:平台信令
|
* 1000~1999:平台信令
|
||||||
* 2000~2999:终端信令
|
* 2000~2999:终端信令
|
||||||
* 3000~3999:会议信令
|
* 3000~3999:会议信令
|
||||||
* 4000~4999:直播信令
|
|
||||||
* 5000~5999:媒体信令
|
* 5000~5999:媒体信令
|
||||||
* 6000~6999:媒体信令(Mediasoup)
|
* 6000~6999:媒体信令(Mediasoup)
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
package com.acgist.taoyao.signal.protocol.live;
|
|
||||||
|
|
||||||
public class LiveClientListProtocol {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package com.acgist.taoyao.signal.protocol.live;
|
|
||||||
|
|
||||||
public class LiveCloseProtocol {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package com.acgist.taoyao.signal.protocol.live;
|
|
||||||
|
|
||||||
public class LiveListProtocol {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package com.acgist.taoyao.signal.protocol.live;
|
|
||||||
|
|
||||||
public class LiveRegisterProtocol {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package com.acgist.taoyao.signal.protocol.live;
|
|
||||||
|
|
||||||
public class LiveStatusProtocol {
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user