streaming-expert
SKILL.md
영상 스트리밍 전문가
$ARGUMENTS 영상 스트리밍 관련 질문에 답변하고 구현을 도와드립니다.
@pf-dev/cctv 패키지 구조
packages/cctv/src/
├── components/
│ └── CCTVPlayer.tsx # Headless 플레이어
├── hooks/
│ ├── useHLSStream.ts # HLS 스트리밍
│ └── useWHEPStream.ts # WHEP 스트리밍
├── stores/
│ ├── useHLSStore.ts # HLS 상태
│ └── useWHEPStore.ts # WHEP 상태
└── types/
└── index.ts
프로토콜 비교
| 프로토콜 | 지연시간 | 장점 | 단점 |
|---|---|---|---|
| HLS | 1-3초 | 안정적, 널리 지원 | 지연 있음 |
| WHEP | ~1초 | 초저지연 (WebRTC) | 서버 구성 복잡 |
HLS 스트리밍
기본 사용
import { useHLSStream } from "@pf-dev/cctv";
function CCTVView({ streamUrl }: { streamUrl: string }) {
const videoRef = useRef<HTMLVideoElement>(null);
const { isPlaying, error, play, pause, destroy } = useHLSStream({
url: streamUrl,
videoRef,
autoPlay: true,
onError: (err) => console.error("HLS Error:", err),
});
return (
<div>
<video ref={videoRef} muted playsInline />
{error && <p className="text-red-500">{error.message}</p>}
<button onClick={isPlaying ? pause : play}>{isPlaying ? "일시정지" : "재생"}</button>
</div>
);
}
LL-HLS (Low-Latency HLS)
const { ... } = useHLSStream({
url: streamUrl,
videoRef,
hlsConfig: {
lowLatencyMode: true,
liveSyncDurationCount: 3,
liveMaxLatencyDurationCount: 10,
},
});
WHEP 스트리밍 (WebRTC)
기본 사용
import { useWHEPStream } from "@pf-dev/cctv";
function LowLatencyCCTV({ whepUrl }: { whepUrl: string }) {
const videoRef = useRef<HTMLVideoElement>(null);
const { isConnected, error, connect, disconnect } = useWHEPStream({
url: whepUrl,
videoRef,
autoConnect: true,
onConnectionChange: (connected) => {
console.log("Connection:", connected);
},
});
return (
<div>
<video ref={videoRef} muted playsInline />
{!isConnected && <p>연결 중...</p>}
{error && <p className="text-red-500">{error.message}</p>}
</div>
);
}
자동 재연결
const { ... } = useWHEPStream({
url: whepUrl,
videoRef,
reconnect: true,
reconnectInterval: 3000, // 3초 후 재시도
maxReconnectAttempts: 5,
});
CCTVPlayer (Headless)
import { CCTVPlayer } from "@pf-dev/cctv";
function CustomPlayer({ url, protocol }) {
return (
<CCTVPlayer
url={url}
protocol={protocol} // "hls" | "whep"
autoPlay
muted
className="w-full h-full object-cover"
onReady={() => console.log("Ready")}
onError={(err) => console.error(err)}
onLatencyChange={(latency) => console.log(`Latency: ${latency}ms`)}
/>
);
}
자주 묻는 질문
Q: 영상이 안 나와요
A: 체크리스트
- URL 확인 (CORS, 인증)
- 네트워크 탭에서 m3u8/segment 요청 확인
- 브라우저 콘솔 에러 확인
- HTTPS 여부 확인 (WHEP는 HTTPS 필수)
// 디버깅용 로깅
useHLSStream({
url,
videoRef,
hlsConfig: {
debug: true, // HLS.js 디버그 로그
},
});
Q: 지연이 너무 커요
A: HLS 최적화
hlsConfig: {
lowLatencyMode: true,
liveSyncDurationCount: 2, // 동기화할 세그먼트 수 감소
liveMaxLatencyDurationCount: 5,
maxBufferLength: 10, // 버퍼 크기 감소
}
A: WHEP로 전환
// WHEP는 ~1초 지연
<CCTVPlayer protocol="whep" url={whepUrl} />
Q: 끊김이 심해요
A: 버퍼 설정
hlsConfig: {
maxBufferLength: 30, // 버퍼 증가
maxMaxBufferLength: 60,
maxBufferHole: 0.5,
}
Q: 여러 CCTV를 동시에 보고 싶어요
A: 그리드 레이아웃
function CCTVGrid({ streams }: { streams: StreamInfo[] }) {
return (
<div className="grid grid-cols-2 gap-2">
{streams.map((stream) => (
<CCTVPlayer
key={stream.id}
url={stream.url}
protocol={stream.protocol}
muted // 여러 개일 때 음소거 필수
/>
))}
</div>
);
}
주의: 동시 스트림 수는 4-6개 이하 권장 (브라우저 성능)
환경변수
VITE_MEDIA_API_URL=https://media.example.com
VITE_MEDIA_WHEP_URL=https://media.example.com/whep
서버 요구사항
HLS
- Nginx + nginx-rtmp-module
- 또는 FFmpeg + HLS 출력
WHEP
- MediaMTX (권장)
- 또는 Janus Gateway
- 또는 Pion WebRTC
성능 모니터링
const { stats } = useHLSStream({ ... });
// stats 내용
{
currentTime: 123.45,
bufferedDuration: 10.2,
latency: 2.5, // 실시간과의 지연 (초)
bandwidth: 5000000, // bps
droppedFrames: 0,
}
Weekly Installs
3
Repository
pluxity/pf-frontendFirst Seen
13 days ago
Security Audits
Installed on
codex3
gemini-cli2
opencode2
codebuddy2
github-copilot2
kimi-cli2