Files
RTSP/README.md
T

374 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RTSP
Windows의 활성 모니터를 독립 RTSP 채널로 송출하고, 실제 신호가 있는 시스템 재생 장치와 마이크를 자동 선택해 혼합 오디오를 함께 전송하는 PowerShell 기반 watchdog입니다.
## 프로젝트 성격
RTSP는 `ddagrab` 기반 Desktop Duplication API로 화면과 마우스 커서를 캡처하고, 사용 가능한 GPU 하드웨어 인코더를 실제 초기화 시험한 뒤 FFmpeg와 MediaMTX를 관리합니다.
특정 노트북의 NIC 이름이나 `ifIndex`에 고정되지 않는 범용 구성이 기본입니다. 필요한 환경에서는 `-NicDescription`과 `-HealthTarget`을 함께 지정해 특정 NIC의 Link, IPv4, Source IP 통신까지 송출 조건으로 강제할 수 있습니다.
## 주요 기능
- Windows PowerShell 5.1 지원
- 활성 모니터별 독립 RTSP 채널 제공
- Desktop Duplication API `ddagrab` 화면 캡처
- 전체 화면과 마우스 커서 포함
- 모니터 연결, 해제, 좌표, 해상도, 회전, Primary 변경 감지
- NVIDIA NVENC, AMD AMF, Intel QSV 자동 감지
- GPU/드라이버를 매번 다시 읽고 각 인코더를 4초간 실제 인코딩한 뒤 H.264 IDR 주기를 검사해 선택
- NVENC 요구 API와 드라이버 제공 API가 다르면 게시 해시가 있는 이전 호환 FFmpeg 후보를 시험
- AMF를 포함한 모든 후보에 명시적 주기 IDR을 강제하고, 중간 접속 수신기의 첫 영상 수신을 검증
- 환경이 바뀌면 단일 FFmpeg 2채널 2560×1440/30fps/채널당 8Mbps/AAC/11초 RTSP 최종 시험 수행
- 기본 우선순위 `NVIDIA > AMD > Intel`, 실행 인자로 변경 가능
- Windows Core Audio WASAPI loopback 기반 시스템 재생음 캡처
- 실제 오디오 peak가 있는 출력 장치 우선 선택
- 활성 마이크 입력 endpoint 자동 검색 및 실제 입력 peak 기반 선택
- 무음 상태에서는 Windows 기본 출력·입력 장치를 선택해 송출이 불필요하게 끊기지 않음
- DirectShow 마이크와 시스템 재생음을 `amix`로 혼합하고 `asplit`으로 모든 채널에 분배
- 하나의 FFmpeg가 모든 DDA 입력과 RTSP 출력을 함께 처리
- 기본 출력·입력 장치, 선택 장치, 오디오 포맷 변경 시 전체 채널 재시작
- 기본 20fps, GOP 2초(40프레임), 영상 8Mbps, AAC 오디오 192kbps
- NIC Link, IPv4, `ifIndex`, IP 변경 감지
- 선택적 Source IP 고정 ping 상태 검사
- 3초간 정상 상태가 유지된 뒤 전체 채널 시작
- 단일 FFmpeg 또는 WASAPI loopback worker가 종료되면 전체 채널 재시작
- MediaMTX 종료 시 자동 재시작
- 기존 MediaMTX가 RTSP 포트를 사용 중이면 해당 프로세스 재사용
- 자동 생성 MediaMTX 설정은 RTSP over TCP만 사용해 UDP RTP 포트 충돌 방지
- 로그인 시 자동 실행 작업 등록 및 제거
- 기본 실행과 예약 작업 모두 PowerShell 창을 표시하지 않는 숨김 백그라운드 실행
- 절전 해제나 장시간 polling 중단 감지 시 전체 채널 강제 재구성
- 로그인 트리거와 1분 간격 무기한 복구 트리거를 이용한 Watchdog 지속 복구
- 각 RTSP 채널에서 실제 영상 프레임을 주기적으로 디코딩해 살아 있는 채 멈춘 FFmpeg도 자동 복구
- `config.ini` 기반 기능별 설정과 명령줄 override
- 전체 오디오와 마이크 혼합을 각각 `1` 또는 `0`으로 활성화·비활성화
- FFmpeg와 MediaMTX 부재 시 HTTPS 다운로드, 게시 SHA-256 검증, 후보 선검증 및 백업 가능한 안전 교체
- `config.ini` 최상단에 비개인 환경·호환성 정보를 원자적으로 자동 기록
- 모니터·오디오·NIC·프로세스·RTSP 실제 프레임·절전 복구·설정·안전장치용 내장 시뮬레이션 51건
## RTSP URL
기본 2채널 구성은 다음 URL을 유지합니다.
```text
rtsp://<현재_NIC_IP>:8554/monitor1
rtsp://<현재_NIC_IP>:8554/monitor2
```
## 프로세스 구조
기본 2채널에서는 화면·오디오 입력을 하나의 FFmpeg가 열고 두 RTSP 출력을 동시에 publish합니다.
```text
ddagrab monitor 1 ───────────────────────────────┐
ddagrab monitor 2 ───────────────────────────────┤
│
WASAPI 출력 loopback worker → named pipe ─┐ ├─ FFmpeg 1개
├─amix│ ├─ /monitor1
자동 선택 마이크 → DirectShow ────────────┘ │ └─ /monitor2
│
amix → asplit
```
`ChannelCount`를 늘리면 동일한 단일 FFmpeg 안에서 선택된 화면 수만큼 DDA 입력과 RTSP 출력을 만들고, 혼합 오디오도 같은 수만큼 분배합니다.
## 구성
- `screen-rtsp.ps1`: 캡처, 오디오 loopback, GPU 선택, MediaMTX/FFmpeg watchdog
- `config.ini`: 영상, 오디오, 네트워크, RTSP 설정과 진단 명령 예시
- `ffmpeg.exe`: `ddagrab`, `dshow`, `h264_nvenc`, `h264_amf`, `h264_qsv`, `aac` 지원 FFmpeg
- `mediamtx.exe`: RTSP 서버. 현재 검증 기준 버전은 v1.21.1
- `mediamtx.yml`: 없으면 스크립트가 기본 설정을 자동 생성
- `logs/watchdog.log`: watchdog 상태 로그
- `logs/ffmpeg.log`: 모든 monitor 출력을 담당하는 단일 FFmpeg 로그
- `logs/audio-loopback.log`: 단일 WASAPI loopback worker 오류 로그
- `logs/compatibility-state.json`: 동일 환경의 무거운 2채널 최종 시험 성공 상태
- `logs/dependency-evidence.json`: 다운로드 출처와 ZIP SHA-256 검증 이력
- `logs/backups/`: 안전 교체 전 기존 실행 파일 백업
실행 파일과 생성 파일은 저장소에 포함하지 않습니다. `Dependencies.AutoInstall=1`이면 실행할 때 없는 `ffmpeg.exe`와 `mediamtx.exe`를 스크립트 옆에 자동 설치합니다.
## 설정 파일
기본 설정은 `screen-rtsp.ps1`과 같은 폴더의 `config.ini`에서 읽습니다.
파일 최상단의 다음 표식 사이는 프로그램이 관리하는 설치 환경 정보입니다.
```ini
# >>> SCREENRTSP AUTO-MANAGED INSTALLATION ENVIRONMENT >>>
# 이 부분은 실제 컴퓨터에서 실행한 후 자동 기록되며 사용자가 직접 수정하지 않습니다.
# ...
# <<< SCREENRTSP AUTO-MANAGED INSTALLATION ENVIRONMENT <<<
```
GPU 이름과 드라이버, NVENC API, AMF/QSV 시험 결과, 선택 인코더, FFmpeg/MediaMTX 버전·실행 파일 SHA-256·검증 출처·확인 시각이 기록됩니다. 모든 줄이 주석이므로 설정 파서가 읽지 않으며, 송출 판단은 이 기록이 아니라 실행 시 다시 수행한 실제 검사만 사용합니다. 사용자 이름, 컴퓨터 이름, IP, PnP 장치 ID, 토큰이나 인증 정보는 기록하지 않습니다.
갱신은 같은 폴더의 임시 파일을 완성한 뒤 원자적으로 교체하므로 실패해도 기존 `config.ini`를 유지합니다. 표식 밖의 설정과 사용자 주석은 변경하지 않습니다.
```ini
[Video]
FrameRate=20
GopSeconds=2
Bitrate=8000k
EncoderPriority=NVIDIA,AMD,Intel
[Audio]
Enabled=1
MicrophoneEnabled=1
Bitrate=192k
SignalThreshold=0.0005
```
`Audio.Enabled=1`이면 선택한 출력 장치의 시스템 재생음을 WASAPI loopback으로 캡처합니다. `MicrophoneEnabled=1`이면 자동 선택한 마이크를 DirectShow로 열고 시스템 재생음과 혼합합니다. `Audio.Enabled=0`이면 마이크 설정과 관계없이 모든 오디오 감시와 AAC 트랙을 끄고 영상만 송출합니다.
줄 앞의 공백을 제외한 첫 문자가 `#`, `;`, `//`이면 설명이나 참고 명령으로 인식해 건너뜁니다. 값 오른쪽의 inline 주석은 지원하지 않으므로 설명은 별도 줄에 작성합니다. 명령줄에서 직접 지정한 값은 INI 값보다 우선합니다.
알 수 없는 섹션, 설정 이름, 범위를 벗어난 값, `0/1` 이외의 기능 스위치는 시작 전에 오류로 표시합니다.
| 섹션 | 설정 | 기본값 | 설명 |
|---|---|---:|---|
| `General` | `ChannelCount` | `2` | 송출 채널과 필요한 모니터 수 |
| `General` | `StableTimeSec` | `3` | 정상 상태 안정화 시간 |
| `General` | `PollIntervalSec` | `1` | 상태 확인 주기 |
| `Video` | `FrameRate` | `20` | 화면 캡처 및 RTSP 영상 프레임률 |
| `Video` | `GopSeconds` | `2` | IDR/GOP 간격. 기본값은 20fps에서 40프레임 |
| `Video` | `Bitrate` | `8000k` | 채널별 영상 비트레이트 |
| `Video` | `EncoderPriority` | `NVIDIA,AMD,Intel` | GPU 선택 순서 |
| `Audio` | `Enabled` | `1` | 시스템 재생음과 AAC 트랙 사용 여부 |
| `Audio` | `MicrophoneEnabled` | `1` | 마이크 자동 선택 및 시스템 재생음 혼합 여부 |
| `Audio` | `Bitrate` | `192k` | AAC 비트레이트 |
| `Audio` | `SignalThreshold` | `0.0005` | 실제 출력·입력 신호 장치 판별 peak 기준 |
| `Network` | `NicDescription` | 빈 값 | 비우면 기본 경로 NIC 자동 선택 |
| `Network` | `HealthTarget` | 빈 값 | Source IP ping 대상 |
| `RTSP` | `Port` | `8554` | MediaMTX RTSP 포트 |
| `RTSP` | `HealthCheckIntervalSec` | `10` | 모든 RTSP 채널의 실제 프레임 검사 주기 |
| `RTSP` | `HealthTimeoutSec` | `5` | 새 수신기가 영상 1프레임을 디코딩할 제한 시간 |
| `RTSP` | `HealthFailureThreshold` | `2` | 전체 AV 재시작 전 허용할 연속 검사 실패 횟수 |
| `RTSP` | `StartupGraceSec` | `45` | FFmpeg 시작 후 최초 프레임 검사까지의 준비 유예시간 |
| `Dependencies` | `AutoInstall` | `1` | 실행 파일 부재 시 자동 설치 여부 |
| `Dependencies` | `FFmpegUrl` | Gyan essentials ZIP | FFmpeg Windows ZIP 다운로드 주소 |
| `Dependencies` | `FFmpegSha256Url` | Gyan SHA-256 | FFmpeg 게시 해시 주소 |
| `Dependencies` | `FFmpegFallbackUrl` | BtbN 2026-05-31 n8.1 호환 빌드 | NVENC API 불일치 때만 시험할 Windows x64 후보 |
| `Dependencies` | `FFmpegFallbackSha256Url` | 해당 Release `checksums.sha256` | 파일명과 일치하는 게시 해시 주소 |
| `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를 해석한 최종 설정값만 확인하고 종료할 수도 있습니다.
```powershell
.\screen-rtsp.ps1 -ShowConfiguration
```
## 의존 프로그램 자동 설치
`ffmpeg.exe` 또는 `mediamtx.exe`가 없고 `Dependencies.AutoInstall=1`이면 다음 순서로 자동 설치합니다.
1. 기존 실행 파일이 정상이면 유지하며 불필요하게 다운로드하지 않습니다.
2. 필요할 때만 HTTPS 주소의 ZIP을 Windows 임시 폴더에 받습니다.
3. FFmpeg는 배포자가 게시한 SHA-256을 파일명까지 대조하고, MediaMTX는 공식 v1.21.1 Release SHA-256을 검증합니다.
4. 임시 폴더 안의 후보에서 `ddagrab`, `h264_nvenc`, `h264_amf`, `h264_qsv`, AAC와 DirectShow 지원을 확인합니다.
5. 현재 설치 GPU별로 4초/120프레임 이상 인코딩하고, 디코딩 키프레임과 Annex-B NAL type 5가 GOP 30 기준으로 주기 생성되는지 검사합니다.
6. NVIDIA 우선 환경에서 최신 빌드가 `Required NVENC API > Found API`로 실패하면 2026-05-31 BtbN n8.1 호환 후보를 동일한 절차와 2채널 RTSP 시험까지 통과시킨 뒤에만 채택합니다.
7. 교체 직전 기존 실행 파일을 `logs/backups`에 보존하고 같은 볼륨에서 안전 교체합니다. 다운로드·해시·기능·인코딩 검증 중 하나라도 실패하면 기존 파일을 유지합니다.
8. MediaMTX v1.21.1이 정상 실행되면 교체하지 않습니다.
송출을 시작하지 않고 설치와 기능 확인만 먼저 수행할 수 있습니다.
```powershell
.\screen-rtsp.ps1 -InstallDependenciesOnly
```
환경 변경 여부와 관계없이 2채널 최종 시험을 다시 수행하려면 다음처럼 실행합니다. 이미 Watchdog이 두 GPU 세션을 사용 중이면 시험 결과가 왜곡될 수 있으므로 먼저 자동 실행 작업을 완전히 중지한 상태에서 사용합니다.
```powershell
.\screen-rtsp.ps1 -InstallDependenciesOnly -ForceCompatibilityTest
```
자동 다운로드를 금지하려면 `AutoInstall=0`으로 바꿉니다. 이 경우 실행 파일이 없으면 오류를 표시하고 종료합니다. 자동 설치에는 인터넷 HTTPS 연결과 스크립트 폴더 쓰기 권한이 필요합니다.
예를 들어 NVIDIA Quadro P6000 드라이버 582.70이 제공하는 NVENC API가 13.0이고 현재 FFmpeg 빌드가 13.1을 요구하면 로그에 `Required: 13.1 Found: 13.0`을 보존합니다. 이 경우 NVIDIA가 우선순위상 첫 GPU일 때만 13.1 헤더 도입 전의 BtbN 월별 보관 빌드를 내려받아 임시 위치에서 SHA-256, 기능, 4초 IDR, 2채널 RTSP 시험을 모두 수행합니다. 이전 빌드도 실패하면 설치하지 않고, 현재 FFmpeg에서 IDR 및 최종 수신 시험을 통과한 AMD AMF 또는 Intel QSV를 선택합니다.
- FFmpeg Windows build: <https://www.gyan.dev/ffmpeg/builds/>
- FFmpeg 공식 Windows 빌드 안내(Gyan/BtbN): <https://ffmpeg.org/download.html#build-windows>
- NVENC API 13.1 최소 드라이버 안내: <https://github.com/FFmpeg/nv-codec-headers/blob/master/README>
- NVENC API 13.0 호환 후보(BtbN monthly release): <https://github.com/BtbN/FFmpeg-Builds/releases/tag/autobuild-2026-05-31-13-22>
- MediaMTX v1.21.1: <https://github.com/bluenviron/mediamtx/releases/tag/v1.21.1>
## 내장 시뮬레이션
실제 송출 프로세스나 예약 작업을 만들지 않고 주요 판단 로직 49건을 검사합니다. 자동 기록 블록의 파서 격리, 사용자 설정 보존, 중복 방지, 개인정보 키 배제와 GPU별 IDR 옵션도 포함됩니다.
```powershell
.\screen-rtsp.ps1 -RunSimulationTests
```
모든 항목이 통과하면 종료 코드 `0`, 하나라도 실패하면 종료 코드 `1`을 반환합니다.
## 처리 흐름
1. FFmpeg와 MediaMTX가 없으면 HTTPS/SHA-256/후보 실행 검증 후 설치합니다.
2. GPU와 드라이버를 다시 읽고 각 하드웨어 인코더로 4초 이상 실제 H.264를 생성해 주기 IDR을 검사합니다.
3. NVIDIA NVENC API 불일치가 확인되면 호환 이전 빌드를 임시 폴더에서 먼저 검증합니다. 실패하면 기존 파일을 유지하고 IDR 검증을 통과한 AMF/QSV 후보로 넘어갑니다.
4. 최초 실행이나 GPU·드라이버·FFmpeg·MediaMTX 변경 시 두 개의 1440p 시험 영상을 하나의 FFmpeg에서 RTSP로 publish하고 새 수신기 두 개로 11초간 실제 디코딩, IDR, FPS, 비트레이트와 AAC 트랙을 확인합니다.
5. 검증 결과와 비개인 환경 정보를 `config.ini` 자동 기록 영역 및 watchdog 로그에 남깁니다.
6. 활성 모니터, IPv4 기본 경로 NIC, 활성 오디오 출력·입력 endpoint를 읽습니다.
7. Core Audio peak가 감지된 출력 장치와 마이크를 우선하고, 신호가 없으면 Windows 기본 Multimedia 장치를 사용합니다.
8. 모든 조건이 3초 동안 유지되면 WASAPI loopback worker 하나와 FFmpeg 하나를 시작합니다.
9. 화면은 `ddagrab -> hwdownload -> BGRA -> 회전 보정 -> NV12 -> 하드웨어 H.264` 순서로 처리합니다.
10. 시스템 소리는 named pipe, 마이크는 DirectShow로 FFmpeg에 입력됩니다. 두 소리를 `amix`한 뒤 `asplit`으로 각 RTSP 출력에 넣고 AAC로 인코딩합니다.
11. 모니터, NIC, GPU, 드라이버, 실행 파일, 오디오 장치 또는 자식 프로세스 상태가 바뀌면 전체 채널을 종료한 뒤 검증과 구성을 새로 읽어 재시작합니다.
12. FFmpeg PID가 살아 있어도 각 RTSP URL에 새 로컬 수신기를 붙여 실제 영상 프레임을 확인하며, 연속 실패하면 단일 FFmpeg와 오디오 worker를 함께 재시작합니다.
## 설치 및 실행
관리자 PowerShell에서 실행 정책을 우회해 시작합니다. 기본 실행은 최종 설정값과 명령줄 override를 숨김 worker에 전달한 뒤 현재 PowerShell 프롬프트로 즉시 돌아옵니다. 현재 창을 닫아도 송출은 계속됩니다.
```powershell
Set-Location C:\RTSP
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\screen-rtsp.ps1
```
진단 목적으로 현재 콘솔에서 직접 로그를 확인할 때만 `-Foreground`를 사용합니다. 이 경우 창을 닫거나 `Ctrl+C`를 누르면 송출도 종료됩니다.
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\screen-rtsp.ps1 -Foreground
```
### 예약 작업 등록 및 즉시 실행
로그인 자동 실행은 대화형 사용자 세션에 예약 작업을 등록합니다. Desktop Duplication과 사용자 재생 오디오를 캡처해야 하므로 Windows 서비스가 아니라 로그인 트리거를 사용합니다. 관리자 PowerShell에서 다음 명령을 순서대로 실행하면 작업을 등록하고 즉시 시작합니다.
```powershell
Set-Location C:\RTSP
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\screen-rtsp.ps1 -InstallStartup
Start-ScheduledTask -TaskName "Screen RTSP Watchdog"
```
등록된 작업은 다음 복구 정책을 사용합니다.
- PowerShell 작업 인자와 프로세스 창 스타일을 모두 `Hidden`으로 지정
- 로그인 즉시 시작
- 1분마다 작업 생존을 무기한 확인하고, 실행 중이면 `IgnoreNew`로 중복 실행 방지
- 작업 실패 시 1분 간격으로 최대 999회 재시작하고, 횟수가 소진돼도 무기한 반복 트리거가 계속 복구
- 절전 중 놓친 실행은 `StartWhenAvailable`로 절전 해제 후 시작
- 배터리 전환 시에도 중지하지 않으며 실행 시간 제한 없음
Watchdog 내부에서는 Windows `PowerModeChanged/Resume` 이벤트를 감시하고, 이벤트 누락에 대비해 polling 시간 공백도 함께 확인합니다. 절전 해제가 감지되면 단일 FFmpeg AV 파이프라인을 종료하고 모니터·NIC·오디오·GPU 구성을 다시 읽은 뒤 안정화 시간 이후 재시작합니다. 모니터 분리 시에는 채널을 종료하고 계속 대기하며, 필요한 수만큼 다시 연결되면 동일하게 자동 복구합니다.
프로세스 생존 여부와 실제 송출 상태는 별도로 검사합니다. 새 FFmpeg를 시작하면 장치와 RTSP Publisher가 준비되도록 `StartupGraceSec` 동안 검사를 유예합니다. 이후 `HealthCheckIntervalSec`마다 모든 `monitorN` URL에 숨김 로컬 FFmpeg 수신기를 동시에 연결하고, `HealthTimeoutSec` 안에 각 채널에서 영상 1프레임을 디코딩해야 정상으로 판정합니다. `HealthFailureThreshold`회 연속 실패하면 FFmpeg PID가 남아 있어도 프로세스별 상태와 로그 끝부분을 기록하고 전체 AV 파이프라인을 강제로 정리한 뒤 다시 만듭니다. 재시작 횟수 제한은 없습니다.
등록된 작업은 `config.ini` 경로만 전달하므로 설정 파일을 수정한 뒤 작업을 다시 시작하면 변경값이 적용됩니다. 기존 작업이 등록돼 있다면 업데이트된 복구 설정을 적용하기 위해 `-InstallStartup`을 다시 실행해야 합니다.
### 예약 작업 상태 확인 및 다시 시작
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\screen-rtsp.ps1 -StartupStatus
Stop-ScheduledTask -TaskName "Screen RTSP Watchdog"
Start-ScheduledTask -TaskName "Screen RTSP Watchdog"
```
`Stop-ScheduledTask`만 실행하면 무기한 반복 트리거가 1분 이내에 다시 시작할 수 있습니다.
무기한 복구는 사용자가 로그인한 대화형 세션에서 예약 작업이 등록·활성화된 동안 적용됩니다. 작업 자체를 삭제하거나 비활성화한 경우와 전원이 꺼진 동안에는 실행할 수 없으며, 다음 로그인 때 다시 시작합니다.
### 예약 작업 중단 및 삭제
예약 작업과 현재 실행 인스턴스를 완전히 중단하려면 관리자 PowerShell에서 다음 명령을 순서대로 실행합니다. 먼저 실행 중인 작업을 중단하고, 이어서 반복 트리거를 포함한 예약 작업 자체를 삭제합니다.
```powershell
Set-Location C:\RTSP
Stop-ScheduledTask -TaskName "Screen RTSP Watchdog" -ErrorAction SilentlyContinue
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\screen-rtsp.ps1 -UninstallStartup
```
## 실행 옵션
다른 설정 파일을 사용하는 예시:
```powershell
.\screen-rtsp.ps1 -ConfigPath C:\RTSP\config.ini
```
명령줄 값은 `config.ini`보다 우선합니다. 다음 실행에서만 오디오를 끄는 예시:
```powershell
.\screen-rtsp.ps1 -AudioEnabled 0
```
시스템 재생음은 유지하고 마이크만 끄는 예시:
```powershell
.\screen-rtsp.ps1 -MicrophoneEnabled 0
```
GPU 우선순위를 바꾸는 예시:
```powershell
.\screen-rtsp.ps1 -EncoderPriority Intel,NVIDIA,AMD
```
채널 수와 영상 설정을 바꾸는 예시:
```powershell
.\screen-rtsp.ps1 -ChannelCount 2 -FrameRate 20 -GopSeconds 2 -VideoBitrate 8000k -AudioBitrate 192k
```
특정 ASIX NIC와 Gateway 통신을 필수 조건으로 사용하는 노트북 예시:
```powershell
.\screen-rtsp.ps1 `
-NicDescription "ASIX USB to Gigabit Ethernet Family Adapter" `
-HealthTarget "192.168.50.1"
```
이 모드에서도 NIC 이름이나 `ifIndex`가 아니라 `InterfaceDescription`으로 매번 다시 검색합니다. Source IP ping은 검색된 NIC의 현재 IPv4를 사용합니다.
## 오디오 장치 선택 정책
스크립트는 활성 상태의 Windows Render와 Capture endpoint를 모두 읽고 각 장치의 peak를 확인합니다.
- 현재 선택한 출력 또는 입력 장치에 실제 신호가 계속 있으면 해당 장치를 유지합니다.
- 다른 활성 장치에서만 신호가 감지되면 해당 출력 장치 또는 마이크로 전환합니다.
- 모든 장치가 무음이면 Windows 기본 Multimedia 출력·입력 장치를 선택합니다.
- 선택 endpoint ID, 기본 장치 여부, sample rate, 채널 수 또는 sample format이 바뀌면 전체 RTSP 채널을 재시작합니다.
- Core Audio와 DirectShow가 장치명 공백을 다르게 표시해도 정규화해 같은 마이크로 연결합니다.
- 마이크가 활성화된 상태에서 입력 장치가 없으면 영상만 보내지 않고 정상 입력 장치가 생길 때까지 전체 파이프라인을 대기합니다.
이 정책은 음악이나 음성 사이의 무음 구간마다 송출이 중단되는 것을 막으면서 Bluetooth/HDMI/USB 출력과 USB/Bluetooth 마이크 변경을 자동 반영합니다.
## 운영 체크포인트
- `ddagrab`은 대화형 데스크톱 세션이 필요합니다. 사용자가 로그인하지 않은 부팅 직후 세션에서는 화면과 사용자 오디오를 캡처할 수 없습니다.
- GPU 이름만으로 인코더를 확정하지 않습니다. 드라이버 또는 세션 문제로 초기화가 실패하면 다음 우선순위 GPU를 시험합니다.
- 여러 GPU에 모니터가 물린 특수 구성에서는 FFmpeg가 사용하는 D3D11 adapter의 출력 순서를 확인해야 합니다.
- RTSP 포트를 MediaMTX가 아닌 다른 프로세스가 사용하면 충돌 프로세스를 종료하지 않고 송출을 대기합니다.
- 인증이 없는 기본 MediaMTX 설정은 신뢰된 LAN에서만 사용하고, 외부 네트워크에 노출할 때는 MediaMTX 인증과 방화벽 정책을 추가합니다.
## 저장소 정책
FFmpeg와 MediaMTX 바이너리, 로그, 자동 생성 설정, 인증서와 키는 Git에 올리지 않습니다. 비밀번호나 토큰도 스크립트와 README에 기록하지 않습니다.
실제 실행 후 `config.ini` 최상단에는 해당 PC의 GPU와 실행 파일 정보가 채워집니다. 저장소에는 표식과 안내 문구 및 빈 필드만 남겨야 하므로 `.githooks/pre-commit`이 커밋 직전에 자동 기록 영역만 비우고 다시 stage합니다. `pre-push`는 HEAD에 실제 값이 남아 있으면 push를 중단합니다. 스크립트를 Git 작업 폴더에서 한 번 실행하면 `core.hooksPath=.githooks`를 자동 설정하며, 수동 활성화와 수동 초기화 명령은 다음과 같습니다.
```powershell
.\screen-rtsp.ps1 -InstallGitHooks
.\screen-rtsp.ps1 -ResetManagedInfo
```
이 초기화는 표식 사이만 교체하며 나머지 설정값과 사용자 주석을 보존합니다. `--no-verify`로 hook을 우회하지 마십시오.