주요 콘텐츠로 건너뛰기
AI 튜토리얼

ff-tracking으로 코드 생성 AI 터미널 영화 만들기

ff-tracking이 터미널에서 입력하는 AI 에이전트를 렌더링하고 각 글리프를 추적하며, 이동 카메라와 SkSL 렌즈 효과를 적용하고 동기화된 사운드를 생성하는 방법을 알아보세요. 이 튜토리얼에서는 설정, 2단계 파이프라인, 렌더링 명령어, 사용자 지정, 진단 및 선택 사항인 Slab 사운드트랙을 다룹니다.

ff-tracking으로 코드 생성 AI 터미널 영화 만들기

ff-tracking은 터미널에 입력하는 AI 에이전트를 가상 카메라가 따라가는 코드 생성 단편 영화입니다. 컴퓨터 비전 스타일의 오버레이가 개별 글리프를 추적하며, 원근감, 피사계 심도, 색상 처리, 블룸, 스캔라인 찢김, 그레인, 사운드는 모두 코드로 생성됩니다.

이 프로젝트는 Rust, fframes, Skia Metal, SkSL, FFmpeg, Python으로 구축되었습니다. 두 개의 연동된 패스를 통해 6초 분량의 영상을 렌더링하며, 시각 효과와 오디오는 모두 공유 트래킹 데이터를 사용합니다.

트래킹 오버레이가 적용된 코드 생성 터미널 영화

프로젝트가 생성하는 결과물

영화에는 thinking…, reading 14 files, tool_call: render_frame(), ✓ 0 problems와 같은 터미널 메시지가 차례로 나타납니다. 트래커는 새로 입력된 문자를 따라가며 실제 픽셀 좌표, 대상 괄호, 레이블, 상자 사이의 연결선을 표시합니다.

  • 실제 좌표: 트래커 레이블은 출력 프레임에서 각 상자의 실제 위치를 사용합니다.
  • 이동하는 초점: 피사계 심도 대상은 에이전트가 입력하는 동안 추적된 상자를 따라 이동합니다.
  • 애니메이션 트래킹: 연결선은 읽기 순서에 따라 상자를 연결하며, 각 연결선을 따라 점이 이동합니다.
  • 잠금 효과: 새 단어가 두 프레임 동안 빨간색으로 바뀌고 스캔라인 찢김 효과가 적용되며, 공간적으로 패닝된 비프음이 재생됩니다.
  • 다양한 룩: 12개의 샷에서 Paper, Thermal, Mono, Phosphor, Amber, Navy, Neon 팔레트를 사용합니다.
  • 최종 축소: 14개의 상자가 하나의 상자로 합쳐지고, 검은 화면으로 페이드되기 전에 Done 필로 변합니다.

2패스 파이프라인 이해하기

이 프로젝트는 터미널 레이아웃을 카메라 및 렌즈 효과와 분리합니다. 이를 통해 모든 글리프 위치를 결정적으로 유지하면서, 두 번째 패스에서 렌더링된 터미널을 셰이더 입력으로 처리할 수 있습니다.

  1. HUD 데이터: hud 크레이트는 장면, 트래커 상자, 카메라 이동, 투영 데이터를 정의합니다.
  2. 플랫 패스: flat 바이너리는 터미널을 3840×2160 해상도의 SVG로 렌더링합니다. 위치를 정확히 파악할 수 있도록 글리프마다 하나의 <text> 요소를 배치합니다.
  3. 렌즈 패스: lens 바이너리는 플랫 영상을 iChannel0으로 샘플링하고 가상 카메라와 SkSL 효과를 적용합니다.
  4. 오디오 패스: tools/sfx.py는 out/tracks.json을 읽고 입력, 컷, 잠금, 최종 착지에 맞는 사운드 이벤트를 합성합니다.
  5. 인코딩: FFmpeg는 처리된 영상과 오디오를 out/tracking.mp4로 결합합니다.

렌즈 셰이더는 원근감, 피사계 심도, 팔레트 매핑, 색수차, 블룸, LED 그리드, 찢김, 그레인, 카메라 공간의 트래커 오버레이를 처리합니다. 피사계 심도 효과는 황금각을 사용하는 36개의 샘플을 이용하며, 하이라이트에는 보케 스타일의 가중치가 적용됩니다.

렌즈 셰이더 효과의 단계

필수 구성 요소 설치

이 프로젝트는 Metal에서 Skia를 사용하므로 렌더링하려면 Apple 실리콘이 탑재된 Mac이 필요합니다. 빌드하기 전에 다음 도구를 설치하세요:

  • 2024 에디션을 지원하는 Rust
  • FFmpeg
  • Python 3
  • Python 패키지 numpy 및 scipy
  • README 미디어를 다시 빌드하려는 경우 Pillow 및 img2webp

저장소를 복제하고 해당 디렉터리로 이동합니다:

git clone https://github.com/mrsarac/ff-tracking
cd ff-tracking

기본 영화 렌더링

메인 스크립트는 Rust 워크스페이스를 빌드하고, 트래킹 데이터를 내보내며, 플랫 패스를 렌더링하고, 사운드를 합성한 다음 렌즈 패스를 렌더링합니다:

tools/render.sh

완성된 영상은 out/tracking.mp4에 저장됩니다. M3 Pro에서는 초기 빌드 후 렌더링에 약 40초가 걸립니다.

생성된 데이터에는 기본 사운드 디자인을 설명하고 구동하는 out/tracks.json이 포함됩니다. 선택 사항인 카메라 바이너리는 프레임별 줌, 틸트, 롤, 추적 상자 위치, 화면 중심 정보가 담긴 out/camera.json도 작성합니다.

프레임, 오디오, 셰이더 단계 확인

각 패스가 fframes CLI이므로 일반적인 명령어로 출력을 확인할 수 있습니다:

target/release/lens strip all -n 12
target/release/lens frame 81 -o frames
target/release/lens preview
target/release/lens audio analyze

strip은 콘택트 시트를 만들고, frame은 전체 크기의 프레임을 내보내며, preview는 사운드와 함께 실시간 미리보기를 엽니다. 오디오 분석 명령은 음량과 실제 피크 정보를 보고합니다.

특정 단계 이후 셰이더를 중지하려면 LENS_STAGE를 설정하세요. 지원되는 단계는 0부터 3까지 번호가 지정됩니다:

LENS_STAGE=1 target/release/lens frame 81

소스 이미지에서 최종 렌즈 처리로 전환되는 과정을 디버깅할 때 유용합니다.

장면 사용자 지정

각 샷은 hud/src/lib.rs의 SCENE_LIST에 있는 항목입니다. 장면은 종류, 텍스트, 팔레트, 카메라, 시작 위치, 글꼴 크기를 정의합니다:

SceneDef {
    kind: Kind::Typing,
    text: "생각 중…",
    palette: Palette::Thermal,
    cam: cam(0.38, -0.22, 0.04, 2.5, 2.8, 50.0, 0.0, 1.2),
    hero: (560.0, 540.0),
    size: 104.0,
},

텍스트를 변경하거나 다른 팔레트를 선택하고 카메라 값을 조정한 다음 다시 렌더링하세요:

tools/render.sh

트래커, 포커스 대상, 레이블, 잠금 비프음은 업데이트된 장면 데이터를 자동으로 따릅니다. 사용 가능한 팔레트 이름에는 Paper, Thermal, Mono, Phosphor, Amber, Navy, Neon이 있습니다.

장면을 편집한 후 HUD 테스트를 실행하세요:

cargo test -p hud

이 테스트는 각 줄이 화면에 맞는지, 카메라가 모든 대상을 프레임 안에 유지하는지 확인합니다.

터미널 추적 장면과 시각적 팔레트

기본 또는 선택적 사운드트랙 사용

기본 사운드트랙은 tools/sfx.py로 생성됩니다. 화면의 웅웅거리는 소리, 장면 전환 시 비트 크러시 글리치, 키 입력 클릭음, 추적 상자를 향해 패닝되는 5음 음계 잠금 비프음을 결합합니다. 또한 접힘 장면에는 상승음을 추가하고, Done 필이 나타날 때 서브 히트가 포함된 차임을 재생합니다. 음량은 FFmpeg의 ebur128로 측정하며 -14 LUFS로 설정됩니다.

저장소에는 120BPM의 선택적이고 더 어두운 Slab 스코어도 포함되어 있습니다. 이 스코어는 동일한 추적 및 카메라 데이터를 따르므로 잠금 블립, 키 입력, 패드, 상승음, 글리치, 베이스 필터링, 베이스 티어가 애니메이션에 반응합니다.

커밋된 스코어 렌더를 사용하려면 다음을 실행하세요:

tools/score.sh

스코어를 다시 렌더링하려면 zig build -Doptimize=ReleaseFast로 빌드한 Slab 체크아웃을 제공하세요:

SLAB=/path/to/slab tools/score.sh

스코어 스크립트는 score/ff_tracking.slab을 작성하며, 렌더링된 오디오는 score/score.wav로 제공됩니다. 스코어 파이프라인은 리버브 잔향을 위해 영상보다 길게 처리한 다음 결과를 6초로 자르고 영상과 함께 페이드합니다.

score/score.py는 GPL-3.0으로 배포되는 Slab의 slabkit을 가져온다는 점에 유의하세요. Slab은 스코어를 다시 렌더링할 때만 필요하며, README에 따라 커밋된 스코어 파일은 저장소의 MIT 라이선스로 제공됩니다.

문서 미디어 다시 빌드

저장소에는 README 이미지를 다시 생성하는 스크립트가 포함되어 있습니다. 이미지 의존성을 설치한 후 Python으로 실행하세요:

python3 -I tools/readme_media.py

프로젝트 구조

  • hud/: 장면, 트래커 상자, 카메라 데이터, 투영 로직.
  • flat/: 3840×2160 해상도의 첫 번째 터미널 렌더링 단계.
  • lens/: lens/shaders/lens.sksl과 카메라 공간 트래커를 포함한 두 번째 단계.
  • tools/: 기본 렌더 스크립트, 사운드 생성기, README 미디어 생성기, Slab 파이프라인.
  • score/: 선택적 Slab 스코어, 프로젝트, 렌더링된 WAV 파일.
  • docs/: 디자인 사양, 프롬프트, 결정 사항, fframes 기여 자료.

고급 구현 참고 사항

셰이더는 현재 동일한 프레임에서 SVG 하위 트리를 샘플링할 수 없으므로 2단계 설계가 중요합니다. 대신 완성된 플랫 프레임을 동기화하고 이미지 입력으로 셰이더에 전달합니다:

.image("iChannel0", &frame.get_synced_video_frame(..)?.into_image())

README에는 다음과 같은 몇 가지 실용적인 제약 사항도 문서화되어 있습니다:

  • flat은 SkSL에서 예약되어 있으므로 헬퍼 이름으로 사용하지 마세요.
  • Video 수준에서는 Svgr::empty() 대신 루트 <svg>를 반환하세요. 빈 루트는 뒤늦은 렌더링 오류로 나타날 수 있습니다.
  • CPU 투영 함수 hud::project는 트래커 오버레이를 셰이더의 카메라와 정렬된 상태로 유지합니다.
  • 두 시각적 단계와 사운드 생성기는 동일한 HUD 추적 정보를 읽으므로 포커스와 오디오 이벤트가 글리프에서 벗어나지 않습니다.

결론

ff-tracking은 구조화된 장면 데이터, SVG, Rust, SkSL, GPU 렌더링, 합성 오디오만으로 짧은 시네마틱 시퀀스를 생성하는 방법을 보여줍니다. tools/render.sh로 시작해 중간 프레임을 확인한 다음 SCENE_LIST를 편집하여 자신만의 터미널 메시지, 팔레트, 카메라 이동, 추적 구성을 만들어 보세요. 동일한 타이밍과 카메라 움직임을 따르는 스코어가 필요할 때는 선택적 Slab 파이프라인을 사용하세요.