Bước 15 — Concat các rendered parts thành main story video trên worker Mục tiêu: - Ghép toàn bộ các file part_XX.mp4 đã render đạt ở bước 14 thành một file main story video hoàn chỉnh. - Giữ nguyên sync audio/subtitle đã đạt ở từng part. - Tạo main video để sang bước 16 QA early/mid/late. Service dùng: - MP4 concat worker: http://192.168.1.104:8016 - Endpoint: /concat-mp4 Input: - parts/part_ranges.json - render_parts/render_validation.json - render_parts/part_01.mp4, part_02.mp4, ... đã đạt validation Cách làm: 1. Đọc danh sách part theo đúng thứ tự từ part_ranges.json. 2. Chỉ chọn các part đã render đạt validation ở bước 14. 3. Gọi worker 8016 /concat-mp4. 4. Truyền input_paths theo đúng thứ tự và output_path = output/main_story.mp4. 5. Probe file main sau concat để lấy duration, audio/video stream và codec/container. 6. So sánh duration main với tổng duration các part validated và tổng target part ranges. 7. Nếu lệch lớn, không sang bước 16. Payload chuẩn: { "input_paths": [".../render_parts/part_01.mp4", ".../render_parts/part_02.mp4"], "output_path": ".../output/main_story.mp4", "reencode": false } Output bắt buộc: - output/main_story.mp4 - output/main_story_probe.json - output/concat_report.json - logs/step15_concat_parts_manifest.json Validation bắt buộc: - file main tồn tại - duration main hợp lý so với tổng part - audio vẫn tồn tại, không bị mất tiếng - không thiếu part, không sai thứ tự part - không concat bằng file first-pass lỗi nếu project dùng compensation/trim Quy tắc quan trọng: - Không dùng local ffmpeg để ghép. - Không đảo thứ tự part. - Không dùng part chưa compensation nếu workflow smooth/crossfade yêu cầu compensation/trim. - Không coi main video là final; đây mới là main story trước intro/outro/BGM. - Phải qua bước 16 QA trước khi sang bước 17-18. Checklist: 15. Concat validated rendered parts on worker 192.168.1.104:8016/concat-mp4 into output/main_story.mp4, then probe/validate duration and part order before Step 16 QA.