Opus 5.5로 CSV를 차트 영상으로 만드는 방법: Python에서 MP4까지
CSV 검증, Opus 5.5 프롬프트, Python·FFmpeg 렌더링을 차례로 진행합니다. 다운로드 가능한 참조 프로젝트로 수치와 최종 MP4를 확인하세요.
Opus 5.5로 차트 영상을 만들려면 검증한 데이터와 고정된 시각화 명세를 전달하고, Python으로 프레임을 그린 뒤 FFmpeg로 인코딩합니다. 원래 건수에는 애니메이션을 적용하지 마세요. 화면에서 막대가 늘어나는 연출이 실제 사업 지표가 시간에 따라 성장했다는 주장으로 바뀌어서는 안 됩니다.
이 튜토리얼의 결과물은 CSV의 세 항목을 보여 주는 12초, 1280 × 720 MP4입니다. 보고서 데이터를 발표나 소셜 영상으로 옮기고 싶고 로컬 명령을 실행할 수 있는 독자를 대상으로 합니다. 데이터를 준비하고, Claude에 구체적으로 지시한 뒤, 차트를 확인하고 내보내 최종 파일의 수치까지 점검합니다. 기본 설정과 다른 제작 방식은 Opus 5.5 영상 제작 가이드에서 확인할 수 있습니다.
참조 결과를 보고 프로젝트 다운로드하기
편집자가 작성한 참조 프로젝트를 실제로 로컬에서 렌더링한 영상입니다. 수치는 가상이며 라벨은 영어이고, 의도적으로 소리를 넣지 않았습니다. Ofox의 고객, 매출, 지원 업무 데이터가 아닙니다.
전체 프로젝트, MP4, 전체 프롬프트를 다운로드하세요.
검증 범위: 이번에 Claude Code로 Opus 5.5를 호출하려 했지만 세션이 로그인되지 않아 실패했습니다. 따라서 편집자가 참조 구현을 작성하고 CSV 검증과 Python/FFmpeg 렌더링을 테스트했습니다. 이를 이번 Opus의 출력이나 한 번의 요청으로 성공한 생성 결과라고 표시하지 않습니다. 프롬프트는 본인에게 이용 권한이 있는 Claude 환경에서 쓸 수 있으며, 제공 프로젝트는 모델 호출 없이 재현할 수 있습니다. 별도의 스크린샷 영상 튜토리얼에는 해당 작업에서 성공한 모델 호출 기록이 있습니다. 그것이 이번 호출까지 검증해 주는 것은 아닙니다.
차트가 무엇을 말할 수 있는지 먼저 정하기
샘플은 채널별 문의 건수 비교입니다. 시간 순서, 전환 퍼널, 성장 그래프가 아닙니다. 이 차이는 애니메이션과 나중에 넣을 내레이션 모두에 영향을 줍니다.
| 항목 | 건수 | 이 예제에서의 의미 |
|---|---|---|
| 120 | Email에 배정한 가상의 문의 | |
| Chat | 180 | Chat에 배정한 가상의 문의 |
| Docs | 90 | Docs에 배정한 가상의 문의 |
합계는 390건입니다. 이 가상의 예에서 Chat은 Email보다 60건 많습니다. 그렇다고 Chat의 전환율이 더 높거나, 시간을 절약하거나, 사용자 만족도가 더 높다는 뜻은 아닙니다. 분모나 성과 측정값이 없기 때문입니다.
세 막대는 모두 0에서 시작하며 동일한 0~200 척도를 사용합니다. 최종 너비는 차트 영역의 60%, 90%, 45%입니다. 시청자가 서로 다른 척도를 해석하지 않고도 비교할 수 있어야 합니다. 차이를 극적으로 보이게 하려고 축의 시작 부분을 잘라내지 마세요.
실제 데이터라면 출처, 추출 날짜, 보고 기준 시간대, 단위, 집계 규칙을 CSV와 함께 기록하세요. 항목이 서로 겹치는지도 확인해야 합니다. 겹친다면 합계가 중복을 제거한 총수를 뜻하지 않을 수 있습니다. 모델 프롬프트에 넣기 전에 개인정보를 제거하고, 사용 권한이 있는 데이터만 공유하세요.
재현할 환경 준비하기
압축 파일에는 sample.csv, prepare.py, test_prepare.py, render.py, requirements.txt, prompt.txt, README가 들어 있습니다. 참조 구현은 Python 3.9 이상, Pillow 11.3.0, H.264 인코더(libx264)를 사용할 수 있는 FFmpeg를 씁니다. FFmpeg는 명령 검색 경로에 있어야 합니다. 텍스트는 로컬 TrueType 글꼴로 그립니다. 제공 프로젝트를 렌더링하는 데 브라우저나 모델 API는 필요하지 않습니다.
로컬 디렉터리에 압축을 풀고 그 위치에서 명령을 실행하세요. python3 -m venv .venv로 가상 환경을 만든 다음, macOS/Linux에서는 source .venv/bin/activate, Windows PowerShell에서는 .venv\Scripts\Activate.ps1로 활성화하고 설치 및 검증을 진행합니다.
python3 -m pip install -r requirements.txt
python3 prepare.py
python3 -m unittest test_prepare.py
ffmpeg -version
준비 단계에서 기대하는 메시지는 Validated 3 rows. Total: 390입니다. 다르면 중단하고 확인하세요. 다섯 테스트 메서드는 정상 입력, 0과 경계값, 따옴표로 감싼 라벨 속 쉼표, 잘못된 값, 형식이 어긋난 행을 검사합니다. 파서 테스트 통과가 영상 렌더링 성공을 뜻하지는 않습니다.
CHART_FONT를 사용 허가가 있는 로컬 TrueType 글꼴로 지정하세요. 예를 들어 해당 파일이 있는 macOS에서는 다음과 같이 설정합니다.
export CHART_FONT='/System/Library/Fonts/Supplemental/Arial.ttf'
Linux에 설치된 DejaVu Sans는 /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf에 있을 수 있습니다. Windows PowerShell에서는 Arial이 설치되어 있다면 $env:CHART_FONT='C:\Windows\Fonts\arial.ttf'로 선택할 수 있습니다. Python 실행 명령은 환경에 맞게 바꾸세요. Windows에서는 python3 대신 python인 경우가 많습니다. 예시 경로일 뿐, 모든 컴퓨터에 해당 글꼴이 있다는 보장은 아닙니다. 압축 파일에는 글꼴을 재배포하지 않습니다. 필요한 언어의 글리프가 있는 글꼴을 고르고 라이선스를 확인하세요.
FFmpeg 명령이 없다면 운영체제에 맞는 신뢰할 수 있는 설치 방법을 이용하세요. FFmpeg 다운로드 페이지에 플랫폼별 선택지가 있습니다. Claude에 코드 작성이나 수정을 요청하려면 본인의 접근 권한이 필요하며 플랜의 사용량을 소모할 수 있습니다. 제공한 Python 코드는 모델을 호출하지 않습니다. 이 로컬 예제만으로 유료 서비스 이용이나 API 호환성까지 확인되었다고 말하지 않습니다.
모델에 전달하기 전에 CSV 검증하기
다음 헤더와 샘플을 그대로 사용하세요.
label,value
Email,120
Chat,180
Docs,90
파서는 Python의 CSV 리더를 사용하므로 "Email, shared"처럼 따옴표로 감싼 라벨을 한 셀로 읽습니다. BOM이 있거나 없는 UTF-8을 모두 받습니다. 헤더 변경, 중복 또는 빈 라벨, 추가 셀, 다른 행 수, 숫자가 아닌 값, 음수, 정수가 아닌 건수, 무한대, 차트 상한을 넘는 값은 거부합니다.
제약이 엄격한 이유가 있습니다. 이 레이아웃은 세 항목의 정수 건수를 위한 것입니다. 누락된 측정값을 조용히 0으로 바꾸면 안 됩니다. 소수로 표현한 비율을 반올림해 건수로 바꿔서도 안 됩니다. 240을 200에서 잘라 놓고 정확한 막대처럼 보여 줄 수는 없습니다.
다른 파일을 검사하려면 python3 prepare.py my-data.csv를 실행하세요. 준비 스크립트는 모든 행이 통과한 뒤에만 data.json을 씁니다. 본인 데이터로 렌더링하려면 샘플을 백업하고 sample.csv를 교체한 다음 다시 검증하세요. 렌더러는 실행할 때마다 sample.csv를 직접 읽고 검증합니다. 이전에 만든 검사용 JSON을 대신 읽지 않습니다.
검증이 실패해도 이전 out/chart.mp4가 남아 있을 수 있습니다. 그 파일을 새로운 렌더링의 성공 결과처럼 전달하지 마세요. 렌더러는 임시 MP4를 쓰고 FFmpeg가 성공을 보고한 뒤에만 최종 파일을 교체합니다. 성공한 명령의 출력과 out/accepted-data.json을 결과물과 함께 보관하세요.
라벨은 24자까지 허용합니다. 렌더러는 선택한 글꼴에서 너비가 200픽셀을 넘는 라벨도 거부하므로 차트와 겹치게 내버려 두지 않습니다. 뜻을 설명한 약어로 줄이거나 라벨 열을 의도적으로 다시 설계하세요. 글자 수만으로 잘 맞는다고 보장할 수 없으며, 필요한 글자가 제대로 표시되는지는 눈으로 확인해야 합니다.
Opus에 구체적이고 범위가 정해진 지시 전달하기
검증한 행을 첨부하거나 아래 명세와 함께 붙여 넣으세요. 다운로드용 전체 프롬프트에는 참조 레이아웃의 좌표, 검증 규칙, 글자 설정이 포함되어 있습니다. 아래 짧은 지시는 이미 받은 프로젝트를 수정할 때 유용합니다. 실행 조건을 동일하게 유지하도록 영어 원문을 제공합니다.
Edit this existing Python/Pillow and FFmpeg project to make a 12-second chart video.
Read sample.csv with the existing prepare.py parse() validator.
It contains exactly three rows: Email 120, Chat 180, Docs 90.
These are synthetic ticket counts, not real company results.
Keep output at 1280x720, 30fps and 360 RGB frames.
Keep a zero baseline and a shared, fixed maximum of 200.
Keep the exact numeric labels visible and unchanged at every frame.
Reveal bar widths only between frames 30 and 90; hold thereafter.
Use progress=max(0,min(1,(frame-30)/60)) for the reveal.
Do not use random values, network data or new packages.
Keep a permanent label: Synthetic example · tickets · fixed scale 0–200.
State that the reveal is not growth over time.
Preserve CSV validation and do not substitute zero for missing values.
If a value exceeds the maximum, stop and explain; do not clip it.
Return the changed file, explain changes, and give the render command.
Do not invent a test result. List tests that still need to be run.
실행하기 전에 답변을 검토하세요. 패키지 변경과 파일 작업이 요청한 내용에 맞는지 비교합니다. 설치, 데이터 업로드, 덮어쓰기는 각각 별도 작업입니다. 생성된 안내에 포함되었다는 이유만으로 꼭 필요한 것은 아닙니다. 이 작은 차트에는 기존 의존성만으로 충분합니다.
다른 내용을 전달하고 싶다면 지시부터 바꾸세요. “더 흥미롭게 만들어 줘”라고만 하면 무엇을 유지해야 하는지 설명하지 않은 채 동작을 추가하게 됩니다. “모든 값과 척도는 유지하고, 도입부는 2초로 하며, 완성된 차트는 최소 6초 동안 보여 줘”처럼 요청하는 편이 낫습니다.
타임라인과 고정 척도 확인하기
초당 30프레임에서 360프레임은 12초입니다. 참조 구현은 첫 1초 동안 막대 영역을 비워 두고, 다음 2초에 걸쳐 막대를 보여 준 뒤, 남은 9초 동안 완성된 차트를 읽을 수 있게 유지합니다.
| 프레임 | 시간 | 기대하는 화면 |
|---|---|---|
| 0~29 | 0초~1초 미만 | 제목, 라벨, 정확한 값, 축은 보이고 막대 너비는 0 |
| 30~89 | 1초~3초 미만 | 막대 너비가 늘어나지만 숫자 라벨은 그대로 유지 |
| 90~359 | 3초~12초 미만 | 모든 막대가 최종 길이를 유지 |
핵심 계산은 짧습니다.
progress = max(0, min(1, (frame - 30) / 60))
width = round(value / 200 * 820 * progress)
차트 영역의 너비는 820픽셀입니다. 최종 상태에서 Email은 492픽셀, Chat은 738픽셀, Docs는 369픽셀입니다. 60번 프레임에서는 픽셀 반올림 차이를 제외하면 등장 효과가 절반 진행되지만, 라벨은 계속 원래 데이터를 보여 줍니다. 중간 시점의 측정값이 아니라 등장 연출입니다.
상하한을 적용하면 진행률이 0과 1 사이에 머뭅니다. 이 제약이 없으면 선형 계산으로 인해 시작 전에 음수 너비가 나오거나 종료 후 막대가 너무 길어질 수 있습니다. 데이터 그래픽에서 목표 길이를 넘어가는 연출은 실제 측정값보다 큰 값을 암시할 수 있습니다. 참조 구현은 의도적으로 그 효과를 사용하지 않습니다.
MP4를 내보내고 실제 파일 검사하기
검증이 성공하고 CHART_FONT를 설정했다면 렌더링합니다.
python3 render.py
스크립트는 Pillow로 RGB 프레임 360장을 그리고 FFmpeg에 파이프로 전달합니다. CSV 입력으로 셸 명령 문자열을 조합하지 않고 인수 목록을 사용합니다. 인코딩 설정은 libx264, yuv420p, 오디오 없음, +faststart입니다. FFmpeg 문서에서 입출력과 인코딩 옵션을, Pillow 그리기 참조 문서에서 프레임을 그리는 기본 기능을 확인할 수 있습니다.
예상 결과는 out/chart.mp4, 검토용 프레임 4장, 검증을 통과한 데이터 사본입니다. 실제로 사용할 앱에서 재생해 보세요. 프로세스가 정상 종료되어도 글자가 읽기 좋은지, 잘못된 해석을 유도하지 않는지까지 입증되지는 않습니다.
FFmpeg 도구가 설치되어 있다면 출력 파일을 별도로 검사하세요.
ffprobe -v error -select_streams v:0 \
-show_entries stream=codec_name,width,height,r_frame_rate,nb_frames \
-show_entries format=duration -of json out/chart.mp4
수정하지 않은 샘플의 기대값은 H.264, 1280 × 720, 30/1 프레임 레이트, 12초 길이입니다. 모든 컨테이너에서 프레임 수 메타데이터가 제공되는 것은 아닙니다. 필드가 없다고 0프레임으로 해석하지 마세요. 시작, 막대 등장, 마지막 정지 구간을 재생합니다. 최종 숫자가 120, 180, 90이고 척도가 여전히 0~200인지 확인하세요. 이 샘플에는 의도적으로 오디오 트랙을 넣지 않았습니다.
의미를 바꾸지 않고 문제 해결하기
| 증상 | 먼저 확인할 내용 | 적절한 조치 |
|---|---|---|
prepare.py가 잘못된 값을 보고함 | 빈 셀, 소수 비율, 천 단위 구분용 쉼표 | 데이터 형식을 바로잡고 누락값을 임의로 0으로 바꾸지 않기 |
| 값이 200을 넘음 | 실제 건수인지, 단위가 잘못되었는지 | 검증 규칙, 막대 너비, 눈금, 설명의 공통 상한을 함께 변경 |
| 새 CSV의 숫자가 나오지 않음 | 작업 디렉터리의 sample.csv를 바꿨는지, 렌더링이 성공했는지 | 해당 파일을 검증하고 다시 렌더링한 뒤 새 MP4와 out/accepted-data.json 확인 |
| 렌더러가 넓은 라벨을 거부함 | 선택한 글꼴과 대상 언어에서 라벨이 차지하는 너비 | 설명을 덧붙인 약어로 줄이거나 라벨 열을 재설계하고 차트 영역도 재확인 |
ffmpeg 또는 libx264가 없음 | 명령 경로와 설치된 인코더 지원 여부 | 신뢰할 수 있는 출처의 적절한 FFmpeg 빌드를 설치하고 버전 검사 재실행 |
| MP4에서 소리가 나지 않음 | 구성에 오디오가 포함되어 있는지 | 이 예제는 무음이 정상이며, 필요하면 연결된 음성 작업 절차를 참고해 추가 |
| 막대가 계속 늘어남 | 진행률 범위 또는 모델이 추가한 다른 애니메이션 | 프레임 기준의 상하한 있는 진행률 계산으로 복원 |
데이터가 커지면 배열을 늘리는 것 이상으로 설계 판단이 필요합니다. 열 개 항목은 더 긴 세로 레이아웃, 그룹화, 여러 장면이 필요할 수 있습니다. 음수는 양쪽 방향으로 뻗는 축이 필요하고, 백분율은 명확한 분모와 표시 규칙이 있어야 합니다. 이 세 항목의 건수 예제로 그러한 변경까지 검증한 것은 아닙니다.
데이터와 영상을 함께 전달하기
검증한 CSV, 소스 프로젝트, 최종 MP4와 함께 출처, 단위, 척도, 내보내기 설정, 실제 데이터인지 가상 데이터인지를 적은 짧은 메모를 묶으세요. 이 샘플을 공유할 때는 가상 데이터 표시를 유지합니다. 그 자리를 회사 로고로 바꿔 시청자가 실제 사업 실적으로 받아들이게 해서는 안 됩니다.
내레이션이 필요하면 보이스오버와 자막 동기화 절차를 참고하세요. 별도의 Remotion 프로젝트를 쓰므로 그 명령을 이 Python 압축 파일에 그대로 적용할 수는 없습니다. 세로형 결과물에는 가로 영상을 세로 레이아웃으로 바꾸는 튜토리얼이 도움이 됩니다. 라벨 배치를 바꾸지 않고 크기만 변경하면 차트를 읽기 어려워집니다. 다음 영상이 데이터보다 제품 맥락을 설명해야 한다면 실제 스크린샷을 이용한 데모 프로젝트가 적합한 출발점입니다.
모델은 애니메이션을 작성하고 수정하는 데 도움을 줍니다. 최종 설명의 신뢰성을 지키는 것은 검증한 CSV, 명시한 척도, 렌더링된 파일에 대한 확인입니다.
자주 묻는 질문
- Opus 5.5가 MP4를 직접 생성하나요?
- 이 작업에서는 Claude가 코드 작성과 수정을 돕고, Python이 프레임을 그린 뒤 FFmpeg가 영상을 인코딩합니다. 다운로드 프로젝트는 편집자가 작성해 로컬에서 검증한 참조 구현이며, 이번에 Opus가 생성한 결과물로 제시하지 않습니다.
- CSV를 제 데이터로 바꿔도 되나요?
- 입력 조건을 확인한 뒤 바꿀 수 있습니다. 이 예제는 고유한 라벨이 있는 정확히 3개 행과 0~200 사이의 정수 건수만 받습니다. 행이 더 많거나 값이 더 크면 레이아웃과 척도도 명시적으로 바꿔야 합니다.
- 막대가 늘어나는데 숫자는 왜 그대로인가요?
- 등장하는 동안에도 실제 건수를 표시하기 위해서입니다. 막대가 늘어나는 것은 등장 효과이지, 시계열이나 성장의 증거가 아닙니다.


