GitHub 트렌딩 딥다이브 · 2026-06-24 · TrendShift 라이브 멘션

mockfeed 딥다이브
— FFmpeg 플래그 20개를 외울 필요 없이, 명령 한 줄로 '가짜 라이브 영상'을 만들어 RTMP·SRT·UDP로 쏘는 CLI

mockfeed/mockfeed. AWS MediaLive·MediaConnect 같은 클라우드 영상 서비스를 연동·테스트하려면 실제 라이브 스트림이 필요한데, mockfeed는 입력 영상 파일 없이 컬러바·테스트 패턴을 즉석 생성해 RTMP/SRT/UDP 엔드포인트로 송출하는 파이썬 명령줄 도구다. 정체는 잘 설계된 FFmpeg 래퍼로, "왜 B프레임을 꺼야 하나, 왜 GOP를 2초로 맞춰야 하나" 같은 서비스별 인코더 요구사항을 프리셋(preset)으로 박제해, 손으로 FFmpeg 명령 20줄을 쓰고 디버깅하던 일을 mockfeed push --preset aws-medialive-rtmp 한 줄로 줄인다. 진짜 가치는 코드가 아니라 "스트리밍 도메인 지식의 깔끔한 코드화" — pydantic으로 설정을 타입세이프하게 검증하고, 순수 함수로 FFmpeg 명령을 조립하며, 스레드로 실시간 진행률을 그린다. (저장소: mockfeed/mockfeed · 언어 Python 3.13+ · 본체 ~1,700줄 + 테스트 ~2,657줄 · v0.1.0 · 라이선스 MIT · 저자 Israjur Rahman · 외부 의존 FFmpeg 6.0+ — TrendShift 라이브 멘션, r/VIDEOENGINEERING 화제)

목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석 (설정 한 줄이 송출되기까지)
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 시스템 요구사항 · 옵션
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

"입력 영상 없이 컬러바를 즉석으로 만들어, 클라우드 영상 서비스가 받아 줄 형식 그대로 라이브 송출한다."

한 줄로

mockfeed는 미디어 파일 없이도 '가짜 라이브 방송 신호'(컬러바·테스트 패턴 + 테스트 톤)를 즉석 생성해, RTMP/SRT/UDP로 클라우드 영상 서비스에 쏴 주는 FFmpeg 래퍼 CLI다 — "내 채널이 입력을 제대로 받나?"를 명령 한 줄로 확인하게 해 준다.

클라우드 영상 서비스(예: AWS MediaLive)를 설정하면, "정말 신호가 들어오나"를 확인할 라이브 입력이 필요합니다. 그런데 진짜 카메라·인코더를 띄우긴 번거롭고, 직접 FFmpeg를 쓰자니 플래그가 20개입니다 — 해상도·코덱·비트레이트·GOP·픽셀 포맷·오디오 프로파일·컨테이너… 하나라도 틀리면 채널이 조용히 입력을 거부하고, 그 이유를 반나절 디버깅하게 됩니다. mockfeed는 이 고통을 프리셋으로 없앱니다 — 서비스가 요구하는 정확한 인코딩 설정을 미리 박제해 두고, mockfeed push --preset aws-medialive-rtmp --destination rtmp://... 한 줄이면 올바른 형식의 컬러바 방송이 흘러갑니다. 입력 미디어 파일조차 필요 없습니다 — FFmpeg의 가상 신호 생성기(lavfi)로 컬러바·1kHz 톤을 그 자리에서 만들기 때문입니다.

용어
라이브 스트리밍 / ingest / 인코더 요구사항
라이브 스트리밍은 영상을 실시간으로 쪼개 네트워크로 흘려보내는 것입니다. 받는 쪽(클라우드 서비스)이 영상을 빨아들이는 입구를 ingest(인제스트)라 합니다. 문제는 ingest가 아무 영상이나 받지 않는다는 것 — "H.264 main 프로파일, 2초 GOP, B프레임 없음, AAC-LC 오디오, FLV 컨테이너"처럼 인코더 요구사항이 까다롭습니다. 이걸 맞추는 FFmpeg 명령을 손으로 쓰는 게 고통의 근원이고, mockfeed는 그 요구사항을 프리셋으로 대신 외워 줍니다.

README의 Before/After가 이 도구의 전부를 말해 줍니다 — 손으로 쓰던 FFmpeg 한 덩어리가 명령 한 줄로 줄어듭니다:

# Before: 손으로 쓰는 FFmpeg (외우기도 디버깅하기도 괴롭다)
ffmpeg -re -f lavfi -i smptebars=size=1920x1080:rate=30 \
  -f lavfi -i sine=frequency=1000:sample_rate=48000 \
  -map 0:v -map 1:a -c:v libx264 -preset veryfast -profile:v main \
  -b:v 5000k -maxrate 5000k -bufsize 10000k -g 60 -keyint_min 60 \
  -sc_threshold 0 -bf 0 -pix_fmt yuv420p \
  -c:a aac -profile:a aac_low -b:a 128k -ac 2 -ar 48000 \
  -f flv rtmp://your-medialive-endpoint/live/key

# After: mockfeed
mockfeed push --preset aws-medialive-rtmp --destination rtmp://your-endpoint/live/key

이 문서가 파고드는 건 사용법만이 아니라 그 안의 소프트웨어 설계입니다 — "프리셋이든 설정 파일이든 대화형이든 결국 하나의 검증 지점으로 모으는 법(pydantic 단일 진실원)", "FFmpeg 명령을 부수효과 없는 순수 함수로 만들어 테스트하는 법", "FFmpeg가 토해내는 진행 로그를 별도 스레드로 파싱해 실시간 대시보드를 그리는 법". 스트리밍 프로토콜과 깔끔한 CLI 설계를 한 레포에서 배우고 싶은 사람에게 좋은 소품입니다.

2왜 주목받는가

"영상 엔지니어라면 누구나 겪는 'FFmpeg 명령 지옥'을, 도메인 지식을 박제한 프리셋 CLI로 풀었다."

먼저, 푸는 문제 — 'FFmpeg는 강력하지만 외우기 괴롭다'

FFmpeg는 영상 처리의 만능 도구지만, 라이브 송출 명령은 플래그가 수십 개라 매번 다시 찾아보고, 틀리고, 디버깅하게 됩니다. 특히 클라우드 서비스마다 요구가 미묘하게 달라(RTMP는 FLV, SRT는 MPEG-TS, ABR엔 고정 GOP…), 한 번 맞춰 놓은 명령도 서비스가 바뀌면 무용지물입니다.

함정
"FFmpeg 명령 한 줄 복붙하면 되지"라는 착각

복붙한 명령은 왜 그렇게 썼는지를 담지 못합니다. -bf 0(B프레임 끔)이 왜 필요한지, -g 60(2초 GOP)이 왜 ABR에 중요한지, -sc_threshold 0(씬컷 키프레임 끔)이 왜 세그먼트 정렬에 필수인지를 모른 채 복붙하면, 해상도·프레임레이트가 바뀌는 순간 설정이 깨지고 채널이 조용히 입력을 거부합니다. 그 이유를 찾는 데 반나절이 날아갑니다.

해결
결정 근거까지 주석으로 박제한 프리셋 + 타입세이프 설정

mockfeed의 프리셋 YAML은 단순 설정이 아니라 "왜 이 값인가"를 AWS 문서 인용과 함께 주석으로 남긴 지식 캡슐입니다. 그리고 모든 설정을 pydantic 스키마로 검증해, 비트레이트 범위·코덱·프로토콜이 어긋나면 송출 전에 친절한 에러로 잡습니다. GOP는 fps × keyframe_interval_seconds로 자동 계산되니, 해상도를 바꿔도 설정이 깨지지 않습니다.

비결은 '코드가 아니라 도메인 지식이 자산'이라는 점

이 프로젝트가 영상 엔지니어 커뮤니티(r/VIDEOENGINEERING)에서 공감을 산 이유는 화려한 기능이 아니라 "우리가 매번 검색하던 그 지식을 깔끔히 정리해 줬다"는 데 있습니다.

설계 선택무엇을왜 좋은가
입력 미디어 0lavfi 가상 소스로 컬러바·톤 생성테스트용 영상 파일을 준비할 필요가 없음
프리셋에 근거 주석AWS 문서 URL + "왜 이 값"복붙이 아니라 학습이 됨
pydantic 검증범위·enum·교차필드 검사잘못된 설정을 송출 전에 차단
테스트가 본체보다 큼본체 1,700줄 vs 테스트 2,657줄FFmpeg 없이 명령 배열을 단언하는 품질 지향
비유

맨손 FFmpeg = 매번 백지에서 요리하기. 소금 몇 g, 몇 분 굽기를 매번 검색하고, 한 번 틀리면 처음부터 다시. 레시피를 적어 두지 않아 다음에 또 헤맵니다.

mockfeed = 검증된 레시피 카드(프리셋)를 꺼내 쓰는 것. "AWS MediaLive RTMP"라고 적힌 카드를 고르면 재료·불 세기가 다 정해져 있고, 카드 뒷면엔 '왜 B프레임을 빼는지'까지 적혀 있습니다. 게다가 재료를 잘못 넣으면(비트레이트 범위 초과) 요리 전에 알려 줍니다.

함정 (솔직하게)
아주 어리고, 얇고, 일부 기능은 '선언만' 돼 있다

냉정히 보면 mockfeed는 v0.1.0, 소스 14개 파일·~1,700줄, 프리셋 단 2개(MediaLive RTMP·MediaConnect SRT)의 갓 태어난 도구입니다. 화려한 기능보다 "깔끔한 코드화"가 가치입니다. 특히 타임코드/텍스트 오버레이(OverlayConfig)는 설정 스키마에만 있고 실제 FFmpeg 명령에 연결돼 있지 않습니다(=현재 동작 안 함). Dockerfile·CI 워크플로도 없습니다(이슈 템플릿만 존재). 파일 출력(MP4 녹화) 모드도 아직 없습니다. 즉 "스트리밍 도메인 지식 + CLI 설계 패턴"을 배우는 교본으로 보는 게 정확합니다.

3기술 스택 전체 지도

"파이썬 현대 도구 모음(uv·typer·pydantic·rich) + 시스템에 설치된 FFmpeg. 의존성 목록만 봐도 'CLI를 제대로 만들겠다'는 의도가 읽힌다."

mockfeed는 DB·네트워크 서버가 없는 순수 CLI 도구입니다. 핵심 의존성이 CLI·설정검증·터미널UI·FFmpeg 연동에 또렷이 몰려 있어, pyproject.toml이 곧 설계 의도입니다.

① 언어 · 패키징

구성내용
Python 3.13+requires-python = ">=3.13" — 최신 파이썬 강제
hatchling + uv빌드 백엔드 hatchling, 설치·관리는 uv(uv tool install git+...). 빠른 차세대 파이썬 도구체인
FFmpeg 6.0+런타임 외부 의존 — pip로 안 깔리고 시스템에 별도 설치 필요. mockfeed는 이걸 호출하는 래퍼

② CLI · 설정 · UI 핵심 4종

라이브러리역할한 줄 설명
typer ≥0.15CLI 프레임워크타입힌트로 서브커맨드(push/validate/presets) 정의. Click 기반
pydantic ≥2.0설정 검증모든 설정을 BaseModel + Literal/Field 제약으로 타입세이프 검증. 이 도구의 중추
rich ≥13.0터미널 UI실시간 진행률 패널·테이블·신택스 하이라이트
questionary ≥2.0대화형 프롬프트인자 없이 실행하면 화살표 메뉴로 설정을 묻는 대화형 폴백
pyyaml ≥6.0YAML 파싱프리셋·설정 파일을 yaml.safe_load로 읽음
용어
pydantic / 타입세이프 설정 / lavfi
pydantic은 파이썬에서 "데이터의 모양"을 클래스로 선언하면, 들어온 값이 그 규칙(타입·범위·허용값)에 맞는지 자동 검증해 주는 라이브러리입니다. bitrate_kbps를 "500~20000 정수"로 선언하면, 30000이 들어오는 순간 친절한 에러가 납니다 — 이게 타입세이프 설정입니다. lavfi는 FFmpeg의 가상 입력 장치로, smptebars(컬러바)·sine(사인파 톤)처럼 미디어 파일 없이 신호를 즉석 생성합니다. mockfeed가 "입력 영상이 필요 없는" 비결이 바로 이것입니다.

③ FFmpeg를 코드로 안전하게 구동하는 법

mockfeed의 FFmpeg 연동에는 보안·안정성 디테일이 있습니다.

기법설명
인자 리스트 + shell=False명령을 문자열이 아닌 ["ffmpeg","-re",...] 리스트로 subprocess.Popen에 넘겨 셸 인젝션 차단
-progress pipe:2FFmpeg가 stderr에 key=value 진행 블록을 토해내게 해, 머신리더블 진행률을 별도 스레드로 파싱
2단계 graceful shutdownCtrl-C → SIGTERM(트레일러 flush 시간) → 5초 후 SIGKILL. 두 번째 Ctrl-C는 즉시 종료
URL 화이트리스트validators.py가 scheme(rtmp/srt/udp…)을 화이트리스트로 막고, 위험 IP·미설정 sentinel 호스트 감지

④ 개발 품질 도구 — "테스트가 본체보다 크다"

이 작은 프로젝트의 진짜 인상적인 부분입니다. 개발 도구로 pytest ≥8, ruff ≥0.9(린트+포맷), pyright(strict 타입체크)를 쓰고, 테스트 코드가 ~2,657줄로 본체(~1,700줄)보다 큽니다. 비결은 명령 빌더를 순수 함수로 만들어 FFmpeg 실행 없이 "인자 배열이 올바른가"만 단언하는 것 — 실제 ffmpeg가 필요한 테스트는 integration 마커로 분리해 평소엔 제외합니다.

4아키텍처 심화 분석 (설정 한 줄이 송출되기까지)

"입력 3종(프리셋·파일·대화형) → 단일 검증 지점(FeedConfig) → 순수 함수로 명령 조립 → 프로세스 감시 → 실시간 대시보드. 한 방향으로 흐른다."

전체 데이터 흐름 한 장

┌─────────────── 입력 경로 3종 ───────────────┐ (A) push --preset │ presets/registry.py : 번들 YAML 로드 │ (B) push --config │ config/loaders.py : 파일 YAML 로드 │ ─┐ (C) mockfeed(무인자)│ interactive.py : 대화형 프롬프트 │ │ └────────────────────────────────────────────┘ │ │ CLI 플래그 오버라이드 │ ▼ (--resolution 등 병합) │ ┌───────────────────────────────────────────────────┐ │ │ pydantic FeedConfig (config/feed_config.py) │ ◀──────┘ │ = 단일 진실원(single source of truth) │ │ · VideoConfig(해상도/코덱/비트레이트/패턴…) │ │ · list[AudioTrack] (1~8 트랙) │ │ · OutputConfig(protocol→container 자동 도출) │ │ · validators : URL scheme 화이트리스트 + IP 차단 │ └───────────────────────────────────────────────────┘ │ ▼ ┌───────────────────────────────────────────────────┐ │ ffmpeg/command_builder.py : build_command() │ │ FeedConfig → ["ffmpeg","-re","-f","lavfi", …] │ │ · 해상도→W×H×fps, GOP = fps × keyframe_interval │ │ · bufsize = bitrate × 2 (순수 함수, 부수효과 0) │ └───────────────────────────────────────────────────┘ │ list[str] ▼ ┌───────────────────────────────────────────────────┐ │ ffmpeg/runner.py : FeedRunner.run() │ │ subprocess.Popen(shell=False, stderr=PIPE) │ │ ├─ [메인] process.wait(), Ctrl-C → TERM→KILL │ │ └─ [reader 스레드] stderr 줄 → │ │ progress_parser.py(key=value 누적) → 콜백 │ └───────────────────────────────────────────────────┘ │ ProgressEvent ▼ ┌───────────────────────────────────────────────────┐ │ output/reporter.py : rich.live.Live 대시보드 │ │ fps · bitrate · speed · elapsed · drop/dup 실시간 │ └───────────────────────────────────────────────────┘ ▼ RTMP / RTMPS / SRT / UDP 송출

설계 ① — 단일 진실원(pydantic FeedConfig): 입력이 셋이어도 검증은 한 곳

가장 핵심적인 설계입니다. 프리셋이든 설정 파일이든 대화형이든, 모든 입력은 결국 하나의 FeedConfig 객체로 수렴합니다. 검증·명령생성은 그 뒤 한 군데서만 일어나므로, 입력 경로가 늘어나도 빌드 로직은 건드릴 필요가 없습니다.

# config/feed_config.py — 범위·허용값을 타입으로 강제
class VideoConfig(BaseModel):
    resolution: Literal["480p30","720p30","720p60","1080p30","1080p60"] = "1080p30"
    codec: Literal["h264","hevc"] = "h264"
    bitrate_kbps: int = Field(5000, ge=500, le=20000)   # 500~20000만 허용
    keyframe_interval_seconds: int = Field(2, ge=1, le=10)
    pattern: Literal["smptebars","testsrc2","mandelbrot","color"] = "smptebars"

class OutputConfig(BaseModel):
    protocol: Literal["rtmp","rtmps","srt","udp"]
    # protocol → container 자동 도출 (rtmp→flv, srt/udp→mpegts)

설계 ② — 명령 빌더와 실행기의 분리: 순수 함수 vs I/O

build_command()부수효과가 전혀 없는 순수 함수입니다 — FeedConfig를 받아 FFmpeg 인자 리스트를 돌려줄 뿐, 파일도 안 만들고 프로세스도 안 띄웁니다. 그래서 FFmpeg를 실행하지 않고도 "인자 배열이 올바른가"를 테스트할 수 있습니다. 실제 I/O·시그널은 FeedRunner가 따로 담당합니다.

# ffmpeg/command_builder.py (개념)
def build_command(config: FeedConfig) -> list[str]:
    w, h, fps = _RESOLUTION_SPECS[config.video.resolution]
    gop = fps * config.video.keyframe_interval_seconds      # GOP 자동 계산
    args = ["ffmpeg","-re","-f","lavfi","-i",
            f"{config.video.pattern}=size={w}x{h}:rate={fps}", ...]
    args += ["-b:v",f"{br}k","-maxrate",f"{br}k",
             "-bufsize",f"{br*2}k",                          # CBR + 버퍼 2배
             "-g",str(gop),"-keyint_min",str(gop),
             "-sc_threshold","0","-bf","0", ...]             # 씬컷·B프레임 끔
    return args   # 부수효과 0 → 테스트가 이 배열만 단언

설계 ③ — 스레드 기반 비차단 진행률

메인 스레드는 process.wait()로 FFmpeg 종료를 기다리고, 별도 데몬 스레드가 FFmpeg의 stderr를 한 줄씩 읽어 진행률을 파싱합니다. -progress pipe:2가 토해내는 key=value 블록을 상태머신으로 누적하다가, progress=continue|end를 만나면 한 이벤트로 묶어 콜백을 호출합니다. = 없는 일반 로그 줄은 무시하므로, 로그와 진행률이 섞여 와도 견고합니다.

설계 ④ — 프로토콜 → 컨테이너 자동 도출

사용자는 "RTMP로 보낼래"만 고르면 됩니다. 컨테이너(FLV/MPEG-TS)는 프로토콜에서 자동으로 정해집니다.

protocolcontainer비고
rtmp / rtmpsflv라이브 송출 표준(대부분 클라우드). rtmps는 RTMP over TLS
srtmpegts저지연·손실 복원 전송. mockfeed는 caller로 동작(listener에 접속). ?latency=2000000(μs) 같은 쿼리를 그대로 전달
udpmpegtsraw UDP, 로컬·LAN 스모크테스트(ffplay udp://127.0.0.1:5000로 수신)
설계 철학 한 줄

"입력은 여럿이어도 진실은 하나로(FeedConfig). 명령 생성은 순수하게(테스트 가능), 실행은 따로(I/O·시그널). 도메인 지식은 주석으로 박제한다."

이 셋이 mockfeed를 관통합니다 — 단일 진실원(프리셋·파일·대화형이 한 객체로 수렴), 순수 함수 + I/O 분리(FFmpeg 없이 명령을 단언, 그래서 테스트가 본체보다 큼), 근거를 남기는 프리셋(복붙이 아니라 학습). 작지만 "잘 설계된 CLI란 무엇인가"의 좋은 표본입니다.

5디렉토리 구조 해부

"패키지 본체 14개 파일이 config / ffmpeg / output / presets로 깔끔히 갈린다. 가장 중요한 건 스키마·명령빌더·프리셋 YAML 세 곳."

mockfeed/ (저장소 루트) ├── README.md Before/After·설치·Quickstart ├── pyproject.toml 의존성·진입점·ruff/pyright/pytest 설정 ├── uv.lock 의존성 잠금 ├── Makefile install/test/lint/format (uv 래핑) ├── LICENSE MIT (Israjur Rahman) ├── IDEAS.md 실사용 마찰점 기록용 빈 템플릿(도그푸딩) ├── docs/USAGE.md 전 명령·전 스키마·프리셋·FAQ (매우 충실) ├── examples/ │ ├── rtmp_template.yaml RTMP 설정 템플릿 │ └── udp_localhost.yaml 로컬 UDP 스모크테스트(30s) │ ├── mockfeed/ ── 패키지 본체(~1,700줄) ── │ ├── __main__.py python -m mockfeed 진입점 │ ├── cli.py (381) ★ Typer 앱: push / validate / presets / version │ ├── interactive.py (397) questionary 대화형 플로우 + 검증 │ ├── config/ │ │ ├── feed_config.py (96) ★ pydantic 스키마(Video/Audio/Output/Feed) │ │ ├── loaders.py (136) 파일/프리셋 로드 + CLI 오버라이드 병합 │ │ └── validators.py (57) URL scheme 화이트리스트 + 위험 IP 차단 │ ├── ffmpeg/ │ │ ├── command_builder.py (161) ★ FeedConfig → ffmpeg 인자(순수 함수) │ │ ├── runner.py (141) subprocess 감시 + 시그널 + 스레드 │ │ └── progress_parser.py (103) -progress 스트림 상태머신 파서 │ ├── output/ │ │ └── reporter.py (140) rich 라이브 패널 + 설정/요약 패널 │ └── presets/ │ ├── registry.py (78) 번들 YAML lazy 로딩 │ ├── aws_medialive_rtmp.yaml ★ AWS 문서 인용 주석 포함 │ └── aws_mediaconnect_srt_listener.yaml │ └── tests/ ── ~2,657줄, 본체보다 크다 ── ├── unit/ (cli·command_builder·config_validation·loaders· │ preset_registry·progress_parser·interactive) └── integration/test_runner.py (마커 "integration" = 실제 ffmpeg 구동)
용어
순수 함수(pure function) / 통합 테스트 마커
순수 함수는 "같은 입력이면 항상 같은 출력, 그리고 바깥 세상을 건드리지 않는(파일·네트워크·전역상태 변경 없음)" 함수입니다. build_command가 그 예로, FeedConfig를 넣으면 인자 배열만 돌려줍니다 — 그래서 FFmpeg 없이도 결과를 단언할 수 있어 테스트가 쉽고 빠릅니다. 반대로 실제 ffmpeg를 띄우는 무거운 테스트는 pytest 마커 integration으로 표시해, 평소엔 -m "not integration"으로 건너뜁니다. "빠른 단위 테스트 vs 느린 통합 테스트"를 가르는 전형적 기법입니다.

가장 중요한 세 파일

config/feed_config.py(스키마) · ffmpeg/command_builder.py(명령 생성) · presets/*.yaml(박제된 지식)이 mockfeed의 삼각편대입니다. 스키마가 "무엇이 올바른 설정인가"를 정의하고, 빌더가 "그 설정을 FFmpeg 언어로 번역"하며, 프리셋이 "현업이 검증한 정답값"을 담습니다. 나머지(cli·interactive·runner·reporter)는 이 셋을 사용자와 잇는 배관입니다.

6학습 포인트 (기술별 — 배울 것 + 실습 아이디어)

"라이브 스트리밍 프로토콜·FFmpeg 안전 구동·pydantic 설계·CLI 설계·순수함수 테스트가 한 레포에 압축돼 있다."

① 라이브 스트리밍 프로토콜 실전 지식

배울 것: RTMP→FLV, SRT→MPEG-TS 매핑, SRT의 caller/listener 모델과 latency를 마이크로초로 주는 이유, ABR(적응형 비트레이트)을 위한 고정 GOP 정렬과 씬컷 키프레임 비활성화. 단순 개념이 아니라 "왜 클라우드 ingest가 거부하는가"라는 실패 중심.

실습: ffplay udp://127.0.0.1:5000를 띄워 두고 mockfeed로 UDP 송출 → 화면에 컬러바가 뜨는지 확인. 같은 영상을 RTMP로 바꿔 보내 컨테이너가 FLV로 바뀌는 걸 명령에서 확인.

② FFmpeg를 코드로 안전하게 구동

배울 것: shell=False + 인자 리스트로 셸 인젝션 차단, lavfi 가상 소스로 입력 파일 없이 신호 생성, -progress pipe:2로 머신리더블 진행률 받기, SIGTERM→SIGKILL 2단계 graceful shutdown.

실습: 파이썬 subprocess.Popen으로 FFmpeg를 띄우고 stderr를 별도 스레드로 읽어 진행률을 출력. Ctrl-C 시 SIGTERM을 보내고 5초 후 SIGKILL하는 종료 로직을 구현.

③ pydantic v2로 설정을 타입세이프하게

배울 것: Literal로 enum 강제, Field(ge=,le=)로 범위, @model_validator(mode="after")로 교차필드 검증(scheme↔protocol↔container 일관성), model_copy(update=)로 불변 병합. "잘못된 입력을 일찍, 친절하게 막는" 설계.

실습: pydantic으로 "비트레이트 500~20000, 코덱은 h264/hevc만" 같은 설정 모델을 만들고, 범위를 벗어난 값을 넣어 에러 메시지를 관찰. 두 필드의 일관성을 검사하는 validator를 추가.

④ 잘 설계된 CLI — Typer + 대화형 폴백

배울 것: Typer로 서브커맨드(push/validate/presets) 구성, 인자 없이 실행하면 questionary 대화형으로 폴백, 상호배타 옵션 처리, 의미 있는 exit code, rich 라이브 대시보드.

실습: Typer로 "인자를 주면 그대로 실행, 안 주면 화살표 메뉴로 묻는" 미니 CLI를 만들기. rich의 Live로 1초마다 갱신되는 진행 패널을 붙여 보기.

⑤ "순수 함수 + I/O 분리" 테스트 전략

배울 것: 핵심 로직(build_command)을 부수효과 없는 함수로 만들어 외부 도구 없이 단언, 실제 ffmpeg가 필요한 테스트는 integration 마커로 분리. 그 결과 테스트 코드가 본체보다 커진 품질 문화.

실습: 내 코드에서 "데이터 → 명령/쿼리 문자열"을 만드는 부분을 순수 함수로 떼어내, 외부 실행 없이 출력만 검증하는 단위 테스트를 작성. 무거운 통합 테스트엔 pytest 마커를 달기.

⑥ 도메인 지식의 코드화 + 보안 감각

배울 것: 프리셋 YAML 주석에 결정 근거 + 1차 출처(AWS 문서 URL)를 남기는 문서화 문화, IDEAS.md로 마찰점을 기록하는 도그푸딩, 그리고 URL scheme 화이트리스트·위험 IP 차단·sentinel 호스트 감지 같은 입력 검증 보안.

실습: 자주 쓰는 복잡한 명령(예: 백업·배포 스크립트)을 "근거 주석이 달린 프리셋"으로 정리해 보기. 사용자 입력 URL을 받을 때 scheme 화이트리스트로 거르는 검증기를 작성.

7시스템 요구사항 · 옵션

"무거운 인프라 0. 파이썬 3.13 + uv + 시스템 FFmpeg면 끝. GPU·DB·클라우드 계정도 (테스트만이면) 불필요."

항목요구사항 / 메모
런타임Python 3.13+ + FFmpeg 6.0+(시스템에 별도 설치). FFmpeg가 실제 인코딩·송출을 수행
설치uv 권장: uv tool install git+https://github.com/mockfeed/mockfeed
외부 서비스테스트 목적이면 불필요(UDP/로컬). 실제 클라우드 송출 시 RTMP/SRT 엔드포인트 필요
지원 패턴smptebars(컬러바·기본) · testsrc2(프레임 카운터 움직임) · mandelbrot · color(단색)
오디오 소스sine_1khz(테스트 톤·기본) · silence · pink_noise. 멀티트랙 1~8개 지원
코덱비디오 h264(libx264)/hevc(libx265) · 오디오 aac/ac3/mp2
해상도480p30·720p30·720p60·1080p30·1080p60
주요 옵션--preset·--config·--destination·--resolution·--bitrate·--duration 등. validate로 송출 전 점검
조작 / 운용 팁
"먼저 UDP로 로컬 점검 → 그다음 클라우드"

examples/udp_localhost.yaml처럼 UDP 로컬 송출로 먼저 스모크테스트하면, 클라우드 비용·네트워크 변수 없이 "내 mockfeed가 제대로 도는가"를 확인할 수 있습니다. ffplay udp://127.0.0.1:5000로 받아 컬러바가 뜨면 통과. 그다음 같은 설정의 protocol만 RTMP/SRT로 바꿔 실제 엔드포인트로 보냅니다.

함정 — 기대치 조정
'선언만 된' 기능과 없는 기능을 구분하라

현재 버전(v0.1.0)에서 타임코드/텍스트 오버레이는 스키마에만 있고 동작하지 않습니다(OverlayConfig가 빌더에 연결 안 됨). 파일 출력(MP4 녹화) 모드도 없고(FAQ에 "향후"), 프리셋은 2개(MediaLive RTMP·MediaConnect SRT)뿐이며, Dockerfile·CI도 없습니다. 즉 "지금 당장의 만능 송출 도구"가 아니라 "핵심 골격이 잘 잡힌 초기 도구 + 좋은 학습 교본"으로 기대하세요. 바로 이 빈칸들이 아래 실습 과제의 좋은 재료입니다.

8직접 해볼 수 있는 실습 과제

"UDP 로컬 송출 → 맨손 FFmpeg와 비교 → 세 번째 프리셋 추가 → 미완성 오버레이 완성 → 미니 mockfeed 만들기."

과제 1난이도 ★☆☆☆☆ · 입문

UDP 로컬 송출로 컬러바 띄우기

mockfeed를 설치하고 ffplay udp://127.0.0.1:5000를 띄운 뒤, examples/udp_localhost.yaml 또는 mockfeed push --config ...로 송출. ffplay 창에 SMPTE 컬러바와 1kHz 톤이 나오는지 확인.

목표: "입력 영상 없이 즉석 신호 송출"을 체감. validate 명령으로 송출 전 설정 점검도 해 보기.

과제 2난이도 ★★☆☆☆ · 초급

생성된 FFmpeg 명령을 맨손 명령과 비교하기

mockfeed가 만든 FFmpeg 인자(소스의 build_command 또는 verbose 출력)를 README의 Before 명령과 나란히 놓고, 각 플래그가 어떤 설정에서 나왔는지 매핑. -gfps × keyframe_interval임을 직접 계산해 확인.

목표: 프리셋이 "박제한 지식"을 역추적해 FFmpeg 라이브 송출 플래그를 스스로 이해. 해상도를 바꿔 GOP가 따라 바뀌는지 확인.

과제 3난이도 ★★★☆☆ · 중급

세 번째 프리셋(YouTube Live / Twitch) 추가하기

presets/에 새 YAML을 만들어 YouTube Live나 Twitch의 RTMP 요구사항(비트레이트·GOP·오디오)을 박제. 기존 두 프리셋처럼 "왜 이 값인지" 근거 주석과 1차 출처 URL을 함께 남기고, registry가 인식하는지 mockfeed presets로 확인.

목표: 프리셋 구조와 registry 로딩을 이해. 도메인 지식을 "근거가 달린 설정"으로 코드화하는 연습.

과제 4난이도 ★★★★☆ · 중상

미완성 오버레이(타임코드/텍스트) 실제로 연결하기

스키마에만 있고 동작 안 하는 OverlayConfigbuild_command()에 연결한다 — FFmpeg drawtext 필터로 타임코드/텍스트 번인을 추가. 순수 함수이므로 단위 테스트로 인자 배열을 먼저 단언한 뒤 실제 송출로 확인.

목표: "선언만 된 기능"을 완성하며 명령 빌더·필터그래프·테스트 흐름을 한 번에 경험. 실제 오픈소스 기여 후보.

과제 5난이도 ★★★★★ · 고급

'미니 mockfeed' 처음부터 만들기

pydantic 설정 모델 + 순수 명령 빌더 + subprocess 러너 + rich 진행 패널을 직접 조립해, 컬러바를 UDP로 쏘는 작은 도구를 완성한다. -progress pipe:2 파싱과 SIGTERM→SIGKILL 종료까지 넣으면 구조가 거의 같아진다.

목표: "입력→검증→명령→실행→표시"의 단방향 파이프라인을 손으로 완성. mockfeed 전체 설계를 내 것으로 만들기.

9관련 기술 심화 학습 로드맵 (5주 플랜)

"FFmpeg 기초에서 출발해 라이브 프로토콜·pydantic·CLI 설계·테스트 전략까지, mockfeed를 길잡이 삼아."

주차주제핵심 학습 + mockfeed 연결점
1주FFmpeg 기초 + lavfi입력/필터/인코딩/출력 모델, lavfi 가상 소스, -re 실시간 → command_builder.py
2주라이브 스트리밍 프로토콜RTMP/FLV·SRT/MPEG-TS·UDP, GOP·CBR·B프레임·씬컷 → 프리셋 YAML
3주pydantic v2 설정 검증Literal·Field·model_validator·model_copy → config/feed_config.py
4주CLI + subprocess + 스레드Typer·questionary·Popen(shell=False)·진행률 파싱·graceful shutdown → cli.py·runner.py
5주테스트 전략 + 도구체인순수함수 단위테스트·integration 마커·ruff·pyright·uv → tests/·pyproject.toml
비유

이 로드맵은 "영상 스트리밍 도메인 + 현대 파이썬 CLI 설계"를 한 줄로 꿴 코스입니다. mockfeed가 작고(본체 ~1,700줄) 잘 정돈돼 있어, FFmpeg와 라이브 프로토콜이라는 "막막한 분야"를 읽을 만한 코드로 안내해 줍니다 — 미디어 엔지니어링에 입문하거나, "잘 만든 CLI 도구"의 골격을 익히려는 사람에게 알맞은 교재입니다.

10핵심 키워드 사전

"이 문서와 저장소에서 반복되는 스트리밍·FFmpeg·파이썬 용어를 한곳에 모았다."

용어의미
RTMP / RTMPSReal-Time Messaging Protocol(+TLS). 라이브 송출 표준, 컨테이너는 FLV
SRTSecure Reliable Transport. 손실 네트워크에서 신뢰성·저지연 전송. caller/listener 모델, latency는 μs
UDP / MPEG-TSraw UDP 송출, 컨테이너는 MPEG transport stream. 로컬·LAN 테스트용
ingest받는 쪽이 라이브 영상을 빨아들이는 입구. 인코더 요구사항이 까다로움
AWS MediaLive / MediaConnectAWS Elemental 클라우드 영상 ingest·전송 서비스. mockfeed 프리셋의 타깃
lavfiFFmpeg 가상 입력. smptebars·testsrc2·sine·anullsrc 등 미디어 파일 없이 신호 생성
GOP (Group of Pictures)키프레임(IDR) 사이 프레임 묶음. GOP = fps × keyframe_interval. ABR 세그먼트 정렬에 필수
CBR / VBRConstant/Variable BitRate. mockfeed는 -b:v=-maxrate로 CBR 강제(클라우드 ingest가 예측가능 대역폭 요구)
B-frame양방향 예측 프레임. 압축률↑이나 디코더가 GOP를 버퍼링 → 지연↑. 라이브는 0 권장
AAC-LC (aac_low)AAC Low Complexity 프로파일. AWS Elemental이 명시적으로 요구
smptebars / testsrc표준 SMPTE 컬러바 / 프레임 카운터가 있는 테스트 패턴
pix_fmt yuv420p4:2:0 크로마 서브샘플링. 대부분 디코더 호환을 위한 요구
sc_threshold 0씬 변화 시 자동 키프레임 삽입 비활성화 → GOP 경계 고정
bufsize / maxrate레이트 컨트롤 버퍼·상한. mockfeed는 bufsize = bitrate × 2
pydantic파이썬 데이터 검증 라이브러리. 타입·범위·허용값으로 설정을 송출 전에 검증
Typer / questionary / richCLI 프레임워크 / 대화형 프롬프트 / 터미널 UI(라이브 대시보드)
uv / hatchling차세대 파이썬 패키지·도구 관리자 / 빌드 백엔드
순수 함수 / integration 마커부수효과 없는 함수(테스트 쉬움) / 실제 ffmpeg가 필요한 느린 테스트 분리 표식
graceful shutdownCtrl-C → SIGTERM(트레일러 flush) → 5초 후 SIGKILL의 2단계 우아한 종료

11참고 링크