[*] 日常优化
This commit is contained in:
@@ -1032,7 +1032,7 @@ public final class Taoyao implements ITaoyao {
|
||||
roomId,
|
||||
key -> new Room(
|
||||
roomId, this.name,
|
||||
this.clientId, password,
|
||||
password, this.clientId,
|
||||
this, this.mainHandler,
|
||||
resources.getBoolean(R.bool.preview),
|
||||
resources.getBoolean(R.bool.playAudio),
|
||||
@@ -1043,6 +1043,7 @@ public final class Taoyao implements ITaoyao {
|
||||
resources.getBoolean(R.bool.dataProduce),
|
||||
resources.getBoolean(R.bool.audioProduce),
|
||||
resources.getBoolean(R.bool.videoProduce),
|
||||
resources.getBoolean(R.bool.roomUseIceServer),
|
||||
this.mediaManager.getMediaProperties(),
|
||||
this.mediaManager.getWebrtcProperties()
|
||||
)
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
<integer name="channelCount">1</integer>
|
||||
<!-- 视频关键帧频率 -->
|
||||
<integer name="iFrameInterval">1</integer>
|
||||
<!-- 视频房间是否使用iceServer -->
|
||||
<bool name="roomUseIceServer">false</bool>
|
||||
<!-- 图片存储目录 -->
|
||||
<string name="imagePath">/taoyao</string>
|
||||
<!-- 视频存储目录 -->
|
||||
|
||||
@@ -33,64 +33,139 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class Room extends CloseableClient implements RouterCallback {
|
||||
|
||||
private final String name;
|
||||
/**
|
||||
* 房间ID
|
||||
*/
|
||||
private final String roomId;
|
||||
private final String clientId;
|
||||
/**
|
||||
* 房间名称
|
||||
*/
|
||||
private final String name;
|
||||
/**
|
||||
* 房间密码
|
||||
*/
|
||||
private final String password;
|
||||
/**
|
||||
* 当前终端ID
|
||||
*/
|
||||
private final String clientId;
|
||||
/**
|
||||
* 是否预览
|
||||
*/
|
||||
private final boolean preview;
|
||||
/**
|
||||
* 是否播放音频
|
||||
*/
|
||||
private final boolean playAudio;
|
||||
/**
|
||||
* 是否播放视频
|
||||
*/
|
||||
private final boolean playVideo;
|
||||
/**
|
||||
* 是否消费数据
|
||||
*/
|
||||
private final boolean dataConsume;
|
||||
/**
|
||||
* 是否消费音频
|
||||
*/
|
||||
private final boolean audioConsume;
|
||||
/**
|
||||
* 是否消费视频
|
||||
*/
|
||||
private final boolean videoConsume;
|
||||
/**
|
||||
* 是否生产数据
|
||||
*/
|
||||
private final boolean dataProduce;
|
||||
/**
|
||||
* 是否生产音频
|
||||
*/
|
||||
private final boolean audioProduce;
|
||||
/**
|
||||
* 是否生产视频
|
||||
*/
|
||||
private final boolean videoProduce;
|
||||
/**
|
||||
* 是否使用IceServer
|
||||
*/
|
||||
private final boolean useIceServer;
|
||||
/**
|
||||
* 是否已经开始生产
|
||||
*/
|
||||
private boolean produce;
|
||||
/**
|
||||
* 媒体配置
|
||||
*/
|
||||
private final MediaProperties mediaProperties;
|
||||
/**
|
||||
* WebRTC配置
|
||||
*/
|
||||
private final WebrtcProperties webrtcProperties;
|
||||
private final Map<String, RemoteClient> remoteClients;
|
||||
/**
|
||||
* 房间指针
|
||||
*/
|
||||
private final long nativeRoomPointer;
|
||||
/**
|
||||
* 本地终端
|
||||
*/
|
||||
private LocalClient localClient;
|
||||
private PeerConnection.RTCConfiguration rtcConfiguration;
|
||||
private PeerConnectionFactory peerConnectionFactory;
|
||||
/**
|
||||
* 远程终端
|
||||
*/
|
||||
private final Map<String, RemoteClient> remoteClients;
|
||||
/**
|
||||
* RTC能力
|
||||
*/
|
||||
private Object rtpCapabilities;
|
||||
/**
|
||||
* SCTP能力
|
||||
*/
|
||||
private Object sctpCapabilities;
|
||||
/**
|
||||
* RTC配置
|
||||
*/
|
||||
private PeerConnection.RTCConfiguration rtcConfiguration;
|
||||
/**
|
||||
* PeerConnectionFactory
|
||||
*/
|
||||
private PeerConnectionFactory peerConnectionFactory;
|
||||
|
||||
/**
|
||||
* @param roomId 房间ID
|
||||
* @param name 终端名称
|
||||
* @param clientId 当前终端ID
|
||||
* @param password 房间密码
|
||||
* @param taoyao 信令
|
||||
* @param mainHandler MainHandler
|
||||
* @param preview 是否预览视频
|
||||
* @param playAudio 是否播放音频
|
||||
* @param playVideo 是否播放视频
|
||||
* @param dataConsume 是否消费数据
|
||||
* @param audioConsume 是否消费音频
|
||||
* @param videoConsume 是否消费视频
|
||||
* @param dataProduce 是否生产数据
|
||||
* @param audioProduce 是否生产音频
|
||||
* @param videoProduce 是否生产视频
|
||||
* @param roomId 房间ID
|
||||
* @param name 终端名称
|
||||
* @param clientId 当前终端ID
|
||||
* @param password 房间密码
|
||||
* @param taoyao 信令
|
||||
* @param mainHandler MainHandler
|
||||
* @param preview 是否预览视频
|
||||
* @param playAudio 是否播放音频
|
||||
* @param playVideo 是否播放视频
|
||||
* @param dataConsume 是否消费数据
|
||||
* @param audioConsume 是否消费音频
|
||||
* @param videoConsume 是否消费视频
|
||||
* @param dataProduce 是否生产数据
|
||||
* @param audioProduce 是否生产音频
|
||||
* @param videoProduce 是否生产视频
|
||||
* @param useIceServer 是否使用IceServer
|
||||
* @param mediaProperties 媒体配置
|
||||
* @param webrtcProperties WebRTC配置
|
||||
*/
|
||||
public Room(
|
||||
String roomId, String name,
|
||||
String clientId, String password,
|
||||
ITaoyao taoyao, Handler mainHandler,
|
||||
String roomId, String name,
|
||||
String password, String clientId,
|
||||
ITaoyao taoyao, Handler mainHandler,
|
||||
boolean preview, boolean playAudio, boolean playVideo,
|
||||
boolean dataConsume, boolean audioConsume, boolean videoConsume,
|
||||
boolean dataProduce, boolean audioProduce, boolean videoProduce,
|
||||
boolean useIceServer,
|
||||
MediaProperties mediaProperties, WebrtcProperties webrtcProperties
|
||||
) {
|
||||
super(taoyao, mainHandler);
|
||||
this.roomId = roomId;
|
||||
this.name = name;
|
||||
this.clientId = clientId;
|
||||
this.password = password;
|
||||
this.preview = preview;
|
||||
this.roomId = roomId;
|
||||
this.name = name;
|
||||
this.password = password;
|
||||
this.clientId = clientId;
|
||||
this.preview = preview;
|
||||
this.playAudio = playAudio;
|
||||
this.playVideo = playVideo;
|
||||
this.dataConsume = dataConsume;
|
||||
@@ -99,13 +174,17 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
this.dataProduce = dataProduce;
|
||||
this.audioProduce = audioProduce;
|
||||
this.videoProduce = videoProduce;
|
||||
this.useIceServer = useIceServer;
|
||||
this.produce = false;
|
||||
this.mediaProperties = mediaProperties;
|
||||
this.webrtcProperties = webrtcProperties;
|
||||
this.mediaProperties = mediaProperties;
|
||||
this.webrtcProperties = webrtcProperties;
|
||||
this.remoteClients = new ConcurrentHashMap<>();
|
||||
this.nativeRoomPointer = this.nativeNewRoom(roomId, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 是否成功进入房间
|
||||
*/
|
||||
public boolean enter() {
|
||||
synchronized (this) {
|
||||
if (this.init) {
|
||||
@@ -120,12 +199,18 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
this.localClient.playVideo();
|
||||
}
|
||||
// STUN | TURN
|
||||
final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
|
||||
// 不用配置
|
||||
// final List<PeerConnection.IceServer> iceServers = this.webrtcProperties.getIceServers();
|
||||
final List<PeerConnection.IceServer> iceServers;
|
||||
if(this.useIceServer) {
|
||||
// 不用配置:正常情况都是能够直接访问媒体服务
|
||||
iceServers = this.webrtcProperties.getIceServers();
|
||||
} else {
|
||||
iceServers = new ArrayList<>();
|
||||
}
|
||||
this.rtcConfiguration = new PeerConnection.RTCConfiguration(iceServers);
|
||||
// 开始协商
|
||||
return this.taoyao.requestFuture(
|
||||
this.taoyao.buildMessage("media::router::rtp::capabilities", "roomId", this.roomId),
|
||||
// 成功加载Mediasoup房间
|
||||
response -> {
|
||||
this.nativeEnterRoom(
|
||||
this.nativeRoomPointer,
|
||||
@@ -135,6 +220,7 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
);
|
||||
return true;
|
||||
},
|
||||
// 失败关闭资源
|
||||
response -> {
|
||||
this.close();
|
||||
return false;
|
||||
@@ -143,11 +229,16 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生产媒体
|
||||
*/
|
||||
public void mediaProduce() {
|
||||
if(this.produce) {
|
||||
return;
|
||||
synchronized(this) {
|
||||
if(this.produce) {
|
||||
return;
|
||||
}
|
||||
this.produce = true;
|
||||
}
|
||||
this.produce = true;
|
||||
if (this.audioProduce || this.videoProduce) {
|
||||
this.createSendTransport();
|
||||
}
|
||||
@@ -164,6 +255,9 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建发送媒体通道
|
||||
*/
|
||||
private void createSendTransport() {
|
||||
this.taoyao.requestFuture(
|
||||
this.taoyao.buildMessage(
|
||||
@@ -183,6 +277,9 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建接收媒体通道
|
||||
*/
|
||||
private void createRecvTransport() {
|
||||
this.taoyao.requestFuture(
|
||||
this.taoyao.buildMessage(
|
||||
@@ -202,6 +299,12 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 媒体消费
|
||||
*
|
||||
* @param message 信令消息
|
||||
* @param body 消息主体
|
||||
*/
|
||||
public void mediaConsume(Message message, Map<String, Object> body) {
|
||||
this.nativeMediaConsume(this.nativeRoomPointer, JSONUtils.toJSON(message));
|
||||
}
|
||||
@@ -213,41 +316,63 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
*/
|
||||
public void newRemoteClientFromRoomEnter(Map<String, Object> body) {
|
||||
final String clientId = MapUtils.get(body, "clientId");
|
||||
// 忽略自己
|
||||
if(this.clientId.equals(clientId)) {
|
||||
return;
|
||||
}
|
||||
final Map<String, Object> status = MapUtils.get(body, "status");
|
||||
final String name = MapUtils.get(status, "name");
|
||||
final RemoteClient remoteClient = new RemoteClient(name, clientId, this.taoyao, this.mainHandler);
|
||||
final RemoteClient old = this.remoteClients.put(clientId, remoteClient);
|
||||
if(old != null) {
|
||||
final Map<String, Object> status = MapUtils.get(body, "status");
|
||||
final String name = MapUtils.get(status, "name");
|
||||
final RemoteClient remoteClient = new RemoteClient(name, clientId, this.taoyao, this.mainHandler);
|
||||
final RemoteClient oldRemoteClient = this.remoteClients.put(clientId, remoteClient);
|
||||
if(oldRemoteClient != null) {
|
||||
// 关闭旧的资源
|
||||
old.close();
|
||||
this.closeRemoteClient(oldRemoteClient);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增远程终端
|
||||
*
|
||||
* @param body 消息主体
|
||||
*/
|
||||
public void newRemoteClientFromRoomClientList(Map<String, Object> body) {
|
||||
final List<Map<String, Object>> clients = MapUtils.get(body, "clients");
|
||||
if(CollectionUtils.isEmpty(clients)) {
|
||||
return;
|
||||
}
|
||||
clients.forEach(map -> {
|
||||
final String name = MapUtils.get(map, "name");
|
||||
final String name = MapUtils.get(map, "name");
|
||||
final String clientId = MapUtils.get(map, "clientId");
|
||||
// 忽略自己
|
||||
if(this.clientId.equals(clientId)) {
|
||||
return;
|
||||
}
|
||||
final RemoteClient remoteClient = new RemoteClient(name, clientId, this.taoyao, this.mainHandler);
|
||||
final RemoteClient old = this.remoteClients.put(clientId, remoteClient);
|
||||
if(old != null) {
|
||||
final RemoteClient remoteClient = new RemoteClient(name, clientId, this.taoyao, this.mainHandler);
|
||||
final RemoteClient oldRemoteClient = this.remoteClients.put(clientId, remoteClient);
|
||||
if(oldRemoteClient != null) {
|
||||
// 关闭旧的资源
|
||||
old.close();
|
||||
this.closeRemoteClient(oldRemoteClient);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭远程终端
|
||||
*
|
||||
* @param clientId 远程终端ID
|
||||
*/
|
||||
public void closeRemoteClient(String clientId) {
|
||||
final RemoteClient remoteClient = this.remoteClients.remove(clientId);
|
||||
this.closeRemoteClient(remoteClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭远程终端
|
||||
* 注意:需要自己从列表中删除
|
||||
*
|
||||
* @param remoteClient 远程终端
|
||||
*/
|
||||
private void closeRemoteClient(RemoteClient remoteClient) {
|
||||
if(remoteClient == null) {
|
||||
return;
|
||||
}
|
||||
@@ -265,88 +390,150 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
}
|
||||
Log.i(Room.class.getSimpleName(), "关闭房间:" + this.roomId);
|
||||
super.close();
|
||||
// 关闭Mediasoup房间
|
||||
this.nativeCloseRoom(this.nativeRoomPointer);
|
||||
// 关闭远程媒体
|
||||
this.remoteClients.values().forEach(v -> this.closeRemoteClient(v.clientId));
|
||||
this.remoteClients.values().forEach(this::closeRemoteClient);
|
||||
this.remoteClients.clear();
|
||||
// 关闭本地媒体
|
||||
this.localClient.close();
|
||||
// 释放终端
|
||||
this.mediaManager.closeClient();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动关闭消费者
|
||||
*
|
||||
* @param consumerId 消费者ID
|
||||
*/
|
||||
public void mediaConsumerClose(String consumerId) {
|
||||
this.taoyao.push(this.taoyao.buildMessage(
|
||||
"media::consumer::close",
|
||||
"roomId", this.roomId,
|
||||
"roomId", this.roomId,
|
||||
"consumerId", consumerId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭消费者回调(信令)
|
||||
*
|
||||
* @param body 消息主体
|
||||
*/
|
||||
public void mediaConsumerClose(Map<String, Object> body) {
|
||||
final String consumerId = MapUtils.get(body, "consumerId");
|
||||
this.nativeMediaConsumerClose(this.nativeRoomPointer, consumerId);
|
||||
this.remoteClients.values().forEach(v -> v.close(consumerId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动暂停消费者
|
||||
*
|
||||
* @param consumerId 消费者ID
|
||||
*/
|
||||
public void mediaConsumerPause(String consumerId) {
|
||||
this.taoyao.push(this.taoyao.buildMessage(
|
||||
"media::consumer::pause",
|
||||
"roomId", this.roomId,
|
||||
"roomId", this.roomId,
|
||||
"consumerId", consumerId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停消费者回调(信令)
|
||||
*
|
||||
* @param body 消息主体
|
||||
*/
|
||||
public void mediaConsumerPause(Map<String, Object> body) {
|
||||
this.nativeMediaConsumerPause(this.nativeRoomPointer, MapUtils.get(body, "consumerId"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动恢复消费者
|
||||
*
|
||||
* @param consumerId 消费者ID
|
||||
*/
|
||||
public void mediaConsumerResume(String consumerId) {
|
||||
this.taoyao.push(this.taoyao.buildMessage(
|
||||
"media::consumer::resume",
|
||||
"roomId", this.roomId,
|
||||
"roomId", this.roomId,
|
||||
"consumerId", consumerId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复消费者回调(信令)
|
||||
*
|
||||
* @param body 消息主体
|
||||
*/
|
||||
public void mediaConsumerResume(Map<String, Object> body) {
|
||||
this.nativeMediaConsumerResume(this.nativeRoomPointer, MapUtils.get(body, "consumerId"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动关闭生产者
|
||||
*
|
||||
* @param producerId 生产者ID
|
||||
*/
|
||||
public void mediaProducerClose(String producerId) {
|
||||
this.taoyao.push(this.taoyao.buildMessage(
|
||||
"media::producer::close",
|
||||
"roomId", this.roomId,
|
||||
"roomId", this.roomId,
|
||||
"producerId", producerId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭生产者回调(信令)
|
||||
*
|
||||
* @param body 消息主体
|
||||
*/
|
||||
public void mediaProducerClose(Map<String, Object> body) {
|
||||
final String producerId = MapUtils.get(body, "producerId");
|
||||
this.nativeMediaProducerClose(this.nativeRoomPointer, producerId);
|
||||
this.localClient.close(producerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动暂停生产者
|
||||
*
|
||||
* @param producerId 生产者ID
|
||||
*/
|
||||
public void mediaProducerPause(String producerId) {
|
||||
this.taoyao.push(this.taoyao.buildMessage(
|
||||
"media::producer::pause",
|
||||
"roomId", this.roomId,
|
||||
"roomId", this.roomId,
|
||||
"producerId", producerId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停生产者回调(信令)
|
||||
*
|
||||
* @param body 消息主体
|
||||
*/
|
||||
public void mediaProducerPause(Map<String, Object> body) {
|
||||
this.nativeMediaProducerPause(this.nativeRoomPointer, MapUtils.get(body, "producerId"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动恢复生产者
|
||||
*
|
||||
* @param producerId 生产者ID
|
||||
*/
|
||||
public void mediaProducerResume(String producerId) {
|
||||
this.taoyao.push(this.taoyao.buildMessage(
|
||||
"media::producer::resume",
|
||||
"roomId", this.roomId,
|
||||
"roomId", this.roomId,
|
||||
"producerId", producerId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复生产者回调(信令)
|
||||
*
|
||||
* @param body 消息主体
|
||||
*/
|
||||
public void mediaProducerResume(Map<String, Object> body) {
|
||||
this.nativeMediaProducerResume(this.nativeRoomPointer, MapUtils.get(body, "producerId"));
|
||||
}
|
||||
@@ -416,6 +603,18 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void producerCloseCallback(String producerId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void producerPauseCallback(String producerId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void producerResumeCallback(String producerId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consumerNewCallback(String message, long consumerPointer, long consumerMediaTrackPointer) {
|
||||
final Message response = JSONUtils.toJava(message, Message.class);
|
||||
@@ -423,13 +622,12 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
final String kind = MapUtils.get(body, "kind");
|
||||
final String sourceId = MapUtils.get(body, "sourceId");
|
||||
final String consumerId = MapUtils.get(body, "consumerId");
|
||||
final RemoteClient remoteClient = this.remoteClients.get(sourceId);
|
||||
if(remoteClient == null) {
|
||||
// TODO:资源释放
|
||||
return;
|
||||
}
|
||||
final RemoteClient remoteClient = this.remoteClients.computeIfAbsent(sourceId, key -> {
|
||||
// 假如媒体上来时间比进入房间消息快:基本上不可能出现这种情况
|
||||
Log.w(Room.class.getSimpleName(), "未知媒体来源:" + sourceId);
|
||||
return new RemoteClient(sourceId, sourceId, this.taoyao, this.mainHandler);
|
||||
});
|
||||
if(MediaStreamTrack.AUDIO_TRACK_KIND.equals(kind)) {
|
||||
// WebRtcAudioTrack
|
||||
final AudioTrack audioTrack = new AudioTrack(consumerMediaTrackPointer);
|
||||
audioTrack.setVolume(Config.DEFAULT_VOLUME);
|
||||
remoteClient.tracks.put(consumerId, audioTrack);
|
||||
@@ -442,25 +640,136 @@ public class Room extends CloseableClient implements RouterCallback {
|
||||
remoteClient.playVideo();
|
||||
} else {
|
||||
Log.w(Room.class.getSimpleName(), "未知媒体类型:" + kind);
|
||||
// TODO:资源释放
|
||||
return;
|
||||
}
|
||||
this.taoyao.push(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consumerCloseCallback(String consumerId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consumerPauseCallback(String consumerId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consumerResumeCallback(String consumerId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mediasoup创建房间
|
||||
*
|
||||
* @param roomId 房间ID
|
||||
* @param routerCallback 路由回调
|
||||
*
|
||||
* @return Mediasoup房间指针
|
||||
*/
|
||||
private native long nativeNewRoom(String roomId, RouterCallback routerCallback);
|
||||
|
||||
/**
|
||||
* Mediasou进入房间
|
||||
*
|
||||
* @param nativePointer 房间指针
|
||||
* @param rtpCapabilities RTP能力
|
||||
* @param peerConnectionFactoryPointer PeerConnectionFactory指针
|
||||
* @param rtcConfiguration RTC配置
|
||||
*/
|
||||
private native void nativeEnterRoom(long nativePointer, String rtpCapabilities, long peerConnectionFactoryPointer, PeerConnection.RTCConfiguration rtcConfiguration);
|
||||
|
||||
/**
|
||||
* Mediasoup关闭房间
|
||||
*
|
||||
* @param nativePointer 房间指针
|
||||
*/
|
||||
private native void nativeCloseRoom(long nativePointer);
|
||||
|
||||
/**
|
||||
* Mediasoup创建发送通道
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param body 消息主体
|
||||
*/
|
||||
private native void nativeCreateSendTransport(long nativeRoomPointer, String body);
|
||||
|
||||
/**
|
||||
* Mediasoup创建接收通道
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param body 消息主体
|
||||
*/
|
||||
private native void nativeCreateRecvTransport(long nativeRoomPointer, String body);
|
||||
|
||||
/**
|
||||
* Mediasoup生产音频
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param mediaStreamPointer 媒体指针
|
||||
*/
|
||||
private native void nativeMediaProduceAudio(long nativeRoomPointer, long mediaStreamPointer);
|
||||
|
||||
/**
|
||||
* Mediasoup生产视频
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param mediaStreamPointer 媒体指针
|
||||
*/
|
||||
private native void nativeMediaProduceVideo(long nativeRoomPointer, long mediaStreamPointer);
|
||||
|
||||
/**
|
||||
* Mediasoup消费
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param message 信令消息
|
||||
*/
|
||||
private native void nativeMediaConsume(long nativeRoomPointer, String message);
|
||||
|
||||
/**
|
||||
* Mediasoup暂停生产者
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param producerId 生产者ID
|
||||
*/
|
||||
private native void nativeMediaProducerPause(long nativeRoomPointer, String producerId);
|
||||
|
||||
/**
|
||||
* Mediasoup恢复生产者
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param producerId 生产者ID
|
||||
*/
|
||||
private native void nativeMediaProducerResume(long nativeRoomPointer, String producerId);
|
||||
|
||||
/**
|
||||
* Mediasoup关闭生产者
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param producerId 生产者ID
|
||||
*/
|
||||
private native void nativeMediaProducerClose(long nativeRoomPointer, String producerId);
|
||||
|
||||
/**
|
||||
* Mediasoup暂停消费者
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param consumerId 消费者ID
|
||||
*/
|
||||
private native void nativeMediaConsumerPause(long nativeRoomPointer, String consumerId);
|
||||
|
||||
/**
|
||||
* Mediasoup恢复消费者
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param consumerId 消费者ID
|
||||
*/
|
||||
private native void nativeMediaConsumerResume(long nativeRoomPointer, String consumerId);
|
||||
|
||||
/**
|
||||
* Mediasoup关闭消费者
|
||||
*
|
||||
* @param nativeRoomPointer 房间指针
|
||||
* @param consumerId 消费者ID
|
||||
*/
|
||||
private native void nativeMediaConsumerClose(long nativeRoomPointer, String consumerId);
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,13 @@ module.exports = {
|
||||
// 信令密码
|
||||
password: "taoyao",
|
||||
},
|
||||
// 录像配置
|
||||
record: {
|
||||
// 请求关键帧的最大次数
|
||||
requestKeyFrameMaxIndex: 16,
|
||||
// 请求关键帧的文件大小
|
||||
requestKeyFrameFileSize: 32 * 1024,
|
||||
},
|
||||
// Mediasoup
|
||||
mediasoup: {
|
||||
// 配置Worker进程数量
|
||||
|
||||
@@ -79,7 +79,7 @@ async function connectSignalServer() {
|
||||
* 启动方法
|
||||
*/
|
||||
async function main() {
|
||||
console.log(`
|
||||
console.debug(`
|
||||
桃之夭夭,灼灼其华。
|
||||
之子于归,宜其室家。
|
||||
|
||||
|
||||
@@ -814,7 +814,7 @@ class Taoyao {
|
||||
audioTransport.clientId = clientId;
|
||||
room.transports.set(audioTransport.id, audioTransport);
|
||||
audioTransport.observer.on("close", () => {
|
||||
console.log("controlServerRecord audioTransport close:", audioTransport.id);
|
||||
console.debug("controlServerRecord audioTransport close:", audioTransport.id);
|
||||
room.transports.delete(audioTransport.id)
|
||||
});
|
||||
await audioTransport.connect({
|
||||
@@ -833,10 +833,10 @@ class Taoyao {
|
||||
audioConsumer.streamId = audioStreamId;
|
||||
room.consumers.set(audioConsumer.id, audioConsumer);
|
||||
audioConsumer.observer.on("close", () => {
|
||||
console.log("controlServerRecord audioConsumer close:", audioConsumer.id);
|
||||
console.debug("controlServerRecord audioConsumer close:", audioConsumer.id);
|
||||
room.consumers.delete(audioConsumer.id);
|
||||
});
|
||||
console.log("controlServerRecord audio", audioTransportId, audioConsumerId, audioTransport.tuple, audioRtpParameters);
|
||||
console.debug("controlServerRecord audio", audioTransportId, audioConsumerId, audioTransport.tuple, audioRtpParameters);
|
||||
}
|
||||
if(videoProducerId) {
|
||||
const videoTransport = await room.mediasoupRouter.createPlainTransport(plainTransportOptions);
|
||||
@@ -845,7 +845,7 @@ class Taoyao {
|
||||
videoTransport.clientId = clientId;
|
||||
room.transports.set(videoTransport.id, videoTransport);
|
||||
videoTransport.observer.on("close", () => {
|
||||
console.log("controlServerRecord videoTransport close:", videoTransport.id);
|
||||
console.debug("controlServerRecord videoTransport close:", videoTransport.id);
|
||||
room.transports.delete(videoTransport.id)
|
||||
});
|
||||
await videoTransport.connect({
|
||||
@@ -864,10 +864,10 @@ class Taoyao {
|
||||
videoConsumer.streamId = videoStreamId;
|
||||
room.consumers.set(videoConsumer.id, videoConsumer);
|
||||
videoConsumer.observer.on("close", () => {
|
||||
console.log("controlServerRecord videoConsumer close:", videoConsumer.id);
|
||||
console.debug("controlServerRecord videoConsumer close:", videoConsumer.id);
|
||||
room.consumers.delete(videoConsumer.id);
|
||||
});
|
||||
console.log("controlServerRecord video:", videoTransportId, videoConsumerId, videoTransport.tuple, videoRtpParameters);
|
||||
console.debug("controlServerRecord video:", videoTransportId, videoConsumerId, videoTransport.tuple, videoRtpParameters);
|
||||
}
|
||||
if(audioConsumer) {
|
||||
await audioConsumer.resume();
|
||||
@@ -900,7 +900,7 @@ class Taoyao {
|
||||
if(!filepath || !videoConsumer) {
|
||||
return;
|
||||
}
|
||||
if(++index > 10) {
|
||||
if(++index > config.record.requestKeyFrameMaxIndex) {
|
||||
console.warn("请求录像关键帧次数超限", filepath, index);
|
||||
return;
|
||||
}
|
||||
@@ -909,7 +909,7 @@ class Taoyao {
|
||||
return;
|
||||
}
|
||||
// 判断文件大小验证是否已经开始录像:创建文件 -> 视频信息 -> 视频数据 -> 封装视频
|
||||
if(fs.existsSync(filepath) && fs.statSync(filepath).size >= 128 * 1024) {
|
||||
if(fs.existsSync(filepath) && fs.statSync(filepath).size >= config.record.requestKeyFrameFileSize) {
|
||||
console.debug("请求录像关键帧已经开始录像", filepath);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user