diff --git a/README.md b/README.md index ceeadc9..52ffd83 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,10 @@ |taoyao-client-harmony|鸿蒙终端|鸿蒙智能终端接入| |taoyao-signal-server|信令服务|终端信令控制| +## 证书 + +本地开发测试安装`docs/certs`中的`ca.crt`证书 + ## 部署 [部署文档](./docs/Deploy.md) diff --git a/docs/Test.md b/docs/Test.md deleted file mode 100644 index 70650e4..0000000 --- a/docs/Test.md +++ /dev/null @@ -1,7 +0,0 @@ -# 测试 - -## 推流测试 - -``` -ffmpeg -``` diff --git a/docs/etc/nginx.conf b/docs/etc/nginx.conf index 14622a4..1332bd5 100644 --- a/docs/etc/nginx.conf +++ b/docs/etc/nginx.conf @@ -19,7 +19,7 @@ http { default_type application/octet-stream; gzip on; - gzip_types text/xml text/css text/plain text/javascript image/gif image/png image/jpg image/webp image/jpeg image/x-icon image/svg+xml application/json application/javascript font/woff application/octet-stream application/vnd.ms-fontobject; + gzip_types font/woff text/xml text/css text/plain text/javascript image/gif image/png image/jpg image/webp image/jpeg image/x-icon image/svg+xml application/json application/javascript application/octet-stream application/vnd.ms-fontobject; gzip_min_length 1k; sendfile on; diff --git a/taoyao-client-media/src/Config.js b/taoyao-client-media/src/Config.js index 4eba195..d7b3899 100644 --- a/taoyao-client-media/src/Config.js +++ b/taoyao-client-media/src/Config.js @@ -119,12 +119,12 @@ module.exports = { announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || defaultTaoyaoHost || "127.0.0.1", }, // TCP - // { - // protocol: "tcp", - // ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0", - // port: 44444, - // announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || defaultTaoyaoHost || "127.0.0.1", - // }, + { + protocol: "tcp", + ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0", + port: 44444, + announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || defaultTaoyaoHost || "127.0.0.1", + }, ], }, // WebRtcTransport:https://mediasoup.org/documentation/v3/mediasoup/api/#WebRtcTransportOptions diff --git a/taoyao-client-media/src/Taoyao.js b/taoyao-client-media/src/Taoyao.js index 94246c3..998e7b3 100644 --- a/taoyao-client-media/src/Taoyao.js +++ b/taoyao-client-media/src/Taoyao.js @@ -452,8 +452,8 @@ class Taoyao { case "media::transport::close": this.mediaTransportClose(message, body); break; - case "media::transport::plain::in": - me.mediaTransportPlainIn(message, body); + case "media::transport::plain": + me.mediaTransportPlain(message, body); break; case "media::transport::webrtc::connect": me.mediaTransportWebrtcConnect(message, body); @@ -629,8 +629,8 @@ class Taoyao { producer.on("videoorientationchange", (videoOrientation) => { console.info("producer videoorientationchange:", producer.id, videoOrientation); self.push(protocol.buildMessage("media::video::orientation::change", { + ...videoOrientation, roomId: roomId, - ...videoOrientation })); }); // await producer.enableTraceEvent([ 'rtp', 'keyframe', 'nack', 'pli', 'fir' ]); @@ -821,6 +821,7 @@ class Taoyao { }); consumer.on("producerpause", () => { console.info("consumer producerpause:", consumer.id); + // consumer.pause(); this.push( protocol.buildMessage("media::consumer::pause", { roomId: roomId, @@ -830,6 +831,7 @@ class Taoyao { }); consumer.on("producerresume", () => { console.info("consumer producerresume:", consumer.id); + // consumer.resume(); this.push( protocol.buildMessage("media::consumer::resume", { roomId: roomId, @@ -1261,16 +1263,21 @@ class Taoyao { * @param {*} message 消息 * @param {*} body 消息主体 */ - async mediaTransportPlainIn(message, body) { + async mediaTransportPlain(message, body) { const me = this; - const { roomId, rtcpMux, comedia, clientId } = body; + const { roomId, rtcpMux, comedia, clientId, enableSctp, numSctpStreams, enableSrtp, srtpCryptoSuite } = body; const plainTransportOptions = { - rtcpMux: rtcpMux, - comedia: comedia, ...config.mediasoup.plainTransportOptions, + rtcpMux: rtcpMux, + comedia: comedia, + enableSctp: enableSctp || Boolean(numSctpStreams), + numSctpStreams: numSctpStreams || 0, + enableSrtp: enableSrtp, + srtpCryptoSuite: srtpCryptoSuite, }; const room = this.rooms.get(roomId); const transport = await room.mediasoupRouter.createPlainTransport(plainTransportOptions); + me.transportEvent("plain", roomId, transport); transport.clientId = clientId; room.transports.set(transport.id, transport); console.info(transport.tuple) @@ -1336,8 +1343,35 @@ class Taoyao { ...webRtcTransportOptions, webRtcServer: room.webRtcServer, }); + me.transportEvent("webrtc", roomId, transport); transport.clientId = clientId; - // 通用事件 + room.transports.set(transport.id, transport); + message.body = { + roomId: roomId, + transportId: transport.id, + iceCandidates: transport.iceCandidates, + iceParameters: transport.iceParameters, + dtlsParameters: transport.dtlsParameters, + sctpParameters: transport.sctpParameters, + }; + self.push(message); + const { maxIncomingBitrate } = config.mediasoup.webRtcTransportOptions; + // If set, apply max incoming bitrate limit. + if (maxIncomingBitrate) { + try { + await transport.setMaxIncomingBitrate(maxIncomingBitrate); + } catch (error) {} + } + } + /** + * 通道事件 + * + * @param {*} type 类型:webrtc|plain|pipe|direct + * @param {*} roomId 房间ID + * @param {*} transport 通道 + */ + transportEvent(type, roomId, transport) { + /********************* 通用通道事件 *********************/ transport.on("routerclose", () => { console.info("transport routerclose:", transport.id); transport.close(); @@ -1377,50 +1411,41 @@ class Taoyao { // }); // transport.observer.on("trace", fn(trace)); /********************* webRtcTransport通道事件 *********************/ - // transport.on("icestatechange", (iceState) => { - // console.info("transport icestatechange:", transport.id, iceState); - // }); - // transport.on("iceselectedtuplechange", (iceSelectedTuple) => { - // console.info("transport iceselectedtuplechange:", transport.id, iceSelectedTuple); - // }); - // transport.on("dtlsstatechange", (dtlsState) => { - // console.info("transport dtlsstatechange:", transport.id, dtlsState); - // }); - // transport.on("sctpstatechange", (sctpState) => { - // console.info("transport sctpstatechange:", transport.id, sctpState); - // }); - // transport.observer.on("icestatechange", fn(iceState)); - // transport.observer.on("iceselectedtuplechange", fn(iceSelectedTuple)); - // transport.observer.on("dtlsstatechange", fn(dtlsState)); - // transport.observer.on("sctpstatechange", fn(sctpState)); + if("webrtc" === type) { + // transport.on("icestatechange", (iceState) => { + // console.info("transport icestatechange:", transport.id, iceState); + // }); + // transport.on("iceselectedtuplechange", (iceSelectedTuple) => { + // console.info("transport iceselectedtuplechange:", transport.id, iceSelectedTuple); + // }); + // transport.on("dtlsstatechange", (dtlsState) => { + // console.info("transport dtlsstatechange:", transport.id, dtlsState); + // }); + // transport.on("sctpstatechange", (sctpState) => { + // console.info("transport sctpstatechange:", transport.id, sctpState); + // }); + // transport.observer.on("icestatechange", fn(iceState)); + // transport.observer.on("iceselectedtuplechange", fn(iceSelectedTuple)); + // transport.observer.on("dtlsstatechange", fn(dtlsState)); + // transport.observer.on("sctpstatechange", fn(sctpState)); + } /********************* plainTransport通道事件 *********************/ - // transport.on("tuple", fn(tuple)); - // transport.on("rtcptuple", fn(rtcpTuple)); - // transport.on("sctpstatechange", fn(sctpState)); - // transport.observer.on("tuple", fn(tuple)); - // transport.observer.on("rtcptuple", fn(rtcpTuple)); - // transport.observer.on("sctpstatechange", fn(sctpState)); + if("plain" === type) { + // transport.on("tuple", fn(tuple)); + // transport.on("rtcptuple", fn(rtcpTuple)); + // transport.on("sctpstatechange", fn(sctpState)); + // transport.observer.on("tuple", fn(tuple)); + // transport.observer.on("rtcptuple", fn(rtcpTuple)); + // transport.observer.on("sctpstatechange", fn(sctpState)); + } /********************* pipeTransport通道事件 *********************/ - // transport.on("sctpstatechange", fn(sctpState)); - // transport.observer.on("sctpstatechange", fn(sctpState)); + if("pipe" === type) { + // transport.on("sctpstatechange", fn(sctpState)); + // transport.observer.on("sctpstatechange", fn(sctpState)); + } /********************* directTransport通道事件 *********************/ - // transport.on("rtcp", fn(rtcpPacket)); - room.transports.set(transport.id, transport); - message.body = { - roomId: roomId, - transportId: transport.id, - iceCandidates: transport.iceCandidates, - iceParameters: transport.iceParameters, - dtlsParameters: transport.dtlsParameters, - sctpParameters: transport.sctpParameters, - }; - self.push(message); - const { maxIncomingBitrate } = config.mediasoup.webRtcTransportOptions; - // If set, apply max incoming bitrate limit. - if (maxIncomingBitrate) { - try { - await transport.setMaxIncomingBitrate(maxIncomingBitrate); - } catch (error) {} + if("rtcp" === type) { + // transport.on("rtcp", fn(rtcpPacket)); } } /** diff --git a/taoyao-client-web/README.md b/taoyao-client-web/README.md index 40bc4b2..6d26924 100644 --- a/taoyao-client-web/README.md +++ b/taoyao-client-web/README.md @@ -1,13 +1,7 @@ # Web终端 -注意部分`API`需要`localhost`或者`https` - ## Web终端 * [mediasoup-client源码](https://github.com/versatica/mediasoup-client) * [mediasoup-client文档](https://mediasoup.org/documentation/v3/mediasoup-client) * [mediasoup-client接口](https://mediasoup.org/documentation/v3/mediasoup-client/api) - -## TODO - -按钮:选择房间、媒体服务、开关 diff --git a/taoyao-client-web/src/components/Taoyao.js b/taoyao-client-web/src/components/Taoyao.js index b52bad0..eb7a136 100644 --- a/taoyao-client-web/src/components/Taoyao.js +++ b/taoyao-client-web/src/components/Taoyao.js @@ -21,8 +21,9 @@ const protocol = { * @returns 索引 */ buildId() { - if (++this.index > this.maxIndex) { - this.index = 0; + const me = this; + if (++me.index > me.maxIndex) { + me.index = 0; } const date = new Date(); return ( @@ -30,8 +31,8 @@ const protocol = { 1000000000000 * date.getHours() + 10000000000 * date.getMinutes() + 100000000 * date.getSeconds() + - 1000 * this.clientIndex + - this.index + 1000 * me.clientIndex + + me.index ); }, /** @@ -2010,23 +2011,25 @@ class Taoyao extends RemoteClient { */ closeMedia() { let me = this; - if (me.sendTransport) { - me.sendTransport.close(); - } - if (me.recvTransport) { - me.recvTransport.close(); - } if(me.audioTrack) { me.audioTrack.stop(); } if(me.videoTrack) { me.videoTrack.stop(); } + if (me.sendTransport) { + me.sendTransport.close(); + } + if (me.recvTransport) { + me.recvTransport.close(); + } me.sendTransport = null; me.recvTransport = null; + me.dataProducer = null; me.audioProducer = null; me.videoProducer = null; - me.dataProducer = null; + me.consumers.clear(); + me.dataConsumers.clear(); } /** * 关闭资源 diff --git a/taoyao-signal-server/docs/assembly/dev.xml b/taoyao-signal-server/docs/assembly/dev.xml index 949ffa3..c7aaee0 100644 --- a/taoyao-signal-server/docs/assembly/dev.xml +++ b/taoyao-signal-server/docs/assembly/dev.xml @@ -1,58 +1,60 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd"> - dev + dev - - dir - + + dir + - false + false - - - ${taoyao.maven.basedir}/docs - ./ - - README.md - - - - ${taoyao.maven.basedir}/docs/bin - bin - 0755 - true - - - src/main/resources - config - true - - *.yml - *.properties - - - - src/main/resources - config - - *.jks - - - - target - logs - - **/* - - - + + + ${taoyao.maven.basedir}/docs + ./ + + README.md + + + + ${taoyao.maven.basedir}/docs/bin + bin + 0755 + true + + + src/main/resources + config + true + + *.yml + *.properties + + + + src/main/resources + config + + *.jks + *.p12 + *.pfx + + + + target + logs + + **/* + + + - - - lib - - + + + lib + + diff --git a/taoyao-signal-server/docs/assembly/prd.xml b/taoyao-signal-server/docs/assembly/prd.xml index 0458d14..f7077f1 100644 --- a/taoyao-signal-server/docs/assembly/prd.xml +++ b/taoyao-signal-server/docs/assembly/prd.xml @@ -37,7 +37,9 @@ src/main/resources config - *.jks + *.jks + *.p12 + *.pfx diff --git a/taoyao-signal-server/pom.xml b/taoyao-signal-server/pom.xml index bbe50f3..0db026a 100644 --- a/taoyao-signal-server/pom.xml +++ b/taoyao-signal-server/pom.xml @@ -175,7 +175,9 @@ - *.jks + *.jks + *.p12 + *.pfx *.yml *.properties diff --git a/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/ConfigController.java b/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/ConfigController.java index 3de4f12..05794ef 100644 --- a/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/ConfigController.java +++ b/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/ConfigController.java @@ -15,6 +15,7 @@ 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; +import lombok.RequiredArgsConstructor; /** * 配置 @@ -24,6 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; @Tag(name = "配置", description = "配置管理") @RestController @RequestMapping("/config") +@RequiredArgsConstructor public class ConfigController { private final MediaProperties mediaProperties; @@ -31,18 +33,6 @@ public class ConfigController { private final SocketProperties socketProperties; private final WebrtcProperties webrtcProperties; - public ConfigController( - MediaProperties mediaProperties, - CameraProperties cameraProperties, - SocketProperties socketProperties, - WebrtcProperties webrtcProperties - ) { - this.mediaProperties = mediaProperties; - this.cameraProperties = cameraProperties; - this.socketProperties = socketProperties; - this.webrtcProperties = webrtcProperties; - } - @Operation(summary = "媒体配置", description = "媒体配置") @GetMapping("/media") @ApiResponse(content = @Content(schema = @Schema(implementation = MediaProperties.class))) diff --git a/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/ControlController.java b/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/ControlController.java index 5e059ad..fc06029 100644 --- a/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/ControlController.java +++ b/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/ControlController.java @@ -27,6 +27,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; /** * 控制 @@ -37,6 +38,7 @@ import jakarta.validation.constraints.NotNull; @Validated @RestController @RequestMapping("/control") +@RequiredArgsConstructor public class ControlController { private final ControlAiProtocol controlAiProtocol; @@ -49,28 +51,6 @@ public class ControlController { private final ControlConfigAudioProtocol controlConfigAudioProtocol; private final ControlConfigVideoProtocol controlConfigVideoProtocol; - public ControlController( - ControlAiProtocol controlAiProtocol, - ControlPtzProtocol controlPtzProtocol, - ControlBellProtocol controlBellProtocol, - ControlBeautyProtocol controlBeautyProtocol, - ControlRecordProtocol controlRecordProtocol, - ControlWatermarkProtocol controlWatermarkProtocol, - ControlPhotographProtocol controlPhotographProtocol, - ControlConfigAudioProtocol controlConfigAudioProtocol, - ControlConfigVideoProtocol controlConfigVideoProtocol - ) { - this.controlAiProtocol = controlAiProtocol; - this.controlPtzProtocol = controlPtzProtocol; - this.controlBellProtocol = controlBellProtocol; - this.controlBeautyProtocol = controlBeautyProtocol; - this.controlRecordProtocol = controlRecordProtocol; - this.controlWatermarkProtocol = controlWatermarkProtocol; - this.controlPhotographProtocol = controlPhotographProtocol; - this.controlConfigAudioProtocol = controlConfigAudioProtocol; - this.controlConfigVideoProtocol = controlConfigVideoProtocol; - } - @Operation(summary = "AI识别", description = "AI识别控制") @GetMapping("/ai/{clientId}") public Message ai(@PathVariable String clientId, @Valid AiProperties aiProperties) { diff --git a/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/PlatformController.java b/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/PlatformController.java index 55b1468..77cd0ee 100644 --- a/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/PlatformController.java +++ b/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/PlatformController.java @@ -7,6 +7,7 @@ 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.boot.model.MessageCode; import com.acgist.taoyao.signal.protocol.platform.PlatformRebootProtocol; import com.acgist.taoyao.signal.protocol.platform.PlatformShutdownProtocol; @@ -38,6 +39,9 @@ public class PlatformController { @Operation(summary = "重启平台", description = "重启平台") @GetMapping("/reboot") public Message platformReboot() { + if(this.platformRebootProtocol == null) { + return Message.fail(MessageCode.CODE_3406, "功能没有开启"); + } this.platformRebootProtocol.execute(); return Message.success(); } @@ -45,6 +49,9 @@ public class PlatformController { @Operation(summary = "关闭平台", description = "关闭平台") @GetMapping("/shutdown") public Message platformShutdown() { + if(this.platformShutdownProtocol == null) { + return Message.fail(MessageCode.CODE_3406, "功能没有开启"); + } this.platformShutdownProtocol.execute(); return Message.success(); } diff --git a/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/SystemController.java b/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/SystemController.java index 89da2af..198be38 100644 --- a/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/SystemController.java +++ b/taoyao-signal-server/taoyao-server/src/main/java/com/acgist/taoyao/controller/SystemController.java @@ -7,6 +7,7 @@ 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.boot.model.MessageCode; import com.acgist.taoyao.signal.protocol.system.SystemRebootProtocol; import com.acgist.taoyao.signal.protocol.system.SystemShutdownProtocol; @@ -38,6 +39,9 @@ public class SystemController { @Operation(summary = "重启系统", description = "重启系统") @GetMapping("/reboot") public Message systemReboot() { + if(this.systemRebootProtocol == null) { + return Message.fail(MessageCode.CODE_3406, "功能没有开启"); + } this.systemRebootProtocol.execute(); return Message.success(); } @@ -45,6 +49,9 @@ public class SystemController { @Operation(summary = "关闭系统", description = "关闭系统") @GetMapping("/shutdown") public Message systemShutdown() { + if(this.systemShutdownProtocol == null) { + return Message.fail(MessageCode.CODE_3406, "功能没有开启"); + } this.systemShutdownProtocol.execute(); return Message.success(); } diff --git a/taoyao-signal-server/taoyao-server/src/test/java/com/acgist/taoyao/signal/SocketSignalTest.java b/taoyao-signal-server/taoyao-server/src/test/java/com/acgist/taoyao/signal/SocketSignalTest.java index 6c62f7f..cda69b8 100644 --- a/taoyao-signal-server/taoyao-server/src/test/java/com/acgist/taoyao/signal/SocketSignalTest.java +++ b/taoyao-signal-server/taoyao-server/src/test/java/com/acgist/taoyao/signal/SocketSignalTest.java @@ -80,7 +80,7 @@ public class SocketSignalTest { } """; // {"header":{"v":"1.0.0","id":1215310510002009,"signal":"room::enter"},"body":{"roomId":"8260e615-3081-4bfc-96a8-574f4dd780d9"}} - // {"header":{"v":"1.0.0","id":1215310510002010,"signal":"media::transport::plain::in"},"body":{"roomId":"8260e615-3081-4bfc-96a8-574f4dd780d9","rtcpMux":false,"comedia":true}} + // {"header":{"v":"1.0.0","id":1215310510002010,"signal":"media::transport::plain"},"body":{"roomId":"8260e615-3081-4bfc-96a8-574f4dd780d9","rtcpMux":false,"comedia":true}} // {"header":{"v":"1.0.0","id":1215375110006012,"signal":"media::produce"},"body":{"kind":"video","roomId":"8260e615-3081-4bfc-96a8-574f4dd780d9","transportId":"14dc9307-bf9c-4442-a9ad-ce6a97623ef4","appData":{},"rtpParameters":{"codecs":[{"mimeType":"video/vp8","clockRate":90000,"payloadType":102,"rtcpFeedback":[]}],"encodings":[{"ssrc":123123}]}}} // ffplay -protocol_whitelist "file,udp,rtp" taoyao.sdp // ffmpeg -re -i video.mp4 -vcodec copy -map 0:0 -f rtp rtp://localhost:6666 > taoyao.sdp diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/configuration/SignalAutoConfiguration.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/configuration/SignalAutoConfiguration.java index ab12df5..74413a7 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/configuration/SignalAutoConfiguration.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/configuration/SignalAutoConfiguration.java @@ -1,6 +1,5 @@ package com.acgist.taoyao.signal.configuration; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -13,6 +12,7 @@ import com.acgist.taoyao.signal.event.EventPublisher; import com.acgist.taoyao.signal.protocol.ProtocolManager; import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; /** * 信令自动配置 @@ -20,13 +20,13 @@ import jakarta.annotation.PostConstruct; * @author acgist */ @AutoConfiguration +@RequiredArgsConstructor @EnableConfigurationProperties({ CameraProperties.class }) public class SignalAutoConfiguration { - @Autowired - private ApplicationContext applicationContext; + private final ApplicationContext applicationContext; @PostConstruct public void init() { diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/ClientController.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/ClientController.java index f545987..99141c2 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/ClientController.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/ClientController.java @@ -17,6 +17,7 @@ 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; +import lombok.RequiredArgsConstructor; /** * 终端 @@ -26,6 +27,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; @Tag(name = "终端", description = "终端管理") @RestController @RequestMapping("/client") +@RequiredArgsConstructor public class ClientController { private final ClientManager clientManager; @@ -33,16 +35,6 @@ public class ClientController { private final ClientRebootProtocol clientRebootProtocol; private final ClientShutdownProtocol clientShutdownProtocol; - public ClientController( - ClientManager clientManager, ClientWakeupProtocol clientWakeupProtocol, - ClientRebootProtocol clientRebootProtocol, ClientShutdownProtocol clientShutdownProtocol - ) { - this.clientManager = clientManager; - this.clientWakeupProtocol = clientWakeupProtocol; - this.clientRebootProtocol = clientRebootProtocol; - this.clientShutdownProtocol = clientShutdownProtocol; - } - @Operation(summary = "终端列表", description = "终端列表") @GetMapping("/list") @ApiResponse(content = @Content(schema = @Schema(implementation = ClientStatus.class))) diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/ProtocolController.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/ProtocolController.java index 4a4d990..578f4fd 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/ProtocolController.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/ProtocolController.java @@ -15,6 +15,7 @@ import com.acgist.taoyao.signal.protocol.Protocol; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; /** @@ -26,14 +27,11 @@ import lombok.extern.slf4j.Slf4j; @Slf4j @RestController @RequestMapping("/protocol") +@RequiredArgsConstructor public class ProtocolController { private final ApplicationContext applicationContext; - public ProtocolController(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } - @Operation(summary = "信令列表", description = "信令列表Markdown") @GetMapping("/list") public String list() { diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/RoomController.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/RoomController.java index 219c9a9..8f4620a 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/RoomController.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/controller/RoomController.java @@ -19,6 +19,7 @@ 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; +import lombok.RequiredArgsConstructor; /** * 房间 @@ -29,14 +30,11 @@ import io.swagger.v3.oas.annotations.tags.Tag; @Validated @RestController @RequestMapping("/room") +@RequiredArgsConstructor public class RoomController { private final RoomManager roomManager; - public RoomController(RoomManager roomManager) { - this.roomManager = roomManager; - } - @Operation(summary = "房间信息", description = "房间信息") @GetMapping("/log") public Message log() { diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/RouteType.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/RouterType.java similarity index 92% rename from taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/RouteType.java rename to taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/RouterType.java index 9f05665..7df002b 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/RouteType.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/RouterType.java @@ -5,7 +5,7 @@ package com.acgist.taoyao.signal.party.media; * * @author acgist */ -public enum RouteType { +public enum RouterType { // 对讲:只有两个人之间的媒体相互路由 ONE_TO_ONE, diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaConsumeProtocol.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaConsumeProtocol.java index 5a08e02..475062a 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaConsumeProtocol.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaConsumeProtocol.java @@ -67,11 +67,16 @@ public class MediaConsumeProtocol extends ProtocolRoomAdapter implements Applica final ClientWrapper produceClientWrapper = producer.getProducerClient(); room.getClients().values().stream() .filter(v -> v != produceClientWrapper) + .filter(v -> v.getRecvTransport() != null) .filter(v -> v.getSubscribeType().canConsume(producer)) .forEach(v -> this.consume(room, v, producer, this.build())); } else if(event.getClientWrapper() != null) { // 创建WebRTC消费通道:消费其他终端 final ClientWrapper consumeClientWrapper = event.getClientWrapper(); + if(consumeClientWrapper.getRecvTransport() == null) { + log.debug("没有消费通道:{}", consumeClientWrapper.getClientId()); + return; + } room.getClients().values().stream() .filter(v -> v != consumeClientWrapper) .flatMap(v -> v.getProducers().values().stream()) diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaSetRouterTypeProtocol.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaSetRouterTypeProtocol.java new file mode 100644 index 0000000..c65cd57 --- /dev/null +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaSetRouterTypeProtocol.java @@ -0,0 +1,34 @@ +package com.acgist.taoyao.signal.protocol.media; + +import java.util.Map; + +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.party.media.Room; +import com.acgist.taoyao.signal.protocol.ProtocolRoomAdapter; + +/** + * 设置路由类型信令 + * 注意:不会添加移除消费者生产者,只会暂停恢复操作。 + * + * @author acgist + */ +public class MediaSetRouterTypeProtocol extends ProtocolRoomAdapter { + + public static final String SIGNAL = "media::set::router::type"; + + public MediaSetRouterTypeProtocol() { + super("设置路由类型信令", SIGNAL); + } + + @Override + public void execute(String clientId, ClientType clientType, Room room, Client client, Client mediaClient, Message message, Map body) { + if(clientType.mediaClient()) { + // TODO:路由类型 + } else { + this.logNoAdapter(clientType); + } + } + +} diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaTransportPlainOutProtocol.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaTransportPlainOutProtocol.java deleted file mode 100644 index ba36b6b..0000000 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaTransportPlainOutProtocol.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.acgist.taoyao.signal.protocol.media; - -/** - * 创建RTP输出通道信令 - * - * @author acgist - */ -public class MediaTransportPlainOutProtocol { - -} diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaTransportPlainInProtocol.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaTransportPlainProtocol.java similarity index 82% rename from taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaTransportPlainInProtocol.java rename to taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaTransportPlainProtocol.java index f60e677..865ae58 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaTransportPlainInProtocol.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/media/MediaTransportPlainProtocol.java @@ -22,7 +22,10 @@ import lombok.extern.slf4j.Slf4j; /** * 创建RTP输入通道信令 - * TODO:srtp + * 注意: + * 3. ffmpeg不支持rtcpMux + * 2. comedia必须开启srtp功能 + * 1. 如果关闭comedia不会自动升级双向通道 * * @author acgist */ @@ -34,14 +37,21 @@ import lombok.extern.slf4j.Slf4j; "roomId": "房间ID", "rtcpMux": RTP和RTCP端口复用(true|false), "comedia": 自动终端端口(true|false), + "enableSctp": 是否开启sctp(true|false), + "numSctpStreams": sctp数量, + "enableSrtp": 是否开启srtp(true|false), + "srtpCryptoSuite": { + "cryptoSuite": "算法(AEAD_AES_256_GCM|AEAD_AES_128_GCM|AES_CM_128_HMAC_SHA1_80|AES_CM_128_HMAC_SHA1_32)", + "keyBase64": "密钥" + } } """ ) -public class MediaTransportPlainInProtocol extends ProtocolRoomAdapter { +public class MediaTransportPlainProtocol extends ProtocolRoomAdapter { - public static final String SIGNAL = "media::transport::plain::in"; + public static final String SIGNAL = "media::transport::plain"; - public MediaTransportPlainInProtocol() { + public MediaTransportPlainProtocol() { super("创建RTP输入通道信令", SIGNAL); } @@ -65,6 +75,7 @@ public class MediaTransportPlainInProtocol extends ProtocolRoomAdapter { log.warn("发送通道已经存在:{}", transportId); } clientWrapper.setSendTransport(sendTransport); + // TODO:双向队列 // 拷贝属性 sendTransport.copy(responseBody); client.push(response); diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/room/RoomExpelProtocol.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/room/RoomExpelProtocol.java index b24e882..ffc34f2 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/room/RoomExpelProtocol.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/room/RoomExpelProtocol.java @@ -40,6 +40,8 @@ public class RoomExpelProtocol extends ProtocolRoomAdapter { if(clientType.mediaClient()) { final String expelClientId = MapUtils.get(body, Constant.CLIENT_ID); room.unicast(expelClientId, message); + // 如果需要强制提出 +// room.leave(this.clientManager.clients(expelClientId)); } else { this.logNoAdapter(clientType); }