Communitygithub.com

vedit

사용자가 최종 비디오 파일을 요청할 때 사용합니다. 세그먼트 렌더링(캐시 포함), 가드 연접(guarded concat), 단일 패스 오디오, 음량 정규화(loudness normalisation), 단일 먹싱(mux)을 처리합니다.

vedit란 무엇인가요?

이 스킬은 AI 에이전트가 비디오 편집 파이프라인의 최종 내보내기(export) 단계를 담당하도록 설계된 전문 작업입니다. 주로 'exportier das', 'render das fertig', 'export the final', 'render the final cut', 'give me the mp4' 등 사용자의 다양한 최종 파일 요청을 감지하여 실행됩니다. 지원하는 AI 에이전트 도구로는 Claude Code, Cursor, Codex 등을 가정하며, 특정 플랫폼(예: YouTube, TikTok)에 맞춰 출력할 수 있습니다. 핵심 동작 원리는 먼저 각 비디오 세그먼트를 개별적으로 렌더링하여 캐시(.cache/seg/)에 저장하고, 이후 변경된 세그먼트만 다시 렌더링하여 효율성을 극대화합니다. 그 다음 가드 연접(guarded concat)을 통해 모든 세그먼트가 동일한 인코딩 매개변수를 가졌는지 확인한 후 무손실로 결합합니다. 오디오는 타임라인 전체를 단일 패스로 렌더링한 후, 대상 플랫폼의 음량 기준(LUFS)에 맞추기 위해 2-패스 loudnorm을 적용합니다. 마지막으로 비디오와 오디오를 단 한 번 먹싱(mux)하여 최종 MP4 파일을 생성합니다. 이 과정은 캐시를 적극 활용하여 두 번째 내보내기를 몇 초 만에 완료할 수 있게 해주며, 비디오의 재인코딩을 방지하여 품질을 보존합니다. 또한 엄격한 사전 검사(QC)와 사후 검증 단계를 포함하여 출력 파일의 무결성을 보장합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/businessbaum/vedit/tree/HEAD/.agents/skills/export-final

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

export-final

완성된 파일을 조합합니다. 인수: $project 슬러그, $platform은 사용자가 두 번째 결과물을 원할 경우 output.platform을 재정의합니다. 전체 요청은 $ARGUMENTS에 있습니다. 빈 $-플레이스홀더는 스킬이 슬래시로 호출된 것이 아니라 자동 트리거되었음을 의미합니다. 세션 컨텍스트의 PIPELINE_STATE에서 프로젝트를 가져와 선택한 프로젝트를 알려주세요. 동사 이름은 빌드 계약을 따릅니다. python engine/ve.py --help가 최우선입니다.

결정된 렌더링 아키텍처

  • 비디오: 세그먼트당 하나의 캐시된 MP4/MKV, 동일한 인코딩 매개변수, 각각 IDR 프레임에서 시작한 후 -f concat -safe 0 -c copy로 결합합니다. 무손실 및 거의 즉시 처리됨이 확인되었습니다.
  • 오디오: 전체 타임라인에 걸쳐 단일 연속 패스로 pcm_s24le로 렌더링합니다. 세그먼트별로 절대 캐시하지 않습니다.
  • 한 번 먹싱(mux): AAC를 정확히 한 번 인코딩합니다.

내보내기 시점에 이 구조를 재설계하지 마십시오. 특히 모든 세그먼트에 대해 하나의 filter_complex로 "단순화"하지 마십시오. 150개 세그먼트 그래프는 약 19,000자이며, 약 260개 세그먼트에서는 Windows 명령줄 길이를 초과하여 유용한 오류 대신 실행 불가능한 프로세스가 생성됩니다. 또한 세그먼트별 캐시를 무효화하는데, 이 캐시 덕분에 두 번째 내보내기가 몇 초 만에 완료됩니다.

필터그래프는 항상 파일로 저장하고 -/filter_complex fc.txt로 전달합니다. 길어질 때만이 아니라 무조건 이렇게 해야 합니다.

1단계 - 사전 점검

인코딩 전에 다음을 수행합니다:

  1. QC 패스를 실행합니다. QC에 실패한 프로젝트를 내보내는 것은 파이프라인에서 가장 오래 걸리는 작업을 낭비하는 것입니다.
  2. output.platform을 확인합니다. 이는 음량 목표, 해상도 및 자막 안전 영역을 결정합니다. $platform이 output.platform과 다르면 프로젝트를 조용히 변경하지 말고 두 번째 출력 경로를 렌더링하고 각각이 무엇인지 알려주세요.
  3. 계획을 보고합니다: 세그먼트 수, 예상 총 프레임 수, 예상 길이, 코덱, 그리고 이번 패스에서 자막과 그래픽이 함께 인코딩(burn-in)되는지 여부.

2단계 - 세그먼트 렌더링

python engine/ve.py render $project

.cache/seg/ 아래에 세그먼트별로 캐시되며, 키는 소스 강력 키(source strong key), 시작/종료 프레임, 필터, 인코더 및 도구 버전으로 결정됩니다. 변경된 세그먼트만 다시 렌더링됩니다. --only seg_0012는 하나의 세그먼트만 검사용으로 렌더링합니다.

인코더 기본값: h264_nvenc, cq 20, preset p6. 이 Ada 카드의 NVENC는 대략적인 VMAF 기준으로 libx264와 동등합니다. 2Mbps에서 0.19 VMAF 뒤지고, 8Mbps에서 0.06 앞서며, 2-4배 더 빠릅니다. 프리뷰에는 적절한 기본값이며 최종본에도 방어 가능한 선택입니다. 사용자가 비트당 최대 품질을 요청하고 기꺼이 기다리겠다고 할 때만 libx264로 전환하세요.

두 인코더 모두 이 머신에서 실행 간에 바이트 재현 가능(byte-reproducible)하며, 이것이 콘텐츠 주소 지정 세그먼트 캐싱(content-addressed segment caching)을 안전하게 만드는 이유입니다.

3단계 - 연접, 하지만 먼저 보호

concat_compatible()는 예외 없이 모든 -c copy 연접 전에 실행됩니다. 매개변수 불일치 시 연접 디먹서(demuxer)는 종료 코드 0으로 손상된 파일을 반환합니다. 경고나 오류 없이, 10초 동안 재생되다가 망가지는 파일입니다. QC 검사 (c)가 바로 이 검사입니다.

모든 세그먼트의 해상도, 픽셀 형식, 코덱, 프로필, 레벨, 타임베이스, 샘플레이트, 채널 레이아웃을 비교합니다. 불일치는 세그먼트가 다른 매개변수로 렌더링되었음을 의미합니다. 일반적으로 인코더 설정이 변경되기 전의 오래된 캐시 항목입니다. 연접을 강제하지 말고 문제가 있는 세그먼트를 다시 렌더링하세요.

4단계 - 오디오 및 음량

python engine/ve.py render $project

그런 다음 output.loudnorm의 플랫폼 목표에 맞춰 2-패스 loudnorm을 적용합니다. (YouTube: I -14, TP -1.5, LRA 11; 다른 플랫폼은 presets/formats/에 있습니다.)

패스 2에는 반드시 명시적인 -ar 48000을 포함해야 합니다. 그렇지 않으면 출력이 조용히 192kHz가 됩니다. loudnorm의 내부 레이트가 출력에 누출되어 파일 크기가 예상보다 4배 커지고 일부 플레이어가 제대로 리샘플링하지 못합니다. 이는 전체 체인에서 가장 많이 놓치는 플래그입니다.

단일 패스가 아닌 2-패스를 사용하세요. 단일 패스 loudnorm은 동적 추정치이며, 조용한 시작部分이 있는 자료(모든 인터뷰 영상)에서 목표보다 1데시벨 이상 벗어납니다.

5단계 - 한 번 먹싱

2단계부터 5단계까지는 모두 ve render $project입니다. 캐시된 세그먼트를 렌더링하거나 재사용하고, 연접하고, 오디오를 한 패스로 렌더링하고, 음량을 정규화한 다음, AAC 320k를 projects/$project/out/final.mp4 (output.path 기준)로 정확히 한 번 먹싱합니다.

먹싱 시 비디오를 재인코딩하지 마십시오. 화면에 변경이 필요한 경우 세그먼트 수준에서 변경하고 캐시가 나머지를 처리합니다.

먹싱 후 ve render는 렌더링된 오버레이를 합성하고 captions.burn_in이 설정된 경우 ASS 자막을 입힙니다. 이 순서대로 처리되므로 자막이 그래픽 위에 위치합니다. 둘 다 마스터를 재인코딩하므로 ve render 전에 ve gfx와 ve captions를 실행해야 합니다. 이후에 실행하면 마스터가 한 버전 뒤처지게 되며 경고도 없습니다.

ve export는 별도의 이후 단계입니다. 전체 QC를 실행하고, 실패 시 --force를 전달하지 않으면 거부한 다음, 날짜가 포함된 전달용 복사본을 스탬프하고 그 옆에 .manifest.json을 작성합니다.

6단계 - 결과물 확인 후 전달

계획이 아닌 실제 출력 파일에 대해 필수 검사를 실행합니다:

  • 프레임 수가 활성화된 세그먼트의 (out_frame - in_frame) 합계와 일치하는지 확인합니다. QC (a).
  • 오디오 샘플 수가 frames / fps * 48000과 일치하는지 확인합니다. QC (b).
  • ebur128 통합 음량(integrated loudness)이 플랫폼 목표의 0.5 LU 이내이고, 실제 피크(true peak)가 한도 아래인지 확인합니다. QC (f).
  • 컨테이너, 해상도, 프레임 레이트, 길이가 output과 일치하는지 확인합니다.
  • 세 프레임을 무작위 점검합니다: 첫 번째 프레임, 중간의 세그먼트 경계, 마지막 프레임. 경계에서 검은 프레임이 보이면 세그먼트가 짧게 렌더링된 것입니다.

그런 다음 보고합니다: 출력 경로, 파일 크기, 길이, 측정된 LUFS 및 실제 피크, 프레임 수, 세그먼트 수 및 캐시에서 가져온 세그먼트 수. stage를 "export"로 설정합니다.

두 번째 결과물

세로 컷(vertical cut)은 완성된 파일을 다시 자르는 것이 아닙니다. 다른 output.platform을 의미하며, 이는 다른 음량 목표, 다른 자막 프리셋, 다른 안전 영역, 그리고 일반적으로 다른 스토리 패스를 의미합니다. 16:9 마스터를 크기 조정하는 대신 이 점을 설명하세요.

실패 모드

증상원인해결 방법
출력이 재생되다가 끊김, ffmpeg 종료 코드 0연접에서 매개변수 불일치모든 연접 전에 concat_compatible() 실행; 문제 세그먼트 다시 렌더링
마스터가 192kHzloudnorm 패스 2에 -ar 48000 누락추가하고 패스 2 다시 실행
인코딩 프로세스 시작 실패명령줄에 필터그래프가 있음항상 fc.txt를 작성하고 -/filter_complex 전달
음량이 목표에서 1데시벨 벗어남단일 패스 loudnorm2-패스 사용
내보내기가 매번 느려짐변경된 인코더 설정으로 인해 캐시 무효화의도된 설정 변경인지 확인
컷에서 검은 프레임세그먼트가 짧게 렌더링됨해당 세그먼트 다시 렌더링; QC (a) 확인
최종본에서 프리뷰보다 음성이 더 작음amix에 normalize=0 누락오디오 그래프에서 수정하고 오디오 다시 렌더링

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

businessbaum/vedit

This skill should be used when the user asks for subtitles or on-screen text of what is being said - "brenn die Untertitel ein", "mach Untertitel", "Untertitel drauf", "leg Untertitel drüber", "brenn die Subs ein", "mach die Captions", "Wort für Wort Untertitel", "Karaoke-Untertitel", "korrigier den Untertitel-Text", "burn in the captions", "add subtitles", "burn the subs", "word-by-word captions", "fix a caption typo". Covers ASS generation, the pixel-width grouping rule for German, the font table, and burn-in through libass.

businessbaum/vedit

This skill should be used when the user asks for mechanical tightening of material that is already selected - "mach den Rohschnitt", "bau den Rohschnitt", "schneid die Ähms raus", "nimm die Füllwörter raus", "entferne die Pausen", "kürz die Pausen", "schneid die Versprecher raus", "mach den Radioschnitt", "straff das", "build the rough cut", "cut the fillers", "remove the ums", "tighten the pauses", "trim the dead air", "cut the retakes", "radio edit". Turns kept story blocks into enabled segments in project.json. Does not decide what the video is about - that is cut-story.

businessbaum/vedit

This skill should be used when the user asks to decide what the video is actually about before any mechanical cutting - "bau die Story", "was soll ins Video", "was kann raus", "welche Themen bleiben", "kürz das auf 6 Minuten", "mach daraus ein kurzes Video", "wo ist der Hook", "sortier die Themen", "worum geht es hier eigentlich", "build the story", "decide what stays", "structure this", "cut this down to N minutes", "find the hook", "reorder the topics". This is the CONTENT-selection pass that writes the "story" block in project.json; it runs after transcribe and before cut-rough.

관련 스킬