"공식 API도, 편한 내보내기도 없는 Tapo H200/D230에서 녹화 영상을 조회하고 MP4로 내려받기까지의 개발 기록"
결국 내부망의 Tapo H200의 녹화 영상을 확인하는 웹 도구를 만들었다
Tapo D230 도어벨과 H200 허브를 사용하고 있다. 도어벨이 움직임을 감지하면 H200에 녹화가 저장되고, Tapo 앱에서 영상을 확인할 수 있다.
여기까지만 보면 평범한 홈 카메라 서비스다. 문제는 그다음이다.
단지 내 허브에 저장된 내 영상을 외부에서 확인하고싶을 뿐이다. 고객지원에 문의했지만 무시당한지 7개월 TP LINK 제품은 이제 절대 다시 안쓸 것이다.
공식적으로 제공되는 API도 없고, 따로 DVR을 돌리는 방법도 마땅치 않았다.
결국 직접 만들었다.
프로젝트 저장소: tapo-h200-recording-downloader
개발하게 된 계기
도어벨 영상은 단순한 재미용 영상이 아니다. 택배가 언제 왔는지, 누가 현관 앞에 다녀갔는지, 특정 시간대에 무슨 일이 있었는지 확인해야 할 때가 있다.
그런데 외부에서 확인할 방법이 없으니 답답했다. H200에 로컬 저장된 데이터인데도 사용자는 내부망에서만 확인이 가능했다. 제고하는 API도 없다.
내가 원한 것은 단순했다.
- H200에 연결된 D230을 자동으로 찾기
- 날짜별 녹화 목록 보기
- 필요한 영상만 MP4로 저장하기
- 이미 저장한 영상은 건너뛰기
- PC와 휴대폰 브라우저에서 영상 확인하기
- 남는 안드로이드 휴대폰에서도 서버 돌리기
이 정도는 제조사가 기본 기능으로 제공해도 이상하지 않다. 하지만 없었다. 그래서 Python과 커뮤니티에서 분석한 pytapo를 기반으로 필요한 부분을 직접 연결했다.
만든 기능
현재 프로젝트는 다음 기능을 지원한다.
- H200에 페어링된 자식 장치 조회
- D230
device_id와 alias 자동 탐색 - 날짜별 녹화 목록 조회
- 개별 영상 또는 하루 전체 영상 다운로드
- H.264 영상과 오디오를 포함한 MP4 생성
- 이미 저장한 파일 건너뛰기
- 로컬 Web UI에서 목록 조회, 재생, 다운로드
- 비밀번호를 암호화한 로컬 설정 파일로 저장
.env를 이용한 H200 IP와 장치 설정 관리- Ubuntu와 Android Termux 실행 지원
구조를 단순화하면 다음과 같다.
D230 도어벨
↓
H200 허브
↓ 443: 제어 API / 8800: 미디어
pytapo + Python
↓
MP4 파일 + 로컬 Web UI
웹 서버를 실행하면 같은 LAN이나 WireGuard로 연결된 기기에서 접속할 수 있다.
.venv/bin/python h200_web.py --bind 0.0.0.0 --port 8092
브라우저에서는 날짜를 선택하고 녹화 목록을 조회한 뒤, 저장되지 않은 영상을 한꺼번에 내려받을 수 있다. 저장이 끝난 MP4는 브라우저에서 바로 재생하거나 현재 접속한 기기로 다시 다운로드할 수 있다.
생각보다 지독했던 장치 찾기
H200은 허브이고 D230은 그 아래에 붙은 자식 장치다. 문제는 녹화 요청에 H200 정보만 넣는다고 끝나지 않는다는 점이다. 실제 미디어 요청에는 D230의 device_id가 필요하다.
처음에는 장치 ID를 직접 찾아 .env에 넣었다. 하지만 설치할 때마다 사용자가 별도 조회 스크립트를 실행해 값을 복사하는 방식은 불편했다. 지금은 --setup 과정에서 H200의 자식 장치를 조회하고 D230의 ID와 alias를 자동으로 저장한다.
.venv/bin/python h200_recordings.py --setup
이 과정에서 생성되는 .env, 암호화된 JSON, 복호화 키는 Git에 올라가지 않도록 분리했다. JSON에 원문 비밀번호를 저장하지는 않지만, JSON과 key를 모두 가지면 복호화할 수 있으므로 둘 다 민감정보로 취급한다.
비밀번호도 한 종류가 아니다
Tapo 쪽 인증을 다루다 보면 admin, Camera Account 비밀번호, TP-Link 계정 비밀번호가 한꺼번에 등장한다. 사용자가 앱에 로그인할 때 쓰는 계정과 카메라 로컬 접근 계정의 역할도 다르다.
처음 설정이 실패했는데 잘못 입력한 비밀번호가 기존 설정을 덮어쓰는 문제도 있었다. 지금은 H200 인증과 D230 조회가 모두 성공한 뒤에만 설정 파일을 저장한다.
비밀번호 확인만 하고 싶을 때는 별도 스크립트를 사용할 수 있다.
.venv/bin/python check_h200_password.py
한 번 정상 설정한 뒤에는 비밀번호를 매번 입력할 필요가 없다. 편의성은 유지하되, 저장 파일이 Git에 섞이지 않도록 하는 것이 중요했다.
wrong adaptation size와 MPEG-TS 지옥
가장 오래 붙잡고 있었던 문제는 녹화 파일이었다.
H200에서 데이터는 내려오는데 MP4가 만들어지지 않았다. 로그에는 아래 메시지가 끝없이 출력됐다.
WARNING: mpegts: wrong adaptation size
Invalid data found when processing input
처음에는 Termux의 Python 3.14나 암호화 라이브러리를 의심했다. 비밀번호가 잘못돼 미디어 복호화가 깨진 것처럼 보이기도 했다. 하지만 Ubuntu에서도 같은 문제가 재현됐다.
결론은 요청 경로였다.
기존 구현은 H200에 일반적인 download 요청을 보내고 응답을 그대로 TS 파일로 저장했다. D230은 H200 아래의 child device이므로 deviceId를 포함한 sdvod 세션과 playback 요청을 사용해야 했다. 잘못된 경로에서 받은 데이터를 MPEG-TS라고 믿고 저장했으니 ffmpeg 입장에서는 정체불명의 바이트 덩어리였다.
최종적으로 직접 미디어 루프를 유지하는 코드를 제거하고 pytapo.Downloader를 사용했다. 이 다운로더는 TS 구간을 분석하고 실제 녹화 길이에 맞춰 스트림을 종료한 뒤 ffmpeg로 MP4를 만든다.
수정 후 Ubuntu와 갤럭시 S22 Ultra의 Termux에서 같은 영상을 검증했다.
영상: H.264
음성: AAC
녹화 길이: 약 20.93초
결과: Ubuntu / Termux 모두 정상
몇 시간 동안 비밀번호, AES, Python 버전, ffmpeg를 의심했는데 범인은 잘못된 미디어 요청이었다. 네트워크 장비 리버스 엔지니어링은 늘 이런 식이다. 에러 메시지는 가장 시끄러운 곳에서 나오지만, 원인은 훨씬 앞에 숨어 있다.
갤럭시에서 서버 돌리기
남는 갤럭시 S22 Ultra를 작은 홈 서버처럼 사용하고 싶었다. Termux 안에 Ubuntu를 다시 설치할 수도 있지만, 이 프로젝트는 Termux에서 Python을 직접 실행하는 편이 단순하고 가볍다.
여기서도 한 번 순탄하게 끝나지는 않았다.
- Android용
cryptographywheel이 없어 Rust 빌드를 시도함 - Termux의
python-cryptography패키지를 사용해야 함 - 일반 가상환경에서는 시스템 패키지가 보이지 않음
- MP4 생성을 위해 ffmpeg가 필요함
pytapo.Downloader가 사용하는aiofiles가 별도로 필요함- 화면이 꺼졌을 때 프로세스가 죽지 않도록 wake lock이 필요함
이 문제를 줄이기 위해 Termux 전용 관리 스크립트를 만들었다.
./termux_h200_web install
./termux_h200_web start
./termux_h200_web status
./termux_h200_web stop
install과 start는 필요한 Termux 패키지와 Python 모듈을 확인하고 누락된 항목만 설치한다. 가상환경도 --system-site-packages 방식으로 만들어 Termux가 제공하는 cryptography를 사용할 수 있게 했다.
이제 TPLINK 욕 좀 하겠습니다
여기부터는 내가 직접 H200과 D230을 사용하며 겪은 경험에 대한 개인적인 평가다.
솔직히 말하면 고객을 똥으로 보는 회사다. 본인들이 약속한걸 지키지도 않았고 또 메일을 보내봤지만 답변도 안한다.
내가 산 도어벨이고, 내가 산 허브고, 내가 꽂은 저장장치에 기록된 내 영상이다. 그런데 그 영상을 외부에서 볼 수 없을뿐더러 PC에서 편하게 꺼내는 기본 도구가 없다. 로컬 저장을 내세우면서 실제 사용 경험은 앱 안에 데이터를 가둬 놓은 클라우드 서비스와 크게 다르지 않다.
장치 ID는 숨겨져 있고, H200과 D230은 부모·자식 구조로 나뉘어 있으며, 제어 API와 미디어 API는 따로 논다. 인증에는 admin, Camera Account, TP-Link 계정이 뒤섞인다. 잘못된 요청을 보내면 친절한 설명 대신 503, Invalid authentication data, wrong adaptation size 같은 메시지만 던진다.
물론 이 API는 공개 API가 아니다. 공식적으로 지원하지 않는 내부 동작을 억지로 사용하는 것이니 문서가 없고 언제든 바뀔 수 있다는 점은 이해한다. 하지만 바로 그게 욕먹을 지점이다. 사용자가 자기 로컬 녹화에 접근할 공식적인 방법을 제공했다면 내부 API를 뒤질 이유가 없었다.
앱에서 한두 개 영상을 보는 사람에게는 문제가 아닐 수 있다. 하지만 영상을 보관하고, 자동화하고, 여러 기기에서 관리하려는 순간 Tapo의 폐쇄적인 설계가 발목을 잡는다.
보안상 주의할 점
이 프로젝트는 H200의 내부 API에 접근하고 로컬 녹화 파일을 제공한다. Web UI 자체에는 로그인 기능이 없다.
따라서 다음 원칙은 반드시 지켜야 한다.
- Web UI를 공용 인터넷에 직접 노출하지 않기
- 신뢰할 수 있는 LAN 또는 WireGuard 안에서만 사용하기
.env, 로컬 JSON, key 파일을 Git에 올리지 않기- 녹화 영상과 로그를 공개 저장소에 커밋하지 않기
- 공유기에서 8092 포트를 무작정 포트 포워딩하지 않기
로컬 서비스라고 보안을 대충 다루면 현관 영상이 그대로 외부에 노출될 수 있다.
아직 하지 않은 것
현재 프로젝트의 중심은 녹화 목록 조회와 MP4 다운로드다. 실시간 스트리밍 기능은 아직 구현하지 않았다.
도어벨이 배터리 방식이라 스트리밍은 배터리소모가 크다.
그럼에도 불구하고 go2rtc 같은 도구와 연결해 실시간 스트림까지 한 화면에서 볼 수 있도록 확장할 생각이다. 다만 녹화 다운로드 과정에서 이미 H200의 단일 미디어 세션과 503 응답을 겪었기 때문에, 스트리밍과 다운로드의 동시 사용을 어떻게 조정할지가 다음 과제다.
또한 이 프로젝트는 공식 API가 아니라 커뮤니티 리버스 엔지니어링에 의존한다. Tapo 펌웨어나 내부 프로토콜이 변경되면 언제든 다시 깨질 수 있다.
마무리
처음 원했던 것은 내 도어벨 영상을 PC에 저장하는 단순한 기능이었다. 결과적으로 H200 제어 API, D230 child device, 미디어 세션, MPEG-TS, ffmpeg, Termux까지 건드리는 프로젝트가 됐다.
그래도 이제는 날짜를 고르고 버튼을 누르면 영상이 MP4로 저장된다. PC에서도 되고, 갤럭시에서도 된다. 제조사가 제공하지 않은 기능을 결국 내 손으로 만들었다.
TP LINK가 처음부터 외부망 접속, 로컬 녹화 내보내기 API 하나만 제대로 제공했으면 이 고생은 없었을 것이다.
하지만 제공하지 않았다.
그래서 만들었다.
'컴퓨터' 카테고리의 다른 글
| TCP 터널링으로 사내 웹페이지, RDP, SSH 사용하기(집에서 회사망 이용) (2) | 2026.06.29 |
|---|---|
| SK 통신사 모뎀 + iptime 공유기 환경에서 외부 VPN 접속 구축기 (WireGuard) (0) | 2026.05.04 |
| GitHub 대용량 모델 파일 관리: 자동 분할 및 병합 (2) | 2026.02.06 |
| 리눅스 터미널 환경 구성 (3) | 2025.06.19 |
| i9-13900k 언더볼팅 ASRock (274) | 2023.12.05 |