본문 바로가기
잡(job)기술

RTSP 클라이언트를 만들기 전에 꼭 해야 할 준비― mediamtx + FFmpeg으로 테스트 환경 먼저 만들기

by 무니이구나 2026. 2. 21.

 

들어가며 ― 왜 서버부터 준비해야 할까?

RTSP 클라이언트를 직접 만들어보겠다고 마음먹으면, 보통은 이런 생각이 먼저 든다.

“일단 코드부터 짜보자.”

 

나 역시 그랬다. 뭔가를 만들겠다고 하면 손부터 움직이는 편이라서.
그런데 RTSP는 혼자서는 아무 일도 못 한다. 구조적으로 그렇다. 반드시 서버미디어 소스가 있어야 한다. RTSP는 데이터를 실어 나르는 프로토콜이 아니다. 영상 파일을 직접 보내는 게 아니라, “재생해라”, “멈춰라”, “이 스트림을 열어라” 같은 제어 명령을 주고받는 역할에 가깝다. 말 그대로 리모컨이다. 그래서 테스트를 하려면 최소한 이 세 가지가 필요하다.

  • 항상 떠 있는 RTSP 서버
  • 그 서버에 붙어 있는 영상 소스(H.264 등)
  • 결과를 확인할 수 있는 검증용 플레이어

클라이언트를 제대로 만들고 싶다면, 이 환경을 먼저 갖추는 게 훨씬 빠르다. 돌아가는 기준점이 있어야, 내가 짠 코드가 틀렸는지도 판단할 수 있으니까.


1. 왜 이런 환경이 필요한가?

RTSP 클라이언트를 개발하다 보면 이런 상황을 자주 겪는다.

  • 서버가 문제인지
  • 네트워크가 막힌 건지
  • 내가 작성한 코드가 잘못된 건지

구분이 안 된다. 이게 제일 답답하다. 로그는 나오는데 원인이 안 보인다. 그래서 먼저 해야 할 일은 하나다.

“서버는 정상이다.”라는 확실한 상태를 만들어두는 것.

 

이 전제가 있어야 클라이언트 디버깅이 시작된다. 그렇지 않으면 모든 게 의심 대상이 된다.


2. 무엇을 사용할 것인가?

테스트 환경은 복잡할 필요 없다. 아래 세 가지면 충분하다.

구성요소 역할
mediamtx RTSP 서버
FFmpeg 영상 파일을 서버로 송출 (Publish)
ffplay 최종 검증 플레이어

 

구성은 단순하지만, 실제 RTSP 흐름을 모두 재현할 수 있다. 테스트용으로는 꽤 이상적이다.


3. mediamtx 서버 실행

✔ mediamtx란?

MediaMTX는 가볍고 설정이 단순한 RTSP 서버다. 예전 이름은 rtsp-simple-server였고, 지금은 MediaMTX로 발전했다. Docker로 바로 실행할 수 있어서 실험용으로 부담이 없다.

서버 실행

docker run --rm -it \
  -p 8554:8554/tcp \
  -p 8000:8000/udp \
  -p 8001:8001/udp \
  bluenviron/mediamtx

 

컨테이너가 올라가면 RTSP 서버가 바로 대기 상태에 들어간다.

포트 의미

포트용도

포트 용도
8554 RTSP 제어 연결
8000/8001 RTP / RTCP 데이터 전송

 

여기서 중요한 점이 하나 있다. RTSP(제어)와 RTP(데이터)는 분리되어 있다. 처음 접하면 헷갈리기 쉽다. 제어 채널과 미디어 채널이 다르다는 걸 머릿속에 명확히 그려두는 게 좋다.


4. FFmpeg로 스트림 퍼블리시하기

이제 서버는 떠 있다. 그런데 아직 영상은 없다. RTSP 서버는 그냥 빈 껍데기다. 콘텐츠를 밀어 넣어야 한다. FFmpeg을 이용해 MP4 파일을 서버로 퍼블리시해보자.

ffmpeg -re -stream_loop -1 -i ./BigBuckBunny.mp4 \
  -an -c:v copy \
  -f rtsp -rtsp_transport tcp \
  rtsp://127.0.0.1:8554/mystream

 

명령어는 길어 보이지만, 의미는 단순하다.

옵션 의미
-re 실제 재생 속도로 전송
-stream_loop -1 무한 반복
-c:v copy 재인코딩 없이 복사
-f rtsp RTSP 포맷으로 출력
-rtsp_transport tcp RTP를 TCP로 전송

 

특히 -c:v copy는 꽤 중요하다. 재인코딩을 하지 않기 때문에 CPU 부담이 적고, 타이밍도 안정적이다. 테스트 환경에서는 이런 단순함이 오히려 도움이 된다.

왜 H.264인가?

RTSP는 제어만 담당한다. 실제 영상은 코덱으로 인코딩되어 전달된다. H.264는 거의 모든 플레이어가 지원한다. 실험용으로는 가장 무난하다. 괜히 다른 코덱을 써서 문제를 늘릴 필요는 없다.


5. 서버가 제대로 동작하는지 검증하기

이 단계를 건너뛰면 나중에 반드시 후회한다. FFplay로 직접 재생해본다.

ffplay -rtsp_transport tcp rtsp://127.0.0.1:8554/mystream

 

영상이 재생된다면, 적어도 다음은 정상이다.

  • 서버 동작
  • 퍼블리시 동작
  • RTSP 세션 협상
  • RTP 스트림 전송

이 상태를 확인하고 나서야 클라이언트 코드를 만질 수 있다. 기준선이 생긴다.


6. 전체 흐름을 한 번에 보기

여기서 직접 만들 프로그램은 맨 아래, ffplay 자리에 들어간다. 이미 정상 동작하는 체인이 있으니, 이제 비교가 가능해진다.


7. 언제 특히 유용한가?

이 환경은 생각보다 많은 상황에서 도움이 된다.

  • C++로 RTSP 클라이언트를 직접 구현할 때
  • live555 기반 클라이언트를 테스트할 때
  • RTP 패킷을 직접 분석하고 싶을 때
  • TCP와 UDP 차이를 비교할 때
  • Digest 인증을 구현할 때

뭔가를 새로 붙일 때마다, 기존 환경과 비교해보면 감이 훨씬 빨리 온다.


8. 몇 가지 주의할 점

TCP vs UDP

TCP는 안정적이다. 대신 약간 느릴 수 있다.
UDP는 빠르지만 패킷 손실 가능성이 있다.

처음 구현할 때는 TCP가 편하다. 변수 하나라도 줄이는 게 낫다.

재인코딩 문제

-c:v copy를 빼면 FFmpeg가 재인코딩을 한다. CPU 사용량이 올라가고, 지연이 생길 수 있다. 괜히 복잡도를 높이지 않는 편이 좋다.

네트워크 이슈

로컬에서는 잘 되는데 원격에서는 안 되는 경우가 있다. 대부분 방화벽이나 NAT 문제다. 이건 코드가 아니라 네트워크 설정 문제다. 경험상, 여기서 시간을 많이 쓴다.


마무리하며

RTSP 클라이언트를 만들기 전에 서버 환경부터 준비하는 것. 처음에는 돌아가는 길처럼 느껴질 수 있다. 그런데 막상 해보면, 이게 제일 빠르다.

테스트 가능한 기준 환경을 먼저 만들고, 그 위에 코드를 얹는다. 이 순서를 지키는 것만으로도 디버깅 난이도가 확연히 낮아진다.

조급해지기 쉽지만, 한 번만 제대로 세팅해두면 이후 작업이 훨씬 수월해진다. 나도 몇 번 시행착오를 겪고 나서야 이 순서의 중요성을 체감했다.