Blog kỹ thuật

AUTO CAPCUT: biên dịch timeline thành project CapCut thật

Thay vì tự xây engine preview khớp render, mình biên dịch timeline sang project CapCut. Bài này nói về kiến trúc adapter + compiler và sync hai chiều fail-closed.

Nguyễn Hiếu··3 phút đọc
AUTO CAPCUT: biên dịch timeline thành project CapCut thật

AUTO CAPCUT là một engine độc lập, nhiều project: nhận timeline có cấu trúc cùng asset (clip, ảnh, voice, caption, logo) và sinh ra một project CapCut thật (draft_content.json) mở lên là thấy đúng như dự kiến. Bài này giải thích vì sao mình chọn hướng này và các quyết định kỹ thuật chính.

Vì sao biên dịch sang CapCut thay vì tự dựng editor

Nếu tự xây engine "preview khớp render", bạn phải duy trì sự tương đương đó mãi mãi: mỗi hiệu ứng, mỗi font, mỗi quy tắc layout đều phải khớp ở hai nơi. Đó là một khoản nợ không có ngày trả hết.

CapCut đã là một editor đầy đủ, và editor chính là renderer. Nên mình đảo bài toán: không cố khớp, mà sinh ra project của chính nó. Người dùng mở CapCut, thấy WYSIWYG, chỉnh tay nếu muốn.

Kiến trúc: adapter vào, một compiler ra

Pipeline AUTO CAPCUT: đầu vào → adapter → Timeline IR → compiler → CapCut draft; round-trip diff → verify → writeback
Pipeline AUTO CAPCUT: đầu vào → adapter → Timeline IR → compiler → CapCut draft; round-trip diff → verify → writeback

input A (AVS manifest v2) ─┐
                           ├─> Timeline IR ─> compiler ─> CapCut draft
input B (folder_voice)    ─┘
  • Adapter chuyển mỗi kiểu đầu vào về một Timeline IR chung.
  • Compiler duy nhất biến IR thành draft CapCut.

Hiện có hai adapter:

  • avs: đọc AVS manifest v2.
  • folder_voice: một thư mục media cùng một hoặc nhiều file voice, có hai chế độ mixed và story.

Thêm một nguồn đầu vào mới nghĩa là viết thêm adapter, không đụng tới compiler. Đó là lý do mình gọi nó là engine multi-project.

Bền với phiên bản CapCut

Format draft của CapCut đổi theo phiên bản. Hardcode cấu trúc sẽ gãy ở bản cập nhật kế tiếp. Cách mình chọn: clone các material template thật từ cache CapCut cục bộ rồi điền dữ liệu vào, thay vì tự dựng format từ đầu. Template do chính bản CapCut đang cài sinh ra, nên khớp với bản đó.

An toàn dữ liệu khách

Project của người dùng là thứ không được phép hỏng. Vì vậy:

  • Chỉ ghi project mới, không sửa project có sẵn.
  • Backup root_meta_info.json trước khi đụng tới.
  • Ghi atomic.
  • Từ chối đăng ký draft khi CapCut đang mở.

Thiết kế theo kiểu headless-first: phần lõi không cần GUI. Các bước tự động hóa giao diện (auto-caption, export) nằm ở một module riêng, tùy chọn.

Sync hai chiều, và fail-closed

Người dùng sẽ chỉnh tay trong CapCut. Engine cần nhận lại những chỉnh sửa đó mà không phá nguồn gốc. Luồng là:

  1. Import project đã bị sửa tay.
  2. Diff với trạng thái đã biết.
  3. Verify khớp voice với clip đạt 100%.
  4. Ghi ngược về manifest bằng patch kèm oplog, nên undo được.

Bước 3 là fail-closed: chỉ cần một cặp voice-clip lệch, lệnh trả exit code 3 và không ghi gì. Mình thà dừng lại còn hơn đẩy một timeline lệch tiếng vào pipeline.

autocapcut sync diff
autocapcut sync verify      # exit 3 nếu lệch
autocapcut sync writeback
python -m autocapcut.cli build --adapter avs ...

Chất lượng và tích hợp agent

Hiện có 105 test đang pass, chạy trên GitHub Actions CI. Ngoài CLI còn có một MCP server tùy chọn, autocapcut-mcp, để AI agent điều khiển được engine. Tương tự các tool khác của mình, agent gọi những lệnh có tên rõ ràng thay vì sửa file draft trực tiếp.

Giới hạn cần nói thẳng

  • Chỉ chạy trên Windows.
  • Cần CapCut đã cài và ffprobe có trong máy.
  • Phụ thuộc vào cache template của CapCut cục bộ; nếu cache trống thì phải mở CapCut để nó sinh template trước.

Bài học

  • Đừng xây lại thứ mà một sản phẩm trưởng thành đã làm; hãy biên dịch sang nó.
  • Tách adapter khỏi compiler để mở rộng đầu vào mà không đổi lõi.
  • Dùng template thật thay vì hardcode format để chịu được thay đổi phiên bản.
  • Với dữ liệu của khách: chỉ ghi mới, backup, ghi atomic, và verify theo kiểu fail-closed.