Fix RTSP clock pacing at 20 fps

This commit is contained in:
seo-amugae committed 2026-10-08 11:46:16 +09:00
1 parent 5241194b9a
commit 6c91d4f372
3 files changed
+130 -40

No files matched your search

+18 -4
View File
@@ -28,7 +28,7 @@ RTSP는 `ddagrab` 기반 Desktop Duplication API로 화면과 마우스 커서
- DirectShow 마이크와 시스템 재생음을 `amix`로 혼합하고 `asplit`으로 모든 채널에 분배
- 하나의 FFmpeg가 모든 DDA 입력과 RTSP 출력을 함께 처리
- 기본 출력·입력 장치, 선택 장치, 오디오 포맷 변경 시 전체 채널 재시작
- 기본 30fps, 영상 8Mbps, AAC 오디오 192kbps
- 기본 20fps, GOP 2초(40프레임), 영상 8Mbps, AAC 오디오 192kbps
- NIC Link, IPv4, `ifIndex`, IP 변경 감지
- 선택적 Source IP 고정 ping 상태 검사
- 3초간 정상 상태가 유지된 뒤 전체 채널 시작
@@ -108,7 +108,8 @@ GPU 이름과 드라이버, NVENC API, AMF/QSV 시험 결과, 선택 인코더,
```ini
[Video]
FrameRate=30
FrameRate=20
GopSeconds=2
Bitrate=8000k
EncoderPriority=NVIDIA,AMD,Intel
@@ -130,7 +131,8 @@ SignalThreshold=0.0005
| `General` | `ChannelCount` | `2` | 송출 채널과 필요한 모니터 수 |
| `General` | `StableTimeSec` | `3` | 정상 상태 안정화 시간 |
| `General` | `PollIntervalSec` | `1` | 상태 확인 주기 |
| `Video` | `FrameRate` | `30` | 화면 프레임률 |
| `Video` | `FrameRate` | `20` | 화면 캡처 및 RTSP 영상 프레임률 |
| `Video` | `GopSeconds` | `2` | IDR/GOP 간격. 기본값은 20fps에서 40프레임 |
| `Video` | `Bitrate` | `8000k` | 채널별 영상 비트레이트 |
| `Video` | `EncoderPriority` | `NVIDIA,AMD,Intel` | GPU 선택 순서 |
| `Audio` | `Enabled` | `1` | 시스템 재생음과 AAC 트랙 사용 여부 |
@@ -152,6 +154,18 @@ SignalThreshold=0.0005
| `Dependencies` | `MediaMTXUrl` | v1.21.1 공식 ZIP | MediaMTX Windows amd64 ZIP 주소 |
| `Dependencies` | `MediaMTXSha256` | v1.21.1 공식 해시 | MediaMTX ZIP 고정 SHA-256 |
영상 타임스탬프는 프레임 번호로 다시 만들지 않습니다. DDA가 제공한 경과시간 PTS를 0부터 시작하도록 정규화하고 마이크로초 time base로 인코더와 RTSP muxer까지 전달합니다. 따라서 순간 처리량이 목표 FPS 아래로 내려가더라도 영상 시간이 실제 경과시간보다 느려져 MediaMTX 녹화가 drift로 재설정되는 현상을 방지합니다.
FFmpeg가 여러 실시간 입력을 여는 동안 `ddagrab`이 미리 만든 탐사용 첫 프레임은 버리고, 모든 입력이 준비된 뒤 들어온 첫 실제 프레임을 PTS 0으로 사용합니다. 처리하지 못한 프레임을 뒤늦게 복제하지 않으므로 과부하 때 실제 프레임 수는 줄 수 있지만, RTP 영상 시간은 실제 경과시간에서 뒤처지지 않습니다.
입력은 초기화가 느린 WASAPI/DirectShow 오디오 장치를 먼저 열고 DDA 화면을 마지막에 엽니다. 따라서 마이크 초기화를 기다리는 동안 DDA의 첫 프레임 시각만 수 초 앞서가는 현상을 피합니다. 기본 목표는 채널별 20fps이며, 과부하로 프레임이 줄어도 타임스탬프를 느리게 늘려 밀린 프레임을 뒤늦게 보내지 않습니다.
WASAPI loopback과 DirectShow 마이크는 서로 다른 절대 시작 PTS를 사용할 수 있으므로 각각 `asetpts=PTS-STARTPTS`로 정규화한 뒤 리샘플링하고 혼합합니다. 큰 DirectShow 시작 PTS를 `first_pts=0`으로 직접 보정하면서 장시간 무음을 삽입해 영상 처리를 막는 상황을 방지합니다.
기본 출력 장치가 무음이라 WASAPI loopback 패킷이 멈출 때는 Windows `Sleep` 호출 횟수로 고정 길이 무음을 넣지 않습니다. 고해상도 경과시간과 이미 전달한 PCM 프레임 수의 차이만큼 무음을 보충하므로 Windows 타이머 해상도와 관계없이 오디오 시계가 실제 시간과 같은 속도로 진행합니다.
각 RTSP 출력은 오디오와 영상 패킷을 기다리는 muxer interleave 상한을 기본 10초 대신 100ms로 제한하고 패킷을 즉시 flush합니다. 한 트랙이 잠시 늦어져도 다른 트랙과 전체 FFmpeg 필터 그래프가 장시간 정지하지 않습니다.
GPU, 모니터, 오디오, NIC, FFmpeg 지원, RTSP 포트를 확인하는 PowerShell 명령은 `config.ini` 위쪽에 모두 주석 형태로 포함되어 있습니다.
INI를 해석한 최종 설정값만 확인하고 종료할 수도 있습니다.
@@ -302,7 +316,7 @@ GPU 우선순위를 바꾸는 예시:
채널 수와 영상 설정을 바꾸는 예시:
```powershell
.\screen-rtsp.ps1 -ChannelCount 2 -FrameRate 30 -VideoBitrate 8000k -AudioBitrate 192k
.\screen-rtsp.ps1 -ChannelCount 2 -FrameRate 20 -GopSeconds 2 -VideoBitrate 8000k -AudioBitrate 192k
```
특정 ASIX NIC와 Gateway 통신을 필수 조건으로 사용하는 노트북 예시: