[+] 音频监控

This commit is contained in:
acgist
2023-03-05 11:56:31 +08:00
parent 3bc39b4d48
commit c49c3b19d8
15 changed files with 527 additions and 332 deletions

View File

@@ -0,0 +1,30 @@
package com.acgist.taoyao.signal.event;
import com.acgist.taoyao.signal.client.Client;
import com.acgist.taoyao.signal.party.media.Room;
import lombok.Getter;
import lombok.Setter;
/**
* 房间终端列表事件
*
* @author acgist
*/
@Getter
@Setter
public class RoomClientListEvent extends RoomEventAdapter {
private static final long serialVersionUID = 1L;
/**
* 终端
*/
private final Client client;
public RoomClientListEvent(Room room, Client client) {
super(room);
this.client = client;
}
}

View File

@@ -76,7 +76,13 @@ public class ClientWrapper implements AutoCloseable {
* 没有订阅任何媒体时需要用户自己对媒体进行消费控制
*/
private SubscribeType subscribeType;
/**
* RTP协商
*/
private Object rtpCapabilities;
/**
* SCTP协商
*/
private Object sctpCapabilities;
/**
* 发送通道

View File

@@ -78,6 +78,7 @@ public class Room implements Closeable {
if(clientWrapper != null) {
return clientWrapper;
}
log.info("终端进入房间:{} - {}", this.roomId, client.clientId());
clientWrapper = new ClientWrapper(this, client);
this.clients.put(client, clientWrapper);
this.roomStatus.setClientSize(this.roomStatus.getClientSize() + 1);

View File

@@ -2,6 +2,7 @@ package com.acgist.taoyao.signal.protocol.media;
import java.util.Map;
import com.acgist.taoyao.boot.annotation.Description;
import com.acgist.taoyao.boot.annotation.Protocol;
import com.acgist.taoyao.boot.model.Message;
import com.acgist.taoyao.signal.client.Client;
@@ -15,6 +16,15 @@ import com.acgist.taoyao.signal.protocol.ProtocolRoomAdapter;
* @author acgist
*/
@Protocol
@Description(
body = """
{
"volume": 音量,
"clientId": "终端ID"
}
""",
flow = "媒体服务->信令服务->终端"
)
public class MediaAudioActiveSpeakerProtocol extends ProtocolRoomAdapter {
public static final String SIGNAL = "media::audio::active::speaker";
@@ -28,7 +38,7 @@ public class MediaAudioActiveSpeakerProtocol extends ProtocolRoomAdapter {
if(clientType == ClientType.MEDIA) {
room.broadcast(message);
} else {
// 忽略其他情况
this.logNoAdapter(clientType);
}
}

View File

@@ -11,7 +11,7 @@ import com.acgist.taoyao.signal.party.media.Room;
import com.acgist.taoyao.signal.protocol.ProtocolRoomAdapter;
/**
* 路由RTP能力信令
* 路由RTP协商信令
*
* @author acgist
*/
@@ -37,7 +37,7 @@ public class MediaRouterRtpCapabilitiesProtocol extends ProtocolRoomAdapter {
public static final String SIGNAL = "media::router::rtp::capabilities";
public MediaRouterRtpCapabilitiesProtocol() {
super("路由RTP能力信令", SIGNAL);
super("路由RTP协商信令", SIGNAL);
}
@Override
@@ -45,7 +45,7 @@ public class MediaRouterRtpCapabilitiesProtocol extends ProtocolRoomAdapter {
if(clientType == ClientType.WEB || clientType == ClientType.CAMERA) {
client.push(room.request(message));
} else {
// 忽略其他情况
this.logNoAdapter(clientType);
}
}

View File

@@ -2,11 +2,15 @@ package com.acgist.taoyao.signal.protocol.room;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import com.acgist.taoyao.boot.annotation.Description;
import com.acgist.taoyao.boot.annotation.Protocol;
import com.acgist.taoyao.boot.model.Message;
import com.acgist.taoyao.signal.client.Client;
import com.acgist.taoyao.signal.client.ClientType;
import com.acgist.taoyao.signal.event.RoomClientListEvent;
import com.acgist.taoyao.signal.party.media.Room;
import com.acgist.taoyao.signal.protocol.ProtocolRoomAdapter;
@@ -49,13 +53,21 @@ import com.acgist.taoyao.signal.protocol.ProtocolRoomAdapter;
},
flow = "终端=>信令服务->终端"
)
public class RoomClientListProtocol extends ProtocolRoomAdapter {
public class RoomClientListProtocol extends ProtocolRoomAdapter implements ApplicationListener<RoomClientListEvent> {
public static final String SIGNAL = "room::client::list";
public RoomClientListProtocol() {
super("房间终端列表信令", SIGNAL);
}
@Async
@Override
public void onApplicationEvent(RoomClientListEvent event) {
final Room room = event.getRoom();
final Client client = event.getClient();
client.push(this.build(room.clientStatus()));
}
@Override
public void execute(String clientId, ClientType clientType, Room room, Client client, Client mediaClient, Message message, Map<String, Object> body) {

View File

@@ -13,25 +13,24 @@ import com.acgist.taoyao.boot.model.MessageCodeException;
import com.acgist.taoyao.boot.utils.MapUtils;
import com.acgist.taoyao.signal.client.Client;
import com.acgist.taoyao.signal.client.ClientType;
import com.acgist.taoyao.signal.event.RoomClientListEvent;
import com.acgist.taoyao.signal.party.media.ClientWrapper;
import com.acgist.taoyao.signal.party.media.ClientWrapper.SubscribeType;
import com.acgist.taoyao.signal.party.media.Room;
import com.acgist.taoyao.signal.protocol.ProtocolRoomAdapter;
import lombok.extern.slf4j.Slf4j;
/**
* 进入房间信令
*
* @author acgist
*/
@Slf4j
@Protocol
@Description(
body = {
"""
{
"roomId": "房间标识"
"roomId": "房间ID",
"password": "房间密码(选填)"
}
""",
"""
@@ -47,39 +46,52 @@ public class RoomEnterProtocol extends ProtocolRoomAdapter {
public static final String SIGNAL = "room::enter";
private final RoomClientListProtocol roomClientListProtocol;
public RoomEnterProtocol(RoomClientListProtocol roomClientListProtocol) {
public RoomEnterProtocol() {
super("进入房间信令", SIGNAL);
this.roomClientListProtocol = roomClientListProtocol;
}
@Override
public void execute(String clientId, ClientType clientType, Room room, Client client, Client mediaClient, Message message, Map<String, Object> body) {
if(clientType == ClientType.WEB || clientType == ClientType.CAMERA) {
this.enter(clientId, room, client, message, body);
} else {
this.logNoAdapter(clientType);
}
}
/**
* 终端进入
*
* @param clientId 终端ID
* @param room 房间
* @param client 终端
* @param message 消息
* @param body 消息主体
*/
private void enter(String clientId, Room room, Client client, Message message, Map<String, Object> body) {
final String password = MapUtils.get(body, Constant.PASSWORD);
final String subscribeType = MapUtils.get(body, Constant.SUBSCRIBE_TYPE);
final Object rtpCapabilities = MapUtils.get(body, Constant.RTP_CAPABILITIES);
final Object sctpCapabilities = MapUtils.get(body, Constant.SCTP_CAPABILITIES);
final String roomPassowrd = room.getPassword();
if(StringUtils.isNotEmpty(roomPassowrd) && !roomPassowrd.equals(password)) {
throw MessageCodeException.of(MessageCode.CODE_3401, "密码错误");
}
final String subscribeType = MapUtils.get(body, Constant.SUBSCRIBE_TYPE);
final Object rtpCapabilities = MapUtils.get(body, Constant.RTP_CAPABILITIES);
final Object sctpCapabilities = MapUtils.get(body, Constant.SCTP_CAPABILITIES);
// 进入房间
final ClientWrapper clientWrapper = room.enter(client);
// 配置参数
clientWrapper.setSubscribeType(SubscribeType.of(subscribeType));
clientWrapper.setRtpCapabilities(rtpCapabilities);
clientWrapper.setSctpCapabilities(sctpCapabilities);
// 发送通知
message.setBody(Map.of(
Constant.ROOM_ID, room.getRoomId(),
Constant.CLIENT_ID, clientId
Constant.CLIENT_ID, clientId,
Constant.STATUS, client.status()
));
room.broadcast(message);
log.info("进入房间:{} - {}", clientId, room.getRoomId());
// 推送房间用户信息TODO event
final Message roomClientListMessage = this.roomClientListProtocol.build();
roomClientListMessage.setBody(room.clientStatus());
client.push(roomClientListMessage);
}
// 房间终端列表事件
this.publishEvent(new RoomClientListEvent(room, client));
}
}