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 화제)
"입력 영상 없이 컬러바를 즉석으로 만들어, 클라우드 영상 서비스가 받아 줄 형식 그대로 라이브 송출한다."
클라우드 영상 서비스(예: AWS MediaLive)를 설정하면, "정말 신호가 들어오나"를 확인할 라이브 입력이 필요합니다. 그런데 진짜 카메라·인코더를 띄우긴 번거롭고, 직접 FFmpeg를 쓰자니 플래그가 20개입니다 — 해상도·코덱·비트레이트·GOP·픽셀 포맷·오디오 프로파일·컨테이너… 하나라도 틀리면 채널이 조용히 입력을 거부하고, 그 이유를 반나절 디버깅하게 됩니다. mockfeed는 이 고통을 프리셋으로 없앱니다 — 서비스가 요구하는 정확한 인코딩 설정을 미리 박제해 두고, mockfeed push --preset aws-medialive-rtmp --destination rtmp://... 한 줄이면 올바른 형식의 컬러바 방송이 흘러갑니다. 입력 미디어 파일조차 필요 없습니다 — FFmpeg의 가상 신호 생성기(lavfi)로 컬러바·1kHz 톤을 그 자리에서 만들기 때문입니다.
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 설계를 한 레포에서 배우고 싶은 사람에게 좋은 소품입니다.
"영상 엔지니어라면 누구나 겪는 'FFmpeg 명령 지옥'을, 도메인 지식을 박제한 프리셋 CLI로 풀었다."
FFmpeg는 영상 처리의 만능 도구지만, 라이브 송출 명령은 플래그가 수십 개라 매번 다시 찾아보고, 틀리고, 디버깅하게 됩니다. 특히 클라우드 서비스마다 요구가 미묘하게 달라(RTMP는 FLV, SRT는 MPEG-TS, ABR엔 고정 GOP…), 한 번 맞춰 놓은 명령도 서비스가 바뀌면 무용지물입니다.
복붙한 명령은 왜 그렇게 썼는지를 담지 못합니다. -bf 0(B프레임 끔)이 왜 필요한지, -g 60(2초 GOP)이 왜 ABR에 중요한지, -sc_threshold 0(씬컷 키프레임 끔)이 왜 세그먼트 정렬에 필수인지를 모른 채 복붙하면, 해상도·프레임레이트가 바뀌는 순간 설정이 깨지고 채널이 조용히 입력을 거부합니다. 그 이유를 찾는 데 반나절이 날아갑니다.
mockfeed의 프리셋 YAML은 단순 설정이 아니라 "왜 이 값인가"를 AWS 문서 인용과 함께 주석으로 남긴 지식 캡슐입니다. 그리고 모든 설정을 pydantic 스키마로 검증해, 비트레이트 범위·코덱·프로토콜이 어긋나면 송출 전에 친절한 에러로 잡습니다. GOP는 fps × keyframe_interval_seconds로 자동 계산되니, 해상도를 바꿔도 설정이 깨지지 않습니다.
이 프로젝트가 영상 엔지니어 커뮤니티(r/VIDEOENGINEERING)에서 공감을 산 이유는 화려한 기능이 아니라 "우리가 매번 검색하던 그 지식을 깔끔히 정리해 줬다"는 데 있습니다.
| 설계 선택 | 무엇을 | 왜 좋은가 |
|---|---|---|
| 입력 미디어 0 | lavfi 가상 소스로 컬러바·톤 생성 | 테스트용 영상 파일을 준비할 필요가 없음 |
| 프리셋에 근거 주석 | 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 설계 패턴"을 배우는 교본으로 보는 게 정확합니다.
"파이썬 현대 도구 모음(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는 이걸 호출하는 래퍼 |
| 라이브러리 | 역할 | 한 줄 설명 |
|---|---|---|
| typer ≥0.15 | CLI 프레임워크 | 타입힌트로 서브커맨드(push/validate/presets) 정의. Click 기반 |
| pydantic ≥2.0 | 설정 검증 | 모든 설정을 BaseModel + Literal/Field 제약으로 타입세이프 검증. 이 도구의 중추 |
| rich ≥13.0 | 터미널 UI | 실시간 진행률 패널·테이블·신택스 하이라이트 |
| questionary ≥2.0 | 대화형 프롬프트 | 인자 없이 실행하면 화살표 메뉴로 설정을 묻는 대화형 폴백 |
| pyyaml ≥6.0 | YAML 파싱 | 프리셋·설정 파일을 yaml.safe_load로 읽음 |
bitrate_kbps를 "500~20000 정수"로 선언하면, 30000이 들어오는 순간 친절한 에러가 납니다 — 이게 타입세이프 설정입니다. lavfi는 FFmpeg의 가상 입력 장치로, smptebars(컬러바)·sine(사인파 톤)처럼 미디어 파일 없이 신호를 즉석 생성합니다. mockfeed가 "입력 영상이 필요 없는" 비결이 바로 이것입니다.mockfeed의 FFmpeg 연동에는 보안·안정성 디테일이 있습니다.
| 기법 | 설명 |
|---|---|
인자 리스트 + shell=False | 명령을 문자열이 아닌 ["ffmpeg","-re",...] 리스트로 subprocess.Popen에 넘겨 셸 인젝션 차단 |
-progress pipe:2 | FFmpeg가 stderr에 key=value 진행 블록을 토해내게 해, 머신리더블 진행률을 별도 스레드로 파싱 |
| 2단계 graceful shutdown | Ctrl-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 마커로 분리해 평소엔 제외합니다.
"입력 3종(프리셋·파일·대화형) → 단일 검증 지점(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)
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)는 프로토콜에서 자동으로 정해집니다.
| protocol | container | 비고 |
|---|---|---|
| rtmp / rtmps | flv | 라이브 송출 표준(대부분 클라우드). rtmps는 RTMP over TLS |
| srt | mpegts | 저지연·손실 복원 전송. mockfeed는 caller로 동작(listener에 접속). ?latency=2000000(μs) 같은 쿼리를 그대로 전달 |
| udp | mpegts | raw UDP, 로컬·LAN 스모크테스트(ffplay udp://127.0.0.1:5000로 수신) |
이 셋이 mockfeed를 관통합니다 — 단일 진실원(프리셋·파일·대화형이 한 객체로 수렴), 순수 함수 + I/O 분리(FFmpeg 없이 명령을 단언, 그래서 테스트가 본체보다 큼), 근거를 남기는 프리셋(복붙이 아니라 학습). 작지만 "잘 설계된 CLI란 무엇인가"의 좋은 표본입니다.
"패키지 본체 14개 파일이 config / ffmpeg / output / presets로 깔끔히 갈린다. 가장 중요한 건 스키마·명령빌더·프리셋 YAML 세 곳."
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)는 이 셋을 사용자와 잇는 배관입니다.
"라이브 스트리밍 프로토콜·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로 바뀌는 걸 명령에서 확인.
배울 것: shell=False + 인자 리스트로 셸 인젝션 차단, lavfi 가상 소스로 입력 파일 없이 신호 생성, -progress pipe:2로 머신리더블 진행률 받기, SIGTERM→SIGKILL 2단계 graceful shutdown.
실습: 파이썬 subprocess.Popen으로 FFmpeg를 띄우고 stderr를 별도 스레드로 읽어 진행률을 출력. Ctrl-C 시 SIGTERM을 보내고 5초 후 SIGKILL하는 종료 로직을 구현.
배울 것: Literal로 enum 강제, Field(ge=,le=)로 범위, @model_validator(mode="after")로 교차필드 검증(scheme↔protocol↔container 일관성), model_copy(update=)로 불변 병합. "잘못된 입력을 일찍, 친절하게 막는" 설계.
실습: pydantic으로 "비트레이트 500~20000, 코덱은 h264/hevc만" 같은 설정 모델을 만들고, 범위를 벗어난 값을 넣어 에러 메시지를 관찰. 두 필드의 일관성을 검사하는 validator를 추가.
배울 것: Typer로 서브커맨드(push/validate/presets) 구성, 인자 없이 실행하면 questionary 대화형으로 폴백, 상호배타 옵션 처리, 의미 있는 exit code, rich 라이브 대시보드.
실습: Typer로 "인자를 주면 그대로 실행, 안 주면 화살표 메뉴로 묻는" 미니 CLI를 만들기. rich의 Live로 1초마다 갱신되는 진행 패널을 붙여 보기.
배울 것: 핵심 로직(build_command)을 부수효과 없는 함수로 만들어 외부 도구 없이 단언, 실제 ffmpeg가 필요한 테스트는 integration 마커로 분리. 그 결과 테스트 코드가 본체보다 커진 품질 문화.
실습: 내 코드에서 "데이터 → 명령/쿼리 문자열"을 만드는 부분을 순수 함수로 떼어내, 외부 실행 없이 출력만 검증하는 단위 테스트를 작성. 무거운 통합 테스트엔 pytest 마커를 달기.
배울 것: 프리셋 YAML 주석에 결정 근거 + 1차 출처(AWS 문서 URL)를 남기는 문서화 문화, IDEAS.md로 마찰점을 기록하는 도그푸딩, 그리고 URL scheme 화이트리스트·위험 IP 차단·sentinel 호스트 감지 같은 입력 검증 보안.
실습: 자주 쓰는 복잡한 명령(예: 백업·배포 스크립트)을 "근거 주석이 달린 프리셋"으로 정리해 보기. 사용자 입력 URL을 받을 때 scheme 화이트리스트로 거르는 검증기를 작성.
"무거운 인프라 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로 송출 전 점검 |
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도 없습니다. 즉 "지금 당장의 만능 송출 도구"가 아니라 "핵심 골격이 잘 잡힌 초기 도구 + 좋은 학습 교본"으로 기대하세요. 바로 이 빈칸들이 아래 실습 과제의 좋은 재료입니다.
"UDP 로컬 송출 → 맨손 FFmpeg와 비교 → 세 번째 프리셋 추가 → 미완성 오버레이 완성 → 미니 mockfeed 만들기."
mockfeed를 설치하고 ffplay udp://127.0.0.1:5000를 띄운 뒤, examples/udp_localhost.yaml 또는 mockfeed push --config ...로 송출. ffplay 창에 SMPTE 컬러바와 1kHz 톤이 나오는지 확인.
목표: "입력 영상 없이 즉석 신호 송출"을 체감. validate 명령으로 송출 전 설정 점검도 해 보기.
mockfeed가 만든 FFmpeg 인자(소스의 build_command 또는 verbose 출력)를 README의 Before 명령과 나란히 놓고, 각 플래그가 어떤 설정에서 나왔는지 매핑. -g가 fps × keyframe_interval임을 직접 계산해 확인.
목표: 프리셋이 "박제한 지식"을 역추적해 FFmpeg 라이브 송출 플래그를 스스로 이해. 해상도를 바꿔 GOP가 따라 바뀌는지 확인.
presets/에 새 YAML을 만들어 YouTube Live나 Twitch의 RTMP 요구사항(비트레이트·GOP·오디오)을 박제. 기존 두 프리셋처럼 "왜 이 값인지" 근거 주석과 1차 출처 URL을 함께 남기고, registry가 인식하는지 mockfeed presets로 확인.
목표: 프리셋 구조와 registry 로딩을 이해. 도메인 지식을 "근거가 달린 설정"으로 코드화하는 연습.
스키마에만 있고 동작 안 하는 OverlayConfig를 build_command()에 연결한다 — FFmpeg drawtext 필터로 타임코드/텍스트 번인을 추가. 순수 함수이므로 단위 테스트로 인자 배열을 먼저 단언한 뒤 실제 송출로 확인.
목표: "선언만 된 기능"을 완성하며 명령 빌더·필터그래프·테스트 흐름을 한 번에 경험. 실제 오픈소스 기여 후보.
pydantic 설정 모델 + 순수 명령 빌더 + subprocess 러너 + rich 진행 패널을 직접 조립해, 컬러바를 UDP로 쏘는 작은 도구를 완성한다. -progress pipe:2 파싱과 SIGTERM→SIGKILL 종료까지 넣으면 구조가 거의 같아진다.
목표: "입력→검증→명령→실행→표시"의 단방향 파이프라인을 손으로 완성. mockfeed 전체 설계를 내 것으로 만들기.
"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 도구"의 골격을 익히려는 사람에게 알맞은 교재입니다.
"이 문서와 저장소에서 반복되는 스트리밍·FFmpeg·파이썬 용어를 한곳에 모았다."
| 용어 | 의미 |
|---|---|
| RTMP / RTMPS | Real-Time Messaging Protocol(+TLS). 라이브 송출 표준, 컨테이너는 FLV |
| SRT | Secure Reliable Transport. 손실 네트워크에서 신뢰성·저지연 전송. caller/listener 모델, latency는 μs |
| UDP / MPEG-TS | raw UDP 송출, 컨테이너는 MPEG transport stream. 로컬·LAN 테스트용 |
| ingest | 받는 쪽이 라이브 영상을 빨아들이는 입구. 인코더 요구사항이 까다로움 |
| AWS MediaLive / MediaConnect | AWS Elemental 클라우드 영상 ingest·전송 서비스. mockfeed 프리셋의 타깃 |
| lavfi | FFmpeg 가상 입력. smptebars·testsrc2·sine·anullsrc 등 미디어 파일 없이 신호 생성 |
| GOP (Group of Pictures) | 키프레임(IDR) 사이 프레임 묶음. GOP = fps × keyframe_interval. ABR 세그먼트 정렬에 필수 |
| CBR / VBR | Constant/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 yuv420p | 4:2:0 크로마 서브샘플링. 대부분 디코더 호환을 위한 요구 |
| sc_threshold 0 | 씬 변화 시 자동 키프레임 삽입 비활성화 → GOP 경계 고정 |
| bufsize / maxrate | 레이트 컨트롤 버퍼·상한. mockfeed는 bufsize = bitrate × 2 |
| pydantic | 파이썬 데이터 검증 라이브러리. 타입·범위·허용값으로 설정을 송출 전에 검증 |
| Typer / questionary / rich | CLI 프레임워크 / 대화형 프롬프트 / 터미널 UI(라이브 대시보드) |
| uv / hatchling | 차세대 파이썬 패키지·도구 관리자 / 빌드 백엔드 |
| 순수 함수 / integration 마커 | 부수효과 없는 함수(테스트 쉬움) / 실제 ffmpeg가 필요한 느린 테스트 분리 표식 |
| graceful shutdown | Ctrl-C → SIGTERM(트레일러 flush) → 5초 후 SIGKILL의 2단계 우아한 종료 |