Skip to main content

render-final

ffmpeg recipes for rendering the final cut from raw.mp4 + cuts.json, plus encoder settings and validation.

소스 정보

저장소
justrach/empeefour
최근 소스 활동
2026년 5월 9일 07:11
감지된 SKILL.md 언어
영어
스타
0
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
render-final
description
ffmpeg recipes for rendering the final cut from raw.mp4 + cuts.json, plus encoder settings and validation.
when-to-use
After cuts.json exists. Final step before overlay-music or before delivery if there's no music.
# Render Final Build `final.mp4` by trimming each keep-span from `raw.mp4` and concatenating them. Source-order only — never reorder. ## Encoder settings (shortform-safe) | Setting | Value | Reason | |---|---|---| | video codec | `libx264` | Universal, good quality at low bitrates | | crf | `20` | Visually lossless for talking-head; lower = bigger file | | preset | `medium` | Fine balance; `slow` for archival, `fast` for iteration | | audio codec | `aac` | Universal | | audio bitrate | `128k` (160k if music) | Plenty for voice + music | | pixel format | `yuv420p` | Required for broad compatibility (esp. Safari/Twitter) | | flags | `+faststart` | Moves moov atom to start so the file streams | ## Filter graph pattern For N keep-spans `[(s1,e1), (s2,e2), …]`: ```bash ffmpeg -y -i raw.mp4 \ -filter_complex " [0:v]trim=start=$s1:end=$e1,setpts=PTS-STARTPTS[v0]; [0:a]atrim=start=$s1:end=$e1,asetpts=PTS-STARTPTS[a0]; [0:v]trim=start=$s2:end=$e2,setpts=PTS-STARTPTS[v1]; [0:a]atrim=start=$s2:end=$e2,asetpts=PTS-STARTPTS[a1]; ... [v0][a0][v1][a1]...concat=n=N:v=1:a=1[v][a] " \ -map "[v]" -map "[a]" \ -c:v libx264 -crf 20 -preset medium -pix_fmt yuv420p \ -c:a aac -b:a 128k \ -movflags +faststart \ final.mp4 ``` Build the graph string in code — don't hand-write it for >3 spans. ## Rendering with a tail If `cuts.json` has a `tail` block, append the source from `tail.from` to `tail.to` (or end of source) after the keep-spans: ```bash # N hook spans + 1 tail = N+1 segments in the concat ffmpeg -y -i raw.mp4 \ -filter_complex " [0:v]trim=start=$s1:end=$e1,setpts=PTS-STARTPTS[v0]; [0:a]atrim=start=$s1:end=$e1,asetpts=PTS-STARTPTS[a0]; ... [0:v]trim=start=$tail_from,setpts=PTS-STARTPTS[vt]; [0:a]atrim=start=$tail_from,asetpts=PTS-STARTPTS[at]; [v0][a0]...[vt][at]concat=n=N+1:v=1:a=1[v][a] " \ -map "[v]" -map "[a]" \ -c:v libx264 -crf 20 -preset medium -pix_fmt yuv420p \ -c:a aac -b:a 128k -movflags +faststart \ final.mp4 ``` If `tail.to` is set, use `:end=$tail_to` on both trims. If `tail.from` is the same as the last keep-span's end, the cut is seamless — there's no jump, the source just keeps playing. When music is overlaid, music covers ONLY the hook portion (sum of keep-span durations). See `overlay-music/SKILL.md` — the music track needs an `afade=out` ending before `tail.from` so it doesn't bleed into the body. ## Validation ```bash ffprobe -v error -show_entries format=duration \ -of default=noprint_wrappers=1:nokey=1 final.mp4 ``` Confirm: - Duration is within the target window from `cuts.json`. - Sum of `keep_span` durations matches output duration ± 0.05s. If it doesn't, the filter graph is wrong (usually a `setpts` missing on a trim output). For audio sanity: ```bash ffmpeg -hide_banner -i final.mp4 -af volumedetect -f null - ``` - `mean_volume` between -25 and -15 dB - `max_volume` below -1 dB (no clipping) ## Common failure modes - **Output is half-length.** `setpts=PTS-STARTPTS` is missing on a video trim, or `asetpts` is missing on an audio trim. Both are required to reset the timestamp on each segment. - **Audio drifts.** Re-encoding with `-c:v copy` while still re-encoding audio. Use `-c:v libx264` unless you're certain the source codec is shippable. - **Black flash between cuts.** Not actually a render bug — it's the cut happening on a frame the encoder can't reproduce cleanly. Either move the boundary to a nearby word or accept it. - **No audio in output.** The `concat` filter needs `v=1:a=1` and you must `-map` both `[v]` and `[a]`.
GitHub에서 보기