이벤트 리캡 비디오
780개 항목의 이벤트 라이브러리에서 전체적으로 테스트 완료. PATH에 ffmpeg/ffprobe와 Python 3.10+ 및 pip install pillow pillow-heif numpy가 필요합니다.
스크립트는 이 파일 옆에 있습니다. 프로젝트에 복사하세요:
scripts/analyze.py,build.py,reel.py,motion.py,fonts.py→ 프로젝트 루트scripts/work/*.py→<project>/work/examples/*.json→ 프로젝트 루트, 그런 다음 편집하세요.
프로젝트 구조: raw/ (수정되지 않은 원본), music/, work/ (캐시), output/, edit.json (전체 편집).
글꼴은 Windows/macOS/Linux에서 자동으로 찾습니다. FONT_SERIF, FONT_SERIF_BOLD, FONT_SANS_BOLD, FONT_BLACK, FONT_EMOJI로 재정의할 수 있습니다.
1. 미디어 가져오기
- 각 내보내기/압축 파일을
raw/아래에 자체 폴더에 넣으세요. 원본은 절대 수정하지 마세요. - Google 포토는 기존 라이브러리에 대한 API가 없습니다. 사용자의 로그인된 브라우저를 CDP를 통해 직접 제어하세요(이 리포지토리의
brave-cdp스킬 참조). 그리드 항목은a[href*="/photo/"]입니다. 일자 헤더는[role=checkbox][aria-label^="Select all photos from"]입니다. - 진짜 마우스 이벤트(
Input.dispatchMouseEvent)로 일자 헤더를 선택하고,"N selected"텍스트를 확인한 후 Shift+D를 누르세요. 탭이 앞에 있어야 합니다(Page.bringToFront). 그렇지 않으면 그리드가 회색으로 유지됩니다. - Google은 다운로드 후 선택을 지우고 헤더
aria-checked가 오래될 수 있습니다. 다시 선택하기 전에 페이지를 새로고침하세요. Browser.setDownloadBehavior를allowAndName과 함께 사용하면 ZIP 파일을 GUID로 확장자 없이 저장합니다. 완료를 위해Browser.downloadProgress를 모니터링하세요.
2. 분석 및 선택
python analyze.py→work/media.json(EXIF/비디오creation_time에서 현지 시간대로 캡처 시간, 블러, 밝기, 중복, 음량) +work/sheets/에 일자별 연락처 시트 생성.python work/vsheets.py→ 비디오당 3프레임 스트립 생성. 모든 시트를 확인하세요. 녹화 중 회전하는 클립, 주머니 샷 및 어두운 야간 클립은 건너뛰세요.python work/loudest.py ID:seconds ...는 가장 큰 윈도우(노래, 연설, 환호)를 찾습니다. 트리밍 전에 1fps 프레임 스트립으로 확인하세요.- 공유/전달된 파일에는 캡처 날짜가 없습니다(파일 mtime으로 대체). 눈으로 직접 배치하세요.
3. 편집 (관객이 좋아하는 방식)
- 비디오로 시작하세요 (~90% 클립). 강한 그룹 샷에만 사진을 사용하세요. 사진이 많은 컷은 느리게 느껴집니다.
- 콜드 오픈 훅: 1.2–1.8초 길이의 클립 8–10개,
hook_xf0.1로 거의 하드 컷, 그 다음 타이틀 카드. 그런 다음 각 날짜의 첫 번째 클립에 작은"label": "Day N · date"를 붙여 순서대로 나열하고, 3–4초 컷, 몇 개의 9–12초 순간은"speech": true로 표시(음악이 아래로 깔림). - 음악이 훅을 성공시키거나 망칩니다. 하나를 반복하는 대신 비슷한 템포의 트랙 2개를 연결하세요(
"music": [a, b], 3초 크로스페이드).python work/bpm.py file.mp3는 템포를 추정합니다. edit.json키:title, subtitle, closing, closing_sub, title_bg / closing_bg(+ 비디오 ID를 위한_bg_at),music/vertical_music,music_volume, duck_volume, ambient_volume, photo_seconds, hook_xf, closing_seconds, horizontal_hook, horizontal, vertical_hook, vertical. 세그먼트:{"id", "at" (0–1 중앙) | "start", "dur", "speech", "label", "xf"}.python work/shortlist.py→output/shortlist.jpg(모든 컷에서 한 프레임). 렌더링 전에 사용자에게 보여주세요.
4. 렌더링 및 QC
python build.py [horizontal|vertical|vertical-full]—work/seg에 세그먼트별 캐시, xfade 체인, loudnorm −14 LUFS, x264.EDIT=other.json OUT_SUFFIX=-v2 python build.py는 기본 편집을 건드리지 않고 대체 편집을 렌더링합니다.- 모든 렌더링을 QC:
nb_frames == duration*30(xfade 체인은 프레임을 떨어뜨릴 수 있음),blackdetect개수 0, ebur128 ≈ −14 LUFS, 그리고 프레임 타일 시트(fps=1/5,tile=8x6)로 회전 및 잘린 제목을 육안으로 확인. - ffmpeg 7+는 더 이상 사용되지 않는
-filter_complex_script보다-/filter_complex file을 선호합니다.
5. 비트 싱크 릴 (IG / TikTok / FB) — reel.py + reel.json
python reel.py→output/reel.mp4(~45초), build.py의 세그먼트 렌더러를 기반으로 구축.- 컷은 비트 그리드에 정확히 맞춰집니다(
bpm힌트, 자동 위상, 프레임 반올림 컷 시간). 템포를 다시 확인하세요: 단순 추정기는 종종 절반/두 배를 반환합니다(85 대 154). - 첫 1초 = 가장 놀라운 순간, "POV: …" 줄 포함. 4비트 컷, 히어로 순간에 6–8비트, 모든 클립에서 느린 푸시인, 섹션 시작 시 흰색 플래시.
- 텍스트: 두꺼운 검은색 외곽선이 있는 흰색 두꺼운 산세리프, 상단에서 약 24% 위치(TikTok/IG 버튼과 겹치지 않음), 슬라이드 업 페이드. 총 5–7개의 짧은 줄; 마지막 줄은 이벤트 이름입니다.
6. 밈 / 모션 컷 — motion.py + motion.json (사용자가 밈/스티커를 요청할 때만)
- 많은 사람들이 이 스타일을 진심 어린 이벤트에 과하다고 생각합니다. 기본적으로 섹션 3–5를 사용하세요.
- 연결 대신 하나의 길고 꾸준한 트랙(~3분); 콤-필터 검색을 통한 비트 그리드.
- 클립당:
beats,speed(0.5 슬로우 모션 / 2 빨리 감기),freeze(비트; 테이프 중지 + 무음 + 채도 감소),cap스티커 (둥근 상자, 기울임, 탄력 팝, 컬러 이모지),day슬램 제목 + 윙 소리,title,verse,shake,punch,flash,zoom. - 렌더링이 중단된 경우, 다시 실행하기 전에 ffprobe에 실패하는 클립 파일을 삭제하세요(캐시가 이를 재사용할 수 있음).
7. 세로형 및 소셜 전달
- 누군가 16:9 편집을 승인하고 9:16을 요청하면, 동일한 편집의 세로형을 제공하세요(
python build.py vertical-full). 승인된 편집을 다시 스타일링하지 마세요. "더 매력적으로 만들어 달라"는 것은 다듬기만 의미합니다. - 플랫폼(특히 Facebook)은 라이선스 없는 음악이 포함된 게시물을 음소거합니다. 원본 사운드 버전(
"music": null편집) 및/또는 무음 복사본(ffmpeg -i in.mp4 -an -c copy out.mp4)을 제공하여 플랫폼의 라이선스 라이브러리에서 음악을 추가할 수 있도록 하세요. - 최종 다듬기:
eq=contrast=1.07:saturation=1.2:gamma=0.97,colorbalance=rm=0.03:bm=-0.03:rh=0.02:bh=-0.02,unsharp=5:5:0.45,vignette=angle=PI/5.5+ 오디오highpass=80,dynaudnorm,acompressor,loudnorm=I=-14.