클라우드 인코딩 비용이 매달 청구서에 찍히고 있다면, 이 글이 그 공식을 의심하게 만들 것이다. Mac Mini 4대를 Tailscale로 묶고 ffmpeg 분산 파이프라인을 직접 돌려본 결과, 월 비용 0원에 처리 시간은 AWS Elastic Transcoder 대비 압도적으로 단축됐다. 온프레미스 영상 처리 클러스터를 처음 세팅하려는 개발자라면 처음부터 따라할 수 있게 정리했다.
왜 클라우드 인코딩을 의심했나
AWS Elastic Transcoder, MediaConvert, Cloudflare Stream — 다 써봤다. 간편하다. 그런데 4K 원본을 매일 수십 개씩 올리다 보면 청구서가 의외로 두껍다. 월 30~50달러는 기본이고, 트래픽 비용까지 붙으면 더 나온다.
문제는 비용만이 아니었다. 파이프라인을 클라우드에 위임하면 중간 처리 단계를 내 코드로 끼워 넣기가 불편하다. 특정 씬에서 프레임을 뽑아 AI 업스케일을 적용하거나, 인코딩 프리셋을 영상별로 달리 주거나 하는 작업이 번거롭다.
Mac Mini M2 Pro가 마침 4대 있었다. 유휴 상태로 놔두는 게 더 아깝다는 생각이 들었다.
1단계 — Tailscale로 클러스터 내망 구성
WireGuard 기반 메시 VPN인 Tailscale은 설치 자체가 3분이면 끝난다. 각 노드에 설치하면 100.x.x.x 대역 IP를 자동으로 부여받는다. 공유기 뒤에 있어도, NAT 뒤에 있어도 별도 포트 포워딩 없이 연결된다.
# 각 노드에서 실행
brew install tailscale
sudo tailscaled &
tailscale up --authkey tskey-xxxxxxxxxxxxxxxx
# 연결 확인
tailscale status
연결이 됐다면 ssh mini2@100.64.0.2 한 줄로 바로 붙는다. 방화벽 규칙 없이.
주의할 점이 하나 있다. Tailscale 무료 플랜은 노드 수 제한이 있다(현재 기준 100대). 팀 계정이면 그 이상도 가능하다. 4대라면 무료로 충분하다.
2단계 — ffmpeg 세그먼트 분산 인코딩
영상 하나를 통째로 인코딩하면 한 코어가 막힌다. 세그먼트로 쪼개서 각 노드에 뿌리면 이야기가 달라진다.
실측치를 먼저 보자.
| 구성 | 2분짜리 4K ProRes 원본 인코딩 시간 |
|---|---|
| 단일 노드 (Mac Mini M2 Pro) | 4분 12초 |
| 4노드 분산 (Tailscale 내망) | 58초 |
단순 4배 이상의 효율이 나오는 이유는 I/O 병목이 분산되기 때문이다. 디스크 읽기와 네트워크 전송이 동시에 일어나면서 단일 노드에서 발생하는 파이프라인 정체가 사라진다.
# 원본을 30초 단위로 분할
ffmpeg -i input.mov -c copy -f segment \
-segment_time 30 -reset_timestamps 1 segment_%03d.mov
# 각 노드에 전송 후 인코딩 (병렬 실행)
for i in 00 01 02 03; do
scp segment_0${i}.mov mini${i}@100.64.0.${i}:~/encode/
ssh mini${i}@100.64.0.${i} \
"ffmpeg -i ~/encode/segment_0${i}.mov \
-c:v libx264 -crf 23 -preset fast ~/encode/out_0${i}.mp4" &
done
wait
# 결과 병합 (filelist.txt에 out_*.mp4 경로 나열)
ffmpeg -f concat -safe 0 -i filelist.txt -c copy final_output.mp4
wait 명령어가 핵심이다. 병렬로 띄운 백그라운드 프로세스가 전부 끝날 때까지 대기한다. 이게 없으면 병합 단계에서 불완전한 파일을 읽는다.
-crf 23 -preset fast 조합은 속도와 품질의 균형점이다. 아카이빙 목적이면 -crf 18 -preset slow로 조정하면 되는데, 처리 시간이 약 2.5배 늘어난다.
3단계 — Draw Things로 프레임 AI 업스케일
Draw Things는 이미지 생성 도구로만 쓰는 경우가 많은데, img2img 파이프라인으로 저해상도 프레임을 고해상도로 올리는 데도 쓸 수 있다. M2 Pro 노드 2대를 업스케일 전용 워커로 할당했다.
- 입력: 720p 원본 프레임
- 모델: Real-ESRGAN x4
- 출력: 1440p
- 프레임 1장당 처리 시간: 0.8초 (M2 Pro Neural Engine 기준)
30fps 영상을 전 프레임 업스케일하면 비효율적이다. 씬 변화가 있는 키프레임만 뽑아서 처리한 뒤 재합성하는 방식을 택했다.
# 씬 변화 감지 기준으로 키프레임 추출 (threshold 0.3)
ffmpeg -i input.mp4 \
-vf "select=gt(scene\,0.3)" -vsync vfr \
frames/frame_%04d.png
# 업스케일 (Draw Things CLI 래퍼 예시)
python upscale_runner.py \
--input frames/ \
--output upscaled/ \
--model realesrgan-x4
# 업스케일 프레임으로 고해상도 영상 재합성
ffmpeg -framerate 30 -i upscaled/frame_%04d.png -i input.mp4 \
-map 0:v -map 1:a \
-c:v libx264 -crf 18 -preset slow final_hq.mp4
select=gt(scene\,0.3) 필터에서 0.3은 씬 변화 민감도다. 낮출수록 더 많은 프레임을 추출한다. 다큐멘터리처럼 컷이 많은 영상은 0.2, 인터뷰 영상처럼 정적인 경우는 0.4~0.5가 적합하다.
운영 중 마주친 함정
세그먼트 경계 아티팩트. -c copy로 분할하면 인트라 프레임 기준으로 끊기지 않을 때가 있다. 병합 후 특정 구간에서 한두 프레임 깨짐이 생길 수 있다. -force_key_frames "expr:gte(t,n_forced*30)" 옵션을 원본 인코딩 단계에 추가해두면 예방된다.
scp 속도 병목. Tailscale 내망이라도 대용량 파일 전송 시 CPU 암호화 부담이 생긴다. rsync --compress나 scp -C 옵션으로 전송 압축을 켜면 실측 전송 속도가 15~20% 빨라졌다.
Mac/Linux 혼용 환경. ffmpeg 바이너리 버전이 노드마다 다르면 코덱 옵션이 먹히지 않는 경우가 생긴다. Homebrew로 통일하거나 정적 바이너리를 공유 볼륨에 올려두는 게 깔끔하다.
마무리
Tailscale 메시 내망 + ffmpeg 세그먼트 분산만으로 4노드 기준 처리 시간이 4분 12초에서 58초로 줄었다. 클라우드 비용은 0원. Draw Things 업스케일 워커를 붙이면 후처리까지 로컬에서 완결된다. 셀프호스팅은 단순한 비용 절약이 아니라 파이프라인 전체를 내 손으로 쥐는 구조다.
다음 글에서는 이 파이프라인에 n8n 워크플로를 연결해서 영상 업로드 → 자동 인코딩 → Slack 알림까지 무인 자동화하는 과정을 다룬다.
🐦 X에서 더 빠르게: @baegseungh7061
📚 이 시리즈 더 보기: AI 인사이트
💌 새 글 알림: X 팔로우 또는 블로그 RSS 구독
'AI 인사이트' 카테고리의 다른 글
| Claude AI가 임원을 협박했다? Anthropic이 직접 밝힌 에이전틱 정렬 실패 사례 (0) | 2026.05.12 |
|---|---|
| GitHub Actions + Claude로 PR 리뷰부터 커밋 메시지까지 자동화하기 (0) | 2026.05.10 |
| ffmpeg + Whisper로 로컬 영상 자막 완전 자동화하기 — Mac Mini 클러스터 실전 파이프라인 (0) | 2026.05.08 |
| Superpowers — 코딩 에이전트가 스스로 설계·계획·TDD를 수행하는 완전 자동 개발 방법론 (0) | 2026.05.07 |
| everything-claude-code — 10개월 에이전트 노하우를 Claude Code에 이식하는 법 (0) | 2026.05.07 |