C.W.K.
Stream
Lesson 08 of 08 · published

자동화 & AI Post-Processing

~12 min · automation, ai, python, agent-sdk

Level 0Viewer
0 XP0/73 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

Pipeline 안의 FFmpeg

FFmpeg 의 가치가 자동화에 stitch 할 때 compound: transcript 기반 video trim 하는 agent, frame sequence 생성 후 조립 필요한 AI 도구, 안 좋은 audio level detect + fix 하는 batch 작업.

Pippa 예시

이 codebase 가 세 곳에서 Python 에서 FFmpeg 호출:

  • backend/services/tts_normalize.py — 모든 Pippa voice clip 에 EBU R128 + denoise chain 돌림.
  • backend/services/video_export.py — avatar frame + TTS audio 를 WebUI 의 exportable video 로 조립.
  • Telegram bot voice note — transcription 전 Opus → WAV 변환.

패턴

명령어를 list 로 (shell string 아님) subprocess.run 사용 — 더 안전, 파일이름의 space 자동 처리. Progress parsing 위해 stderr pipe. Long job 엔 machine-readable progress event 위해 -progress pipe:1 사용.

Code

Python wrapper — progress 와 basic encode·python
import subprocess, sys, json

def encode_with_progress(src: str, dst: str) -> int:
    cmd = [
        "ffmpeg", "-y", "-i", src,
        "-c:v", "libx264", "-crf", "20", "-preset", "slow",
        "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "192k",
        "-progress", "pipe:1",
        "-nostats", "-loglevel", "error",
        dst,
    ]
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True)
    for line in p.stdout:
        if line.startswith("out_time_ms="):
            ms = int(line.strip().split("=", 1)[1])
            print(f"\rProgress: {ms / 1_000_000:.1f}s", end="", flush=True)
    return p.wait()

if __name__ == "__main__":
    sys.exit(encode_with_progress(sys.argv[1], sys.argv[2]))
Agent-driven trim — LLM 이 timestamp 픽·python
import subprocess, json
from pathlib import Path

def transcribe(src: Path) -> list[dict]:
    """Segment list 반환: [{start, end, text}, ...]
    Pipeline 에 fit 한 transcriber 사용 (faster-whisper, Cloud STT, etc.)
    """
    ...

def llm_pick_highlights(segments: list[dict]) -> list[tuple[float, float]]:
    """Segment 를 LLM 에 보내서 30초 quotable start/end pair 반환 요청.
    (start, end) tuple list 반환.
    """
    ...

def build_highlight_reel(src: Path, ranges: list[tuple[float, float]], dst: Path):
    # Range trim + concat 하는 complex filtergraph 빌드
    parts = []
    filters = []
    for i, (s, e) in enumerate(ranges):
        filters.append(f"[0:v]trim=start={s}:end={e},setpts=PTS-STARTPTS[v{i}]")
        filters.append(f"[0:a]atrim=start={s}:end={e},asetpts=PTS-STARTPTS[a{i}]")
    parts.extend(f"[v{i}][a{i}]" for i in range(len(ranges)))
    filtergraph = "; ".join(filters) + "; " + "".join(parts) + f"concat=n={len(ranges)}:v=1:a=1[outv][outa]"

    subprocess.run([
        "ffmpeg", "-y", "-i", str(src),
        "-filter_complex", filtergraph,
        "-map", "[outv]", "-map", "[outa]",
        "-c:v", "libx264", "-crf", "20", "-preset", "slow",
        "-c:a", "aac", "-b:a", "192k",
        str(dst),
    ], check=True)

# Wire up
src = Path("raw_podcast.mp4")
segs = transcribe(src)
ranges = llm_pick_highlights(segs)
build_highlight_reel(src, ranges, Path("highlights.mp4"))

External links

Exercise

Video 와 (start, end) tuple list 받아 concatenated highlight reel 생성하는 Python script 작성 (위 recipe 사용). -progress pipe:1 parsing 으로 progress print 추가. 보너스: audio transcript 의 'best' 30초 픽 하는 LLM (Claude API) 통해 segment feed.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.