TikTok / Douyin 숏폼 동영상 생성기
에이전트는 창의적인 작업(대본, 장면 분할, 검색 키워드, 스타일 선택, 품질 검토)을 수행합니다. scripts/ 디렉토리의 스크립트는 기계적인 작업(TTS 및 단어 타임스탬프, 자산 검색 및 다운로드, 자막 렌더링, ffmpeg 합성, 음량 정규화)을 처리합니다.
모든 작업은 libass/drawtext 없이 핵심 ffmpeg와 Python venv만으로 실행됩니다. API 키가 없어도 작동하며, PEXELS_API_KEY / PIXABAY_API_KEY 환경 변수가 설정되면 실제 스톡 비디오 클립(더 좋음)을 사용할 수 있습니다.
워크플로우
0. 초기 설정 (.venv/ 및 assets/fonts/가 이미 존재하면 건너뜁니다)
bash scripts/setup.sh
1. 먼저 사실을 확인한 후 대본 및 스토리보드 작성
에이전트의 내부 지식은 오래되었거나 틀릴 수 있습니다 — 검증되지 않은 주장을 동영상에 절대 넣지 마십시오. 장면 텍스트를 작성하기 전에 웹 검색 도구를 사용하여 모든 구체적인 주장(숫자, 통계, 기록, 가격, 날짜, 순위, 그리고 모든 '최초/가장 큰/유일한/가장 빠른' 문장 — 그리고 뉴스, 제품, 버전, '올해/최신'과 같은 시간에 민감한 내용)을 확인하십시오. 규칙:
- 출처에서 명시한 대로만 대본에 주장을 포함하십시오 — 출처에 맞게 표현을 조정하고, 그 반대는 안 됩니다.
- 확인할 수 없으면? 확인 가능한 주장으로 대체하거나 삭제하십시오. 게시된 동영상에서 잘못된 숫자는 약한 후크보다 더 나쁩니다.
- 스토리보드의
"sources": [...]에 신뢰한 URL을 기록하십시오. 이 URL은review/report.txt에 반영되어 사용자가 동영상을 검토할 수 있습니다. - 진정으로 웹에 접근할 수 없는 경우, 오래된 교과서 사실에 의존하고 구체적인 수치는 피하며, 사용자에게 동영상이 검증되지 않았음을 알리십시오.
대본 공식(후크 유형, 페이싱, 장면 구조)은 references/writing-guide.md를 참조하십시오. 그런 다음 projects/<slug>/storyboard.json을 생성하십시오:
{
"title": "深海里最诡异的5种生物",
"lang": "zh",
"aspect": "9:16",
"voice": "zh-CN-YunjianNeural",
"rate": "+10%",
"caption_style": "karaoke",
"bgm": {"mood": "mystery", "gain_db": -16},
"hook": {"text": "深海禁区", "seconds": 2.3},
"scenes": [
{
"text": "你知道吗?在阳光永远照不到的深海,藏着比科幻电影更诡异的生物。",
"keywords": ["deep sea NOAA ocean exploration", "submarine dark ocean"],
"providers": ["openverse", "wikimedia"],
"badge": null,
"effect": "kb_in"
},
{
"text": "第一名,鮟鱇鱼……",
"keywords": ["humpback anglerfish", "anglerfish museum"],
"badge": "第1名"
}
]
}
필드 참조:
| 필드 | 값 | 참고 |
|---|---|---|
lang | zh | en | 자막 그룹화 + 기본 음성 설정 |
aspect | 9:16 (기본값) | 16:9 | 1:1 | |
voice | 모든 edge-tts 음성 | zh: zh-CN-YunjianNeural(매력적인 남성) zh-CN-XiaoxiaoNeural(여성) zh-CN-YunxiNeural(밝은 남성); en: en-US-ChristopherNeural en-US-AriaNeural en-US-GuyNeural |
rate | 예: +10% | 마케팅 채널 페이싱: zh +8%+15%, en +5%+10% |
caption_style | karaoke | pop | none | karaoke = 단어별 하이라이트 (권장) |
bgm | {"mood": ...} | {"query": "스타일 단어"} | {"file": "path.mp3"} | {"mood":"none"} | 기본값은 mood: 선별된 테이블(upbeat funny inspiring chill tech mystery epic sad horror)은 수많은 마케팅 채널이 사용하는 정확한 MacLeod 필수 트랙입니다 — 입증되었고, 안전하며, 프로젝트마다 다양합니다. 내용 스타일에 맞는 분위기가 없거나 사용자가 장르를 지정한 경우에만 query를 사용하십시오: 실제 CC 비트 음악(ccMixter 스타일 태그 + Openverse/Jamendo; ND/NC 제외)을 검색하며 각 후보는 비트 트래커에 의해 선별됩니다 — 자신 있는 75–175 BPM 그루브가 없으면 선택되지 않습니다. 스타일 단어가 태그에 매핑됩니다: trap/phonk, hip hop, lofi/chill, edm/dance, epic/cinematic, quirky. 둘 다 설정할 수 있습니다 — query가 먼저 시도되고, mood는 대체재입니다. file = 사용자의 자체 트랙 |
bgm.vibe | "spedup" | "slowed" | 설정 안 함 | 抖音 시그니처 사운드: spedup ≈ 1.25배속 및 피치 상승(카딩/정리 영상의 주류 처리), slowed = 느린 + 리버브(감성/분위기). file을 포함한 모든 BGM 소스에 적용되며, 처리 후 비트 그리드가 재분석되어 카딩 정확도 유지 |
beat_sync | true (기본값) | false | BGM의 비트를 분석하여 자신 있는 그리드가 있을 때 모든 장면/컷 전환이 비트 그리드에 맞춰집니다(카딩). VO는 절대 잘리지 않으며, 호흡 패드만 유연하게 조정됩니다 |
hook | {"text","seconds"} | 시작 부분에 표시되는 큰 제목 카드, 8자/단어 이하 |
sticky_title | {"text": ...} | 상단에 고정되는 선택적 주제 표시줄. 기본값은 꺼져 있음 — 사용자가 요청한 경우에만 추가 |
sfx | true (기본값) | false | 장면 전환 시 윙 소리 |
scene keywords | 영어, 구체적인 명사 쿼리 목록 | 각 항목 = 하나의 샷(시각적 자료); 동영상은 약 3초마다 새로운 시각 자료로 전환되므로, 4초 이상의 장면에는 2-3개의 쿼리를 제공하십시오(쿼리를 적게 주면 추가 샷이 쿼리를 순환하며 자동 추가됨) |
scene badge | 예: "第1名" / "TOP 1" | 장면 시작 부분에 표시되는 큰 스탬프 레이블 — 목록형 콘텐츠에 사용 |
scene providers | 목록 | 키 없이 이미지: openverse wikimedia nasa; 키 없이 실제 비디오: wikimedia_video (Commons 클립, 서버 트랜스코딩) nasa_video (퍼블릭 도메인 우주/과학) archive_video (Prelinger 퍼블릭 도메인 역사 영화); 키 있음: pexels_video pexels_photo pixabay_video |
scene effect | auto kb_in kb_out pan_left pan_right static | 첫 번째 샷의 Ken Burns 모션; 이후 샷은 자동 순환 |
scene emphasis | 부분 문자열 목록 | 영구적으로 강조 표시될 단어(pop 스타일) |
scene media | 파일 경로 | 검색 건너뛰고 자체 파일 사용(예: 직접 다운로드한 파일) |
경험 법칙(게시 기준): 총 45–75초, 6–9개 장면, 장면당 하나의 아이디어, 장면당 2–3개 샷. 장면 텍스트는 중국어 20–45자 / 영어 14–30단어. 약 40초 미만이거나 전체가 단일 샷 장면인 동영상은 빈약해 보입니다 — 그런 상태로 출시하지 마십시오.
2. 파이프라인 실행
.venv/bin/python scripts/pipeline.py projects/<slug>
또는 단계별로: tts.py → assets.py → bgm.py → compose.py → check.py.
3. 검토 — 차이를 만드는 단계 (필수)
무료 이미지 검색은 완벽하지 않습니다. 항상 이미지 도구로 다음 두 파일을 보고 사람 편집자처럼 판단하십시오:
-
projects/<slug>/media/assets_sheet.jpg— 자산 단계 후 생성됩니다. 샷은01a 01b 02a …로 레이블이 지정됩니다. 내레이션과 명확히 일치하지 않는 모든 샷에 대해 다시 가져오십시오:.venv/bin/python scripts/assets.py projects/<slug> --scene 3 --shot 2 --keywords "better english nouns"(다시 가져오면 거부된 자산이 자동으로 블랙리스트에 추가됩니다. 모든 장면이 일치할 때까지 반복하십시오. 자체 도구로 이미지를 직접 다운로드하여 scene
media에 지정할 수도 있습니다.)파이프라인은 또한 각 샷의 소스 제목을 쿼리와 비교하여 텍스트 감사를 수행하고
[!] OFF-TOPIC플래그를 출력합니다. 플래그가 지정된 샷이 시각적으로 확인 결과 실제로 올바른 경우(예: 제목이 없지만 완벽한 사진),media/manifest.json에서 해당 샷에"approved": true를 설정하여 플래그를 해제하십시오 — 시각적 판단이 텍스트 감사보다 우선합니다. 절대 맹목적으로 승인하지 마십시오. -
projects/<slug>/review/contact_sheet.jpg— compose+check 단계 후 생성됩니다. 확인 사항: 자막이 읽기 쉽고 동기화되었는지, 잘못되거나 보기 흉한 프레임이 없는지, 후크가 보이는지. 문제를 수정(스토리보드 편집 → compose 재실행, 빠름)하여 마케팅 채널 편집자가 실제로 게시할 동영상처럼 보일 때까지 반복하십시오.
review/report.txt에는 길이/음량 확인 및 붙여넣기 준비가 된 출처 정보 블록(CC-BY 출처 + 음악 크레딧)이 포함되어 있습니다 — 항상 final.mp4와 함께 사용자에게 제공하십시오.
자산 검색 팁 (가장 큰 품질 레버)
- 키워드는 영어로, 1~4단어, 구체적인 시각적 명사("humpback anglerfish", "scuba diver silhouette")여야 하며, 추상적 개념("mystery", "success")은 절대 안 됩니다.
wikimedia는 동물/과학/역사/장소에 가장 적합합니다.openverse(Flickr 등)는 라이프스타일/풍경/분위기에 좋습니다.nasa는 우주용입니다. 키가 있으면pexels_video/pixabay_video실제 영상이 잠금 해제됩니다 — 가능하면 이것들을 선호하십시오.- 문맥 단어를 추가하여 모호성을 해소하십시오: "NOAA", "museum", "aquarium", "macro".
- 장면이 계속 실패하면 단어만 바꾸지 말고 시각적 개념 자체를 바꾸십시오(예: "5% 탐사됨"에 대해 "통계" 대신 잠수부 실루엣 표시).
wikimedia_video검색은 부정어를 지원합니다 — Commons 날씨/우주 쿼리는 위성 루프에 묻히므로, 예:"lightning storm -CIRA -satellite -JPSS"와 같이 작성하십시오. 영어 외 단어는 추가 영상을 얻을 수 있습니다("Blitz Gewitter", "tormenta rayos"). 일반 명사보다는 명명된 주제("Fagradalsfjall lava drone")를 선호하고, 시트에서 비디오 썸네일을 항상 눈으로 확인하십시오: 내장 자막, 워터마크, 튜토리얼 및 CGI 프로모션을 조심하십시오.
문제 해결
edge-tts네트워크 오류: 4회 재시도합니다. 계속 실패하면tts.py를 다시 실행하십시오.- BGM 다운로드 실패:
bgm.py를 다시 실행(재시도 + 캐시)하거나,--mood none을 사용하거나, mp3를assets/bgm/에 넣고bgm.file을 설정하십시오. - BGM 스타일이 맞지 않음: 쿼리를 세분화하십시오(
bgm.py <dir> --query "..."후--skip-tts --skip-assets로 재구성). 진정한 현재 유행 사운드의 경우mood: none(또는 낮은 게인)으로 전달하고 사용자에게 업로드 시 TikTok/抖音의 앱 내 라이선스 음악 라이브러리에서 트렌딩 트랙을 추가하도록 안내하십시오 — 이는 합법적이며 알고리즘에 유리합니다. 장면 속도는 변경되지 않으므로 컷 타이밍은 여전히 깔끔합니다. check.py가 "컷이 비트에 맞음"을 출력합니다. 비트 동기화가 건너뛰어진 경우(낮은 그리드 신뢰도, 예: 비트 없는 앰비언트 음악), 더 안정적인 트랙을 선택하고(--query "trap beat"등) 재구성하십시오.- 공급자가 오류를 반환하거나 비어 있어도 괜찮습니다 — 다른 공급자가 대체합니다. 장면별 로그를 확인하십시오.
- 스토리보드 편집 후 재구성은 저렴합니다(
--skip-tts --skip-assets를 pipeline.py와 함께 사용하거나 compose.py를 직접 실행). 장면 텍스트를 변경하려면tts.py를 다시 실행해야 합니다. - 자막의 이모지는 macOS(Apple Color Emoji)에서 렌더링됩니다. Linux에서는 NotoColorEmoji가 설치되지 않으면 삭제됩니다. 의미 전달에 이모지에 의존하지 마십시오.
전달
사용자에게 final.mp4, review/report.txt의 출처 정보 블록, 그리고 (요청 시) 커버 이미지로 review/cover.jpg를 제공하십시오.