From 87256bcfbdc7c7da77fc6042d18321f83a5799ac Mon Sep 17 00:00:00 2001 From: acgist <289547414@qq.com> Date: Thu, 8 Jun 2023 15:45:33 +0800 Subject: [PATCH] =?UTF-8?q?[*]=20=E9=BB=98=E8=AE=A4=E5=80=BC=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/TODO.md | 4 +- taoyao-client-media/src/Taoyao.js | 2 +- .../taoyao/boot/config/FfmpegProperties.java | 32 +++++------ .../src/main/resources/application-dev.yml | 2 - .../src/main/resources/application.yml | 53 ++++++++++--------- .../java/com/acgist/taoyao/RecorderTest.java | 14 ++--- .../taoyao/signal/party/media/Recorder.java | 17 ++---- .../control/ControlServerRecordProtocol.java | 7 +-- 8 files changed, 58 insertions(+), 73 deletions(-) diff --git a/docs/TODO.md b/docs/TODO.md index 53ec7a9..347d8aa 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -30,6 +30,7 @@ ## 计划任务 +* E2E * 发布版本:1.0.0 * 开机自启 * 录像底噪 @@ -38,11 +39,12 @@ * 分辨率调整 * 服务端录像 * 安卓预览按钮 -* 安装内存抖动 +* 安卓内存抖动 * 降低视频录像大小 * 防止重复邀请拉取 * 码率等等参数配置验证 * 查询消费者生产者信息 +* 存在TURN服务优先使用 * 浏览器WebRTC监控页面关闭:`chrome://webrtc-internals/` ## 完成任务 diff --git a/taoyao-client-media/src/Taoyao.js b/taoyao-client-media/src/Taoyao.js index a1a04c7..278c1d3 100644 --- a/taoyao-client-media/src/Taoyao.js +++ b/taoyao-client-media/src/Taoyao.js @@ -908,7 +908,7 @@ class Taoyao { console.warn("请求录像关键帧视频关闭", filepath); return; } - // 文件开始录像同时已经开始生产数据 + // 判断文件大小验证是否已经开始录制:创建文件 -> 视频信息 -> 视频数据 -> 封装视频 if(fs.existsSync(filepath) && fs.statSync(filepath).size >= 128 * 1024) { console.debug("请求录像关键帧已经开始录像", filepath); return; diff --git a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/FfmpegProperties.java b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/FfmpegProperties.java index 0d06e1c..20cfaf6 100644 --- a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/FfmpegProperties.java +++ b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/config/FfmpegProperties.java @@ -17,29 +17,31 @@ import lombok.Setter; @ConfigurationProperties(prefix = "taoyao.ffmpeg") public class FfmpegProperties { - @Schema(title = "SDP模板", description = "SDP模板") - private String sdp; - @Schema(title = "媒体录像", description = "媒体录像") + @Schema(title = "录像地址", description = "录像地址") + private String host; + @Schema(title = "最小端口", description = "最小端口") + private Integer minPort; + @Schema(title = "最大端口", description = "最大端口") + private Integer maxPort; + @Schema(title = "录像帧率", description = "录像帧率") + private Integer frameRate; + @Schema(title = "录像命令", description = "录像命令") private String record; - @Schema(title = "预览截图", description = "预览截图") + @Schema(title = "预览命令", description = "预览命令") private String preview; - @Schema(title = "视频时长", description = "视频时长") + @Schema(title = "时长命令", description = "时长命令") private String duration; + @Schema(title = "录像SDP", description = "录像SDP") + private String recordSdp; + @Schema(title = "预览时间", description = "预览时间") + private Integer previewTime; + @Schema(title = "时长提取", description = "时长提取") + private String durationRegex; @Schema(title = "存储目录", description = "存储目录") private String storagePath; @Schema(title = "图片存储目录", description = "图片存储目录") private String storageImagePath; @Schema(title = "视频存储目录", description = "视频存储目录") private String storageVideoPath; - @Schema(title = "预览截图时间", description = "预览截图时间") - private Integer previewTime; - @Schema(title = "预览截图时间", description = "预览截图时间") - private String durationRegex; - @Schema(title = "录像录像地址", description = "录像录像地址") - private String host; - @Schema(title = "录像最小端口", description = "录像最小端口") - private Integer minPort; - @Schema(title = "录像最大端口", description = "录像最大端口") - private Integer maxPort; } diff --git a/taoyao-signal-server/taoyao-server/src/main/resources/application-dev.yml b/taoyao-signal-server/taoyao-server/src/main/resources/application-dev.yml index 6f8d844..d39c503 100644 --- a/taoyao-signal-server/taoyao-server/src/main/resources/application-dev.yml +++ b/taoyao-signal-server/taoyao-server/src/main/resources/application-dev.yml @@ -7,8 +7,6 @@ server: key-store-password: 123456 key-password: 123456 taoyao: - ffmpeg: - host: 192.168.8.93 security: permit: - / diff --git a/taoyao-signal-server/taoyao-server/src/main/resources/application.yml b/taoyao-signal-server/taoyao-server/src/main/resources/application.yml index 71cac1c..c2f3fbd 100644 --- a/taoyao-signal-server/taoyao-server/src/main/resources/application.yml +++ b/taoyao-signal-server/taoyao-server/src/main/resources/application.yml @@ -71,9 +71,9 @@ taoyao: min-video-bitrate: 800 max-video-bitrate: 1600 # 音频配置 - # 采样位数 - min-sample-size: 8 - max-sample-size: 32 + # 采样位数(位深) + min-sample-size: 16 + max-sample-size: 16 # 采样率 min-sample-rate: 8000 max-sample-rate: 48000 @@ -85,8 +85,8 @@ taoyao: audio: format: OPUS bitrate: 96 - sample-size: 32 - sample-rate: 44100 + sample-size: 16 + sample-rate: 48000 # 默认视频 video: format: H264 @@ -99,26 +99,26 @@ taoyao: fd-audio: format: OPUS bitrate: 256 - sample-size: 32 + sample-size: 16 sample-rate: 48000 # 高清 hd-audio: format: OPUS bitrate: 128 - sample-size: 24 + sample-size: 16 sample-rate: 32000 # 标清 sd-audio: format: OPUS bitrate: 96 - sample-size: 24 + sample-size: 16 sample-rate: 16000 # 视频质量 videos: # 4K:UD=UHD=4K ud-video: format: H264 - bitrate: 1600 + bitrate: 1800 frame-rate: 45 resolution: 4096*2160 # 2K:QD=QHD=2K @@ -147,8 +147,22 @@ taoyao: resolution: 720*480 # FFmpeg配置 ffmpeg: + # 录像地址 + host: 127.0.0.1 + # 最小端口 + min-port: 50000 + # 最大端口 + max-port: 59999 + # 录像帧率 + frame-rate: ${taoyao.media.video.frame-rate:24} + # 录像命令 + record: ffmpeg -y -protocol_whitelist "file,rtp,udp" -thread_queue_size 1024 -c:a libopus -c:v libvpx -r:v %d -i %s -c:a aac -c:v h264 %s + # 预览命令 + preview: ffmpeg -y -i %s -ss %d -vframes 1 -f image2 %s + # 时长命令 + duration: ffprobe -i %s -show_entries format=duration # 录像SDP:VP8 | H264 - sdp: | + record-sdp: | v=0 o=- 0 0 IN IP4 127.0.0.1 s=TaoyaoRecord @@ -163,27 +177,16 @@ taoyao: a=rtcp:%d a=rtpmap:101 VP8/90000 a=recvonly - # 录像命令 - record: ffmpeg -y -protocol_whitelist "file,rtp,udp" -thread_queue_size 1024 -c:a libopus -c:v libvpx -r:v %d -i %s -c:a aac -c:v h264 %s - # 预览命令 - preview: ffmpeg -y -i %s -ss %d -vframes 1 -f image2 %s - # 时长命令 - duration: ffprobe -i %s -show_entries format=duration + # 预览时间 + preview-time: 4 + # 时长提取 + duration-regex: .*duration\=([0-9\.]+).* # 存储目录 storage-path: /data/taoyao/storage # 图片存储目录 storage-image-path: /data/taoyao/storage/image # 视频存储目录 storage-video-path: /data/taoyao/storage/video - # 预览时间 - preview-time: 4 - # 时长提取 - duration-regex: .*duration\=([0-9\.]+).* - # 录像地址 - host: 127.0.0.1 - # 端口范围 - min-port: 50000 - max-port: 59999 # Socket信令 socket: enabled: true diff --git a/taoyao-signal-server/taoyao-server/src/test/java/com/acgist/taoyao/RecorderTest.java b/taoyao-signal-server/taoyao-server/src/test/java/com/acgist/taoyao/RecorderTest.java index 05c6ce8..08b913b 100644 --- a/taoyao-signal-server/taoyao-server/src/test/java/com/acgist/taoyao/RecorderTest.java +++ b/taoyao-signal-server/taoyao-server/src/test/java/com/acgist/taoyao/RecorderTest.java @@ -3,8 +3,6 @@ package com.acgist.taoyao; import org.junit.jupiter.api.Test; import com.acgist.taoyao.boot.config.FfmpegProperties; -import com.acgist.taoyao.boot.config.MediaProperties; -import com.acgist.taoyao.boot.config.MediaVideoProperties; import com.acgist.taoyao.signal.party.media.Recorder; public class RecorderTest { @@ -12,11 +10,10 @@ public class RecorderTest { @Test public void testStart() throws InterruptedException { final FfmpegProperties ffmpegProperties = new FfmpegProperties(); - ffmpegProperties.setStorageVideoPath("D:\\tmp\\video"); + ffmpegProperties.setHost("127.0.0.1"); ffmpegProperties.setMinPort(50000); ffmpegProperties.setMaxPort(59999); - ffmpegProperties.setHost("127.0.0.1"); - ffmpegProperties.setSdp(""" + ffmpegProperties.setRecordSdp(""" v=0 o=- 0 0 IN IP4 127.0.0.1 s=TaoyaoRecord @@ -36,11 +33,8 @@ public class RecorderTest { ffmpegProperties.setRecord("ffmpeg -y -protocol_whitelist \"file,rtp,udp\" -thread_queue_size 1024 -c:a libopus -c:v libvpx -r:v %d -i %s -c:a aac -c:v h264 %s"); ffmpegProperties.setPreview("ffmpeg -y -i %s -ss %d -vframes 1 -f image2 %s"); ffmpegProperties.setDuration("ffprobe -i %s -show_entries format=duration"); - final MediaProperties mediaProperties = new MediaProperties(); - final MediaVideoProperties mediaVideoProperties = new MediaVideoProperties(); - mediaVideoProperties.setFrameRate(24); - mediaProperties.setVideo(mediaVideoProperties); - final Recorder recorder = new Recorder("taoyao", null, null, mediaProperties, ffmpegProperties); + ffmpegProperties.setStorageVideoPath("D:\\tmp\\video"); + final Recorder recorder = new Recorder("taoyao", null, null, ffmpegProperties); recorder.start(); Thread.sleep(20 * 1000); recorder.stop(); diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/Recorder.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/Recorder.java index a08caf3..9ef6249 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/Recorder.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/party/media/Recorder.java @@ -11,8 +11,6 @@ import java.util.regex.Pattern; import org.apache.commons.lang3.math.NumberUtils; import com.acgist.taoyao.boot.config.FfmpegProperties; -import com.acgist.taoyao.boot.config.MediaProperties; -import com.acgist.taoyao.boot.config.MediaVideoProperties; import com.acgist.taoyao.boot.utils.FileUtils; import com.acgist.taoyao.boot.utils.NetUtils; import com.acgist.taoyao.boot.utils.ScriptUtils; @@ -130,10 +128,6 @@ public class Recorder { * 文件路径 */ private final String filepath; - /** - * 媒体配置 - */ - private final MediaProperties mediaProperties; /** * FFmpeg配置 */ @@ -146,10 +140,7 @@ public class Recorder { * @param mediaProperties 媒体配置 * @param ffmpegProperties FFmpeg配置 */ - public Recorder( - String name, Room room, ClientWrapper clientWrapper, - MediaProperties mediaProperties, FfmpegProperties ffmpegProperties - ) { + public Recorder(String name, Room room, ClientWrapper clientWrapper, FfmpegProperties ffmpegProperties) { this.close = false; this.running = false; this.room = room; @@ -158,7 +149,6 @@ public class Recorder { this.preview = Paths.get(this.folder, "taoyao.jpg").toAbsolutePath().toString(); this.filepath = Paths.get(this.folder, "taoyao.mp4").toAbsolutePath().toString(); this.clientWrapper = clientWrapper; - this.mediaProperties = mediaProperties; this.ffmpegProperties = ffmpegProperties; FileUtils.mkdirs(this.folder); } @@ -185,10 +175,9 @@ public class Recorder { * 录制视频 */ private void record() { - final MediaVideoProperties mediaVideoProperties = this.mediaProperties.getVideo(); final String recordScript = String.format( this.ffmpegProperties.getRecord(), - mediaVideoProperties.getFrameRate(), + this.ffmpegProperties.getFrameRate(), this.sdpfile, this.filepath ); @@ -219,7 +208,7 @@ public class Recorder { this.videoPort = NetUtils.scanPort(this.audioPort + 2, maxPort); this.videoRtcpPort = NetUtils.scanPort(this.audioPort + 3, maxPort); final String sdp = String.format( - this.ffmpegProperties.getSdp(), + this.ffmpegProperties.getRecordSdp(), this.audioPort, this.audioRtcpPort, this.videoPort, diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/control/ControlServerRecordProtocol.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/control/ControlServerRecordProtocol.java index 1511bd1..6013ea2 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/control/ControlServerRecordProtocol.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/protocol/control/ControlServerRecordProtocol.java @@ -10,7 +10,6 @@ import com.acgist.taoyao.boot.annotation.Description; import com.acgist.taoyao.boot.annotation.Protocol; import com.acgist.taoyao.boot.config.Constant; import com.acgist.taoyao.boot.config.FfmpegProperties; -import com.acgist.taoyao.boot.config.MediaProperties; import com.acgist.taoyao.boot.model.Message; import com.acgist.taoyao.boot.utils.MapUtils; import com.acgist.taoyao.signal.client.Client; @@ -51,12 +50,10 @@ public class ControlServerRecordProtocol extends ProtocolControlAdapter implemen public static final String SIGNAL = "control::server::record"; - private final MediaProperties mediaProperties; private final FfmpegProperties ffmpegProperties; - public ControlServerRecordProtocol(MediaProperties mediaProperties, FfmpegProperties ffmpegProperties) { + public ControlServerRecordProtocol(FfmpegProperties ffmpegProperties) { super("服务端录像信令", SIGNAL); - this.mediaProperties = mediaProperties; this.ffmpegProperties = ffmpegProperties; } @@ -122,7 +119,7 @@ public class ControlServerRecordProtocol extends ProtocolControlAdapter implemen } final String name = UUID.randomUUID().toString(); // 打开录制线程 - final Recorder recorder = new Recorder(name, room, clientWrapper, this.mediaProperties, this.ffmpegProperties); + final Recorder recorder = new Recorder(name, room, clientWrapper, this.ffmpegProperties); recorder.start(); clientWrapper.setRecorder(recorder); // 打开媒体录制