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단계 - 사전 점검
인코딩 전에 다음을 수행합니다:
- QC 패스를 실행합니다. QC에 실패한 프로젝트를 내보내는 것은 파이프라인에서 가장 오래 걸리는 작업을 낭비하는 것입니다.
output.platform을 확인합니다. 이는 음량 목표, 해상도 및 자막 안전 영역을 결정합니다.$platform이output.platform과 다르면 프로젝트를 조용히 변경하지 말고 두 번째 출력 경로를 렌더링하고 각각이 무엇인지 알려주세요.- 계획을 보고합니다: 세그먼트 수, 예상 총 프레임 수, 예상 길이, 코덱, 그리고 이번 패스에서 자막과 그래픽이 함께 인코딩(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() 실행; 문제 세그먼트 다시 렌더링 |
| 마스터가 192kHz | loudnorm 패스 2에 -ar 48000 누락 | 추가하고 패스 2 다시 실행 |
| 인코딩 프로세스 시작 실패 | 명령줄에 필터그래프가 있음 | 항상 fc.txt를 작성하고 -/filter_complex 전달 |
| 음량이 목표에서 1데시벨 벗어남 | 단일 패스 loudnorm | 2-패스 사용 |
| 내보내기가 매번 느려짐 | 변경된 인코더 설정으로 인해 캐시 무효화 | 의도된 설정 변경인지 확인 |
| 컷에서 검은 프레임 | 세그먼트가 짧게 렌더링됨 | 해당 세그먼트 다시 렌더링; QC (a) 확인 |
| 최종본에서 프리뷰보다 음성이 더 작음 | amix에 normalize=0 누락 | 오디오 그래프에서 수정하고 오디오 다시 렌더링 |