[*] 调整接口
This commit is contained in:
11
README.md
11
README.md
@@ -44,12 +44,9 @@
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* 录制(Recorder)
|
|
||||||
* 音频:降噪、混音、变声
|
|
||||||
* 视频:水印、美颜、AI识别
|
|
||||||
* P2P
|
* P2P
|
||||||
* 反复测试推流拉流、拉人踢人、音频视频控制
|
|
||||||
* 优化JS错误回调 -> platform::error
|
|
||||||
* 24小时不关闭媒体/一秒一次推拉流十分钟测试/三十秒推拉流一小时测试
|
|
||||||
* 标识 -> ID
|
* 标识 -> ID
|
||||||
* 所有字段获取 -> get
|
* 所有字段获取 -> get
|
||||||
|
* 优化JS错误回调 -> platform::error
|
||||||
|
* 反复测试推流拉流、拉人踢人、音频视频控制
|
||||||
|
* 24小时不关闭媒体/一秒一次推拉流十分钟测试/三十秒推拉流一小时测试
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
const os = require("os");
|
const os = require("os");
|
||||||
|
|
||||||
|
// 桃夭媒体服务地址
|
||||||
|
defaultTaoyaoHost = "192.168.1.110";
|
||||||
|
// defaultTaoyaoHost = "192.168.8.110";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置
|
* 配置
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// 服务名称
|
// 服务名称
|
||||||
name: "taoyao-client-media",
|
name: "taoyao-client-media",
|
||||||
// 保存目录
|
|
||||||
storagePath: "/data/storage",
|
|
||||||
// 图片目录
|
|
||||||
storageImagePath: "/data/storage/image",
|
|
||||||
// 视频目录
|
|
||||||
storageVideoPath: "/data/storage/video",
|
|
||||||
// 信令配置
|
// 信令配置
|
||||||
signal: {
|
signal: {
|
||||||
// 服务版本
|
// 服务版本
|
||||||
@@ -33,14 +31,6 @@ module.exports = {
|
|||||||
// 信令密码
|
// 信令密码
|
||||||
password: "taoyao",
|
password: "taoyao",
|
||||||
},
|
},
|
||||||
// 水印
|
|
||||||
watermark: {
|
|
||||||
enabled: false,
|
|
||||||
text: "taoyao",
|
|
||||||
posx: 0,
|
|
||||||
posy: 0,
|
|
||||||
opacity: 1,
|
|
||||||
},
|
|
||||||
// Mediasoup
|
// Mediasoup
|
||||||
mediasoup: {
|
mediasoup: {
|
||||||
// 配置Worker进程数量
|
// 配置Worker进程数量
|
||||||
@@ -126,14 +116,14 @@ module.exports = {
|
|||||||
protocol: "udp",
|
protocol: "udp",
|
||||||
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
||||||
port: 44444,
|
port: 44444,
|
||||||
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || "192.168.1.110",
|
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || defaultTaoyaoHost || "127.0.0.1",
|
||||||
},
|
},
|
||||||
// TCP
|
// TCP
|
||||||
// {
|
// {
|
||||||
// protocol: "tcp",
|
// protocol: "tcp",
|
||||||
// ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
// ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
||||||
// port: 44444,
|
// port: 44444,
|
||||||
// announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || "192.168.1.110",
|
// announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || defaultTaoyaoHost || "127.0.0.1",
|
||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -142,7 +132,7 @@ module.exports = {
|
|||||||
listenIps: [
|
listenIps: [
|
||||||
{
|
{
|
||||||
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
||||||
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || "192.168.1.110",
|
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || defaultTaoyaoHost || "127.0.0.1",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
initialAvailableOutgoingBitrate: 1000000,
|
initialAvailableOutgoingBitrate: 1000000,
|
||||||
@@ -154,7 +144,7 @@ module.exports = {
|
|||||||
plainTransportOptions: {
|
plainTransportOptions: {
|
||||||
listenIp: {
|
listenIp: {
|
||||||
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
ip: process.env.MEDIASOUP_LISTEN_IP || "0.0.0.0",
|
||||||
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || "192.168.1.110",
|
announcedIp: process.env.MEDIASOUP_ANNOUNCED_IP || defaultTaoyaoHost || "127.0.0.1",
|
||||||
},
|
},
|
||||||
maxSctpMessageSize: 262144,
|
maxSctpMessageSize: 262144,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ public interface Constant {
|
|||||||
* IP
|
* IP
|
||||||
*/
|
*/
|
||||||
String IP = "ip";
|
String IP = "ip";
|
||||||
|
/**
|
||||||
|
* 动作
|
||||||
|
*/
|
||||||
|
String ACTIVE = "active";
|
||||||
/**
|
/**
|
||||||
* 状态对象
|
* 状态对象
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
import com.acgist.taoyao.boot.config.MediaProperties;
|
import com.acgist.taoyao.boot.config.MediaProperties;
|
||||||
import com.acgist.taoyao.boot.config.WebrtcProperties;
|
import com.acgist.taoyao.boot.config.WebrtcProperties;
|
||||||
import com.acgist.taoyao.boot.model.Message;
|
import com.acgist.taoyao.boot.model.Message;
|
||||||
|
import com.acgist.taoyao.signal.config.camera.CameraProperties;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
@@ -25,10 +26,12 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
public class ConfigController {
|
public class ConfigController {
|
||||||
|
|
||||||
private final MediaProperties mediaProperties;
|
private final MediaProperties mediaProperties;
|
||||||
|
private final CameraProperties cameraProperties;
|
||||||
private final WebrtcProperties webrtcProperties;
|
private final WebrtcProperties webrtcProperties;
|
||||||
|
|
||||||
public ConfigController(MediaProperties mediaProperties, WebrtcProperties webrtcProperties) {
|
public ConfigController(MediaProperties mediaProperties, CameraProperties cameraProperties, WebrtcProperties webrtcProperties) {
|
||||||
this.mediaProperties = mediaProperties;
|
this.mediaProperties = mediaProperties;
|
||||||
|
this.cameraProperties = cameraProperties;
|
||||||
this.webrtcProperties = webrtcProperties;
|
this.webrtcProperties = webrtcProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +41,13 @@ public class ConfigController {
|
|||||||
public Message media() {
|
public Message media() {
|
||||||
return Message.success(this.mediaProperties);
|
return Message.success(this.mediaProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "摄像头配置", description = "摄像头配置")
|
||||||
|
@GetMapping("/camera")
|
||||||
|
@ApiResponse(content = @Content(schema = @Schema(implementation = CameraProperties.class)))
|
||||||
|
private Message camera() {
|
||||||
|
return Message.success(this.cameraProperties);
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "WebRTC配置", description = "WebRTC配置")
|
@Operation(summary = "WebRTC配置", description = "WebRTC配置")
|
||||||
@GetMapping("/webrtc")
|
@GetMapping("/webrtc")
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.acgist.taoyao.boot.model.Message;
|
import com.acgist.taoyao.boot.model.Message;
|
||||||
|
import com.acgist.taoyao.signal.config.camera.AiProperties;
|
||||||
|
import com.acgist.taoyao.signal.model.control.PtzControl;
|
||||||
|
import com.acgist.taoyao.signal.protocol.control.ControlAiProtocol;
|
||||||
import com.acgist.taoyao.signal.protocol.control.ControlBellProtocol;
|
import com.acgist.taoyao.signal.protocol.control.ControlBellProtocol;
|
||||||
import com.acgist.taoyao.signal.protocol.control.ControlPhotographProtocol;
|
import com.acgist.taoyao.signal.protocol.control.ControlPhotographProtocol;
|
||||||
import com.acgist.taoyao.signal.protocol.control.ControlPtzProtocol;
|
import com.acgist.taoyao.signal.protocol.control.ControlPtzProtocol;
|
||||||
@@ -14,6 +17,7 @@ import com.acgist.taoyao.signal.protocol.control.ControlRecordProtocol;
|
|||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,53 +31,54 @@ import jakarta.validation.constraints.NotNull;
|
|||||||
@RequestMapping("/control")
|
@RequestMapping("/control")
|
||||||
public class ControlController {
|
public class ControlController {
|
||||||
|
|
||||||
|
private final ControlAiProtocol controlAiProtocol;
|
||||||
private final ControlPtzProtocol controlPtzProtocol;
|
private final ControlPtzProtocol controlPtzProtocol;
|
||||||
private final ControlBellProtocol controlBellProtocol;
|
private final ControlBellProtocol controlBellProtocol;
|
||||||
private final ControlRecordProtocol controlRecordProtocol;
|
private final ControlRecordProtocol controlRecordProtocol;
|
||||||
private final ControlPhotographProtocol controlPhotographProtocol;
|
private final ControlPhotographProtocol controlPhotographProtocol;
|
||||||
|
|
||||||
public ControlController(
|
public ControlController(
|
||||||
|
ControlAiProtocol controlAiProtocol,
|
||||||
ControlPtzProtocol controlPtzProtocol,
|
ControlPtzProtocol controlPtzProtocol,
|
||||||
ControlBellProtocol controlBellProtocol,
|
ControlBellProtocol controlBellProtocol,
|
||||||
ControlRecordProtocol controlRecordProtocol,
|
ControlRecordProtocol controlRecordProtocol,
|
||||||
ControlPhotographProtocol controlPhotographProtocol
|
ControlPhotographProtocol controlPhotographProtocol
|
||||||
) {
|
) {
|
||||||
|
this.controlAiProtocol = controlAiProtocol;
|
||||||
this.controlPtzProtocol = controlPtzProtocol;
|
this.controlPtzProtocol = controlPtzProtocol;
|
||||||
this.controlBellProtocol = controlBellProtocol;
|
this.controlBellProtocol = controlBellProtocol;
|
||||||
this.controlRecordProtocol = controlRecordProtocol;
|
this.controlRecordProtocol = controlRecordProtocol;
|
||||||
this.controlPhotographProtocol = controlPhotographProtocol;
|
this.controlPhotographProtocol = controlPhotographProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "AI识别", description = "AI识别")
|
||||||
|
@GetMapping("/ai/{clientId}")
|
||||||
|
public Message ai(@PathVariable String clientId, @Valid AiProperties aiProperties) {
|
||||||
|
return Message.success(this.controlAiProtocol.execute(clientId, aiProperties));
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "PTZ", description = "PTZ")
|
@Operation(summary = "PTZ", description = "PTZ")
|
||||||
@GetMapping("/ptz/{clientId}")
|
@GetMapping("/ptz/{clientId}")
|
||||||
public Message ptz(
|
public Message ptz(@PathVariable String clientId, @Valid PtzControl ptzControl) {
|
||||||
@NotNull(message = "PTZ类型不能为空") ControlPtzProtocol.Type type,
|
return Message.success(this.controlPtzProtocol.execute(clientId, ptzControl));
|
||||||
@NotNull(message = "PTZ参数不能为空") Double value,
|
|
||||||
@PathVariable String clientId
|
|
||||||
) {
|
|
||||||
this.controlPtzProtocol.execute(type, value, clientId);
|
|
||||||
return Message.success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "响铃", description = "响铃")
|
@Operation(summary = "响铃", description = "响铃")
|
||||||
@GetMapping("/bell/{clientId}")
|
@GetMapping("/bell/{clientId}")
|
||||||
public Message bell(@PathVariable String clientId) {
|
public Message bell(@PathVariable String clientId, @NotNull(message = "没有指定操作") Boolean active) {
|
||||||
this.controlBellProtocol.execute(clientId);
|
return Message.success(this.controlBellProtocol.execute(clientId, active));
|
||||||
return Message.success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "录像", description = "录像")
|
@Operation(summary = "录像", description = "录像")
|
||||||
@GetMapping("/record/{clientId}")
|
@GetMapping("/record/{clientId}")
|
||||||
public Message record(@PathVariable String clientId) {
|
public Message record(@PathVariable String clientId, @NotNull(message = "没有指定操作") Boolean active) {
|
||||||
this.controlRecordProtocol.execute(clientId);
|
return Message.success(this.controlRecordProtocol.execute(clientId, active));
|
||||||
return Message.success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "拍照", description = "拍照")
|
@Operation(summary = "拍照", description = "拍照")
|
||||||
@GetMapping("/photograph/{clientId}")
|
@GetMapping("/photograph/{clientId}")
|
||||||
public Message photograph(@PathVariable String clientId) {
|
public Message photograph(@PathVariable String clientId) {
|
||||||
this.controlPhotographProtocol.execute(clientId);
|
return Message.success(this.controlPhotographProtocol.execute(clientId));
|
||||||
return Message.success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,6 +158,35 @@ taoyao:
|
|||||||
port: 3478
|
port: 3478
|
||||||
username: taoyao
|
username: taoyao
|
||||||
password: taoyao
|
password: taoyao
|
||||||
|
# 摄像头配置
|
||||||
|
camera:
|
||||||
|
# 混音
|
||||||
|
audio-mixer: false
|
||||||
|
# 变声
|
||||||
|
audio-changer: false
|
||||||
|
# 降噪
|
||||||
|
audio-denoise: true
|
||||||
|
# 存储目录
|
||||||
|
storage-path: /data/taoyao/storage
|
||||||
|
# 图片存储目录
|
||||||
|
storage-image-path: /data/taoyao/storage/image
|
||||||
|
# 视频存储目录
|
||||||
|
storage-video-path: /data/taoyao/storage/video
|
||||||
|
# AI识别
|
||||||
|
ai:
|
||||||
|
enabled: false
|
||||||
|
type: PERSON
|
||||||
|
# 美颜
|
||||||
|
beauty:
|
||||||
|
enabled: false
|
||||||
|
level: 10
|
||||||
|
# 水印
|
||||||
|
watermark:
|
||||||
|
enabled: false
|
||||||
|
text: taoyao
|
||||||
|
posx: 10
|
||||||
|
posy: 10
|
||||||
|
opacity: 0.8
|
||||||
# 安全配置
|
# 安全配置
|
||||||
security:
|
security:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.acgist.taoyao.signal.config.camera;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI识别配置
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(title = "AI识别配置", description = "AI识别配置")
|
||||||
|
public class AiProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 识别类型
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
|
||||||
|
// 人
|
||||||
|
PERSON;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schema(title = "是否开启", description = "是否开启")
|
||||||
|
@NotNull(message = "没有指定操作")
|
||||||
|
private Boolean enabled;
|
||||||
|
@Schema(title = "识别类型", description = "识别类型")
|
||||||
|
@NotNull(message = "无效识别类型")
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.acgist.taoyao.signal.config.camera;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 美颜配置
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(title = "美颜配置", description = "美颜配置")
|
||||||
|
public class BeautyProperties {
|
||||||
|
|
||||||
|
@Schema(title = "是否开启", description = "是否开启")
|
||||||
|
private Boolean enabled;
|
||||||
|
@Schema(title = "美颜级别", description = "美颜级别")
|
||||||
|
private Integer level;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.acgist.taoyao.signal.config.camera;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 摄像头配置
|
||||||
|
*
|
||||||
|
* 音频:
|
||||||
|
* 混音:不用混音
|
||||||
|
* 变声:
|
||||||
|
* 降噪:
|
||||||
|
*
|
||||||
|
* 视频:
|
||||||
|
* 录制:
|
||||||
|
* 水印:
|
||||||
|
* 美颜:
|
||||||
|
* AI识别:
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(title = "摄像头配置", description = "摄像头配置")
|
||||||
|
@ConfigurationProperties(prefix = "taoyao.camera")
|
||||||
|
public class CameraProperties {
|
||||||
|
|
||||||
|
@Schema(title = "混音", description = "混音")
|
||||||
|
private Boolean audioMixer = Boolean.FALSE;
|
||||||
|
@Schema(title = "变声", description = "变声")
|
||||||
|
private Boolean audioChanger;
|
||||||
|
@Schema(title = "降噪", description = "降噪")
|
||||||
|
private Boolean audioDenoise;
|
||||||
|
@Schema(title = "存储目录", description = "存储目录")
|
||||||
|
private String storagePath;
|
||||||
|
@Schema(title = "图片存储目录", description = "图片存储目录")
|
||||||
|
private String storageImagePath;
|
||||||
|
@Schema(title = "视频存储目录", description = "视频存储目录")
|
||||||
|
private String storageVideoPath;
|
||||||
|
@Schema(title = "AI识别配置", description = "AI识别配置")
|
||||||
|
private AiProperties ai;
|
||||||
|
@Schema(title = "美颜配置", description = "美颜配置")
|
||||||
|
private BeautyProperties beauty;
|
||||||
|
@Schema(title = "水印配置", description = "水印配置")
|
||||||
|
private WatermarkProperties watermark;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.acgist.taoyao.signal.config.camera;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 水印配置
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(title = "水印配置", description = "水印配置")
|
||||||
|
public class WatermarkProperties {
|
||||||
|
|
||||||
|
@Schema(title = "是否开启", description = "是否开启")
|
||||||
|
private Boolean enabled;
|
||||||
|
@Schema(title = "水印内容", description = "水印内容")
|
||||||
|
private String text;
|
||||||
|
@Schema(title = "X坐标", description = "X坐标")
|
||||||
|
private Integer posx;
|
||||||
|
@Schema(title = "Y坐标", description = "Y坐标")
|
||||||
|
private Integer posy;
|
||||||
|
@Schema(title = "透明度", description = "透明度")
|
||||||
|
private Double opacity;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,10 +3,12 @@ package com.acgist.taoyao.signal.configuration;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
import com.acgist.taoyao.boot.runner.OrderedCommandLineRunner;
|
import com.acgist.taoyao.boot.runner.OrderedCommandLineRunner;
|
||||||
|
import com.acgist.taoyao.signal.config.camera.CameraProperties;
|
||||||
import com.acgist.taoyao.signal.event.EventPublisher;
|
import com.acgist.taoyao.signal.event.EventPublisher;
|
||||||
import com.acgist.taoyao.signal.protocol.ProtocolManager;
|
import com.acgist.taoyao.signal.protocol.ProtocolManager;
|
||||||
|
|
||||||
@@ -18,6 +20,9 @@ import jakarta.annotation.PostConstruct;
|
|||||||
* @author acgist
|
* @author acgist
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
|
@EnableConfigurationProperties({
|
||||||
|
CameraProperties.class
|
||||||
|
})
|
||||||
public class SignalAutoConfiguration {
|
public class SignalAutoConfiguration {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.acgist.taoyao.signal.model.control;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PTZ控制参数
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
@Schema(title = "PTZ控制参数", description = "PTZ控制参数")
|
||||||
|
public class PtzControl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PTZ类型
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
|
||||||
|
// 水平
|
||||||
|
PAN,
|
||||||
|
// 垂直
|
||||||
|
TILT,
|
||||||
|
// 变焦
|
||||||
|
ZOOM;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schema(title = "PTZ类型", description = "PTZ类型")
|
||||||
|
@NotNull(message = "PTZ类型不能为空")
|
||||||
|
private Type type;
|
||||||
|
@Schema(title = "PTZ参数", description = "PTZ参数")
|
||||||
|
@NotNull(message = "PTZ参数不能为空")
|
||||||
|
private Double value;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -43,5 +43,22 @@ public class ProtocolControlAdapter extends ProtocolClientAdapter {
|
|||||||
*/
|
*/
|
||||||
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求终端执行控制信令
|
||||||
|
*
|
||||||
|
* @param clientId 终端ID
|
||||||
|
* @param request 请求
|
||||||
|
*
|
||||||
|
* @return 响应
|
||||||
|
*/
|
||||||
|
protected Message request(String clientId, Message request) {
|
||||||
|
final Client client = this.clientManager.clients(clientId);
|
||||||
|
if(client == null) {
|
||||||
|
return Message.fail("无效终端:" + clientId);
|
||||||
|
} else {
|
||||||
|
return client.request(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.acgist.taoyao.signal.protocol.control;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import com.acgist.taoyao.signal.client.ClientType;
|
||||||
|
import com.acgist.taoyao.signal.config.camera.AiProperties;
|
||||||
|
import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开AI识别信令
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
@Protocol
|
||||||
|
@Description(
|
||||||
|
body = """
|
||||||
|
{
|
||||||
|
"to": "目标终端ID",
|
||||||
|
...AiProperties
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
flow = {
|
||||||
|
"信令服务->终端",
|
||||||
|
"终端=>信令服务->终端"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public class ControlAiProtocol extends ProtocolControlAdapter {
|
||||||
|
|
||||||
|
public static final String SIGNAL = "control::ai";
|
||||||
|
|
||||||
|
public ControlAiProtocol() {
|
||||||
|
super("打开AI识别信令", SIGNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
||||||
|
client.push(targetClient.request(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param clientId 终端标识
|
||||||
|
* @param aiProperties AI识别配置
|
||||||
|
*
|
||||||
|
* @return 执行结果
|
||||||
|
*/
|
||||||
|
public Message execute(String clientId, AiProperties aiProperties) {
|
||||||
|
return this.request(clientId, this.build(aiProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.acgist.taoyao.signal.protocol.control;
|
||||||
|
|
||||||
|
import com.acgist.taoyao.boot.annotation.Description;
|
||||||
|
import com.acgist.taoyao.boot.annotation.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开美颜信令
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
@Protocol
|
||||||
|
@Description(
|
||||||
|
)
|
||||||
|
public class ControlBeautyProtocol {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import com.acgist.taoyao.boot.annotation.Description;
|
import com.acgist.taoyao.boot.annotation.Description;
|
||||||
import com.acgist.taoyao.boot.annotation.Protocol;
|
import com.acgist.taoyao.boot.annotation.Protocol;
|
||||||
|
import com.acgist.taoyao.boot.config.Constant;
|
||||||
import com.acgist.taoyao.boot.model.Message;
|
import com.acgist.taoyao.boot.model.Message;
|
||||||
import com.acgist.taoyao.signal.client.Client;
|
import com.acgist.taoyao.signal.client.Client;
|
||||||
import com.acgist.taoyao.signal.client.ClientType;
|
import com.acgist.taoyao.signal.client.ClientType;
|
||||||
@@ -18,7 +19,8 @@ import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
|||||||
@Description(
|
@Description(
|
||||||
body = """
|
body = """
|
||||||
{
|
{
|
||||||
"to": "目标终端ID"
|
"to": "目标终端ID",
|
||||||
|
"active": 是否响铃(true|false)
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
flow = {
|
flow = {
|
||||||
@@ -36,14 +38,17 @@ public class ControlBellProtocol extends ProtocolControlAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
||||||
targetClient.push(message);
|
client.push(targetClient.request(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clientId 终端ID
|
* @param clientId 终端ID
|
||||||
|
* @param active 操作
|
||||||
|
*
|
||||||
|
* @return 执行结果
|
||||||
*/
|
*/
|
||||||
public void execute(String clientId) {
|
public Message execute(String clientId, Boolean active) {
|
||||||
this.clientManager.unicast(clientId, this.build());
|
return this.request(clientId, this.build(Map.of(Constant.ACTIVE, active)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.acgist.taoyao.signal.protocol.control;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置音频
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
public class ControlConfigAudioProtocol {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.acgist.taoyao.signal.protocol.control;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置视频
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
public class ControlConfigVideoProtocol {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -36,14 +36,16 @@ public class ControlPhotographProtocol extends ProtocolControlAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
||||||
targetClient.push(message);
|
client.push(targetClient.request(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clientId 终端标识
|
* @param clientId 终端标识
|
||||||
|
*
|
||||||
|
* @return 执行结果
|
||||||
*/
|
*/
|
||||||
public void execute(String clientId) {
|
public Message execute(String clientId) {
|
||||||
this.clientManager.unicast(clientId, this.build());
|
return this.request(clientId, this.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.acgist.taoyao.boot.annotation.Protocol;
|
|||||||
import com.acgist.taoyao.boot.model.Message;
|
import com.acgist.taoyao.boot.model.Message;
|
||||||
import com.acgist.taoyao.signal.client.Client;
|
import com.acgist.taoyao.signal.client.Client;
|
||||||
import com.acgist.taoyao.signal.client.ClientType;
|
import com.acgist.taoyao.signal.client.ClientType;
|
||||||
|
import com.acgist.taoyao.signal.model.control.PtzControl;
|
||||||
import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,8 +20,7 @@ import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
|||||||
body = """
|
body = """
|
||||||
{
|
{
|
||||||
"to": "目标终端ID",
|
"to": "目标终端ID",
|
||||||
"type": "PTZ类型(PAN|TILT|ZOOM)",
|
...PtzControl
|
||||||
"value": PTZ参数
|
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
flow = {
|
flow = {
|
||||||
@@ -35,35 +35,20 @@ public class ControlPtzProtocol extends ProtocolControlAdapter {
|
|||||||
public ControlPtzProtocol() {
|
public ControlPtzProtocol() {
|
||||||
super("PTZ信令", SIGNAL);
|
super("PTZ信令", SIGNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* PTZ类型
|
|
||||||
*
|
|
||||||
* @author acgist
|
|
||||||
*/
|
|
||||||
public enum Type {
|
|
||||||
|
|
||||||
// 水平
|
|
||||||
PAN,
|
|
||||||
// 垂直
|
|
||||||
TILT,
|
|
||||||
// 变焦
|
|
||||||
ZOOM;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
||||||
targetClient.push(message);
|
client.push(targetClient.request(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param type PTZ类型
|
|
||||||
* @param value PTZ参数
|
|
||||||
* @param clientId 终端标识
|
* @param clientId 终端标识
|
||||||
|
* @param ptzControl PTZ控制参数
|
||||||
|
*
|
||||||
|
* @return 执行结果
|
||||||
*/
|
*/
|
||||||
public void execute(Type type, Double value, String clientId) {
|
public Message execute(String clientId, PtzControl ptzControl) {
|
||||||
this.clientManager.unicast(clientId, this.build(Map.of(type, value)));
|
return this.request(clientId, this.build(ptzControl));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import com.acgist.taoyao.boot.annotation.Description;
|
import com.acgist.taoyao.boot.annotation.Description;
|
||||||
import com.acgist.taoyao.boot.annotation.Protocol;
|
import com.acgist.taoyao.boot.annotation.Protocol;
|
||||||
|
import com.acgist.taoyao.boot.config.Constant;
|
||||||
import com.acgist.taoyao.boot.model.Message;
|
import com.acgist.taoyao.boot.model.Message;
|
||||||
import com.acgist.taoyao.signal.client.Client;
|
import com.acgist.taoyao.signal.client.Client;
|
||||||
import com.acgist.taoyao.signal.client.ClientType;
|
import com.acgist.taoyao.signal.client.ClientType;
|
||||||
@@ -16,15 +17,15 @@ import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
|||||||
*/
|
*/
|
||||||
@Protocol
|
@Protocol
|
||||||
@Description(
|
@Description(
|
||||||
memo = "状态通过心跳回传",
|
|
||||||
body = """
|
body = """
|
||||||
{
|
{
|
||||||
"to": "目标终端ID"
|
"to": "目标终端ID",
|
||||||
|
"active": 是否录像(true|false)
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
flow = {
|
flow = {
|
||||||
"信令服务->终端",
|
"信令服务->终端",
|
||||||
"终端->信令服务->终端"
|
"终端=>信令服务->终端"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
public class ControlRecordProtocol extends ProtocolControlAdapter {
|
public class ControlRecordProtocol extends ProtocolControlAdapter {
|
||||||
@@ -37,14 +38,17 @@ public class ControlRecordProtocol extends ProtocolControlAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
public void execute(String clientId, ClientType clientType, Client client, Client targetClient, Message message, Map<String, Object> body) {
|
||||||
targetClient.push(message);
|
client.push(targetClient.request(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clientId 终端标识
|
* @param clientId 终端标识
|
||||||
|
* @param active 操作
|
||||||
|
*
|
||||||
|
* @return 执行结果
|
||||||
*/
|
*/
|
||||||
public void execute(String clientId) {
|
public Message execute(String clientId, Boolean active) {
|
||||||
this.clientManager.unicast(clientId, this.build());
|
return this.request(clientId, this.build(Map.of(Constant.ACTIVE, active)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.acgist.taoyao.signal.protocol.control;
|
||||||
|
|
||||||
|
import com.acgist.taoyao.boot.annotation.Description;
|
||||||
|
import com.acgist.taoyao.boot.annotation.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开水印信令
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
@Protocol
|
||||||
|
@Description(
|
||||||
|
)
|
||||||
|
public class ControlWatermarkProtocol {
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user