Trade With Viet
Session Explainer
Internal use only — enter access password
pipeline

Long-form video skill — build, refine, roadmap

2026-06-12 · explainer.tradewithviet.com

An idea-to-YouTube long-form video engine — built, refined over 4 rounds, and made self-checking.Một cỗ máy biến ý tưởng thành video YouTube dài — được xây và tinh chỉnh qua 4 vòng, và tự kiểm lỗi.

The /twv-longform skill turns a topic into a 16:9 master + 9:16 teaser + thumbnails: authentic footage, animated motion-graphics, voiceover, and a deterministic gate that proves every spoken number is on screen in sync. This explainer captures how it was built, the bugs caught along the way, and exactly what to upgrade next — Remotion, lighting, audio, information.Skill /twv-longform biến một chủ đề thành video ngang 16:9 + teaser dọc 9:16 + thumbnail: footage thật, đồ hoạ chuyển động, lời thuyết minh, và một cổng kiểm tra tự động chứng minh mọi con số được nói ra đều hiện đúng lúc trên màn hình. Bản giải thích này ghi lại cách xây dựng, các lỗi đã bắt được, và chính xác điều gì nên nâng cấp tiếp theo — Remotion, ánh sáng, âm thanh, thông tin.

StatusLive skillSkill đang chạyScopeTWV / VietConnectRounds4Output4:26 master + teaserMaster 4:26 + teaserDate2026-06-12

6-layer thinking chainChuỗi tư duy 6 tầng

L1
Raw requestYêu cầu gốc
"Make a 4-8 min video on an interesting topic — motion, not just stills, with short public-source clips; thumbnail, hook, viral; impressive transitions.""Tạo video 4-8 phút về chủ đề đáng quan tâm — chuyển động, không chỉ ảnh tĩnh, có clip ngắn từ nguồn công khai; thumbnail, hook, viral; hiệu ứng ấn tượng."
L2
Reframe — what was really neededDiễn giải lại — nhu cầu thật
The real need wasn't one video — it was a repeatable, QA-gated engine that produces a credible editorial video every time, where the visuals, the on-screen numbers, and the narration all agree.Nhu cầu thật không phải một video — mà là một cỗ máy lặp lại được, có cổng QA, tạo ra video biên tập đáng tin mỗi lần, trong đó hình ảnh, con số trên màn hình và lời thuyết minh đều khớp nhau.
L3
ConstraintsRàng buộc
Hard constraints discovered: this ffmpeg has no drawtext / subtitles / vidstab (so all text + captions are rendered HTML→PNG via Playwright, and stabilization uses deshake); Gemini TTS free quota dies fast (fallback to ElevenLabs "Brian"); authentic Vietnam factory footage barely exists on free stock; zoompan d=1 silently shortens a 25fps clip by 0.83×; and stat cards drift out of sync with the voice unless they are pinned.Các ràng buộc cứng phát hiện ra: ffmpeg này không có drawtext / subtitles / vidstab (nên mọi chữ + phụ đề được render HTML→PNG qua Playwright, ổn định hình bằng deshake); quota miễn phí Gemini TTS hết rất nhanh (chuyển sang ElevenLabs "Brian"); footage nhà máy Việt Nam thật gần như không có trên kho miễn phí; zoompan d=1 âm thầm làm clip 25fps ngắn đi 0.83 lần; và thẻ số liệu lệch khỏi giọng đọc nếu không được ghim.
L4
Options weighedCác lựa chọn cân nhắc
Four directions were weighed: (a) footage-led montage — cheap but reads generic; (b) editorial data-documentary (CNBC style) — more design work but credible; (c) AI-generated footage — risky and fake-looking for a trust topic; (d) a slideshow of stills — fast, but the user explicitly rejected stills.Bốn hướng được cân nhắc: (a) montage dẫn dắt bằng footage — rẻ nhưng nhìn chung chung; (b) phim tài liệu dữ liệu kiểu biên tập (phong cách CNBC) — nhiều việc thiết kế hơn nhưng đáng tin; (c) footage do AI tạo — rủi ro và giả với một chủ đề về niềm tin; (d) trình chiếu ảnh tĩnh — nhanh, nhưng người dùng từ chối ảnh tĩnh.
L5
Principle invokedNguyên tắc áp dụng
A deterministic gate beats eyeballing: if a number can drift from the narration, a script — not a human review — must catch it on every render.Một cổng kiểm tra tự động thắng việc nhìn bằng mắt: nếu một con số có thể lệch khỏi lời thuyết minh, thì một script — không phải mắt người — phải bắt được nó ở mỗi lần render.
L6
Pick + recognition signalLựa chọn + dấu hiệu nhận biết
Pick: editorial data-doc + authentic Vietnam establishing footage + designed motion-graphics for everything else, with sync-qa.py as a hard gate. Rejected footage-led and AI (credibility) and slideshow (the user's ask). Recognition signal: whenever content pairs spoken facts with on-screen graphics, build the timing as data (anchors) and verify it with a gate — never trust the eye.Lựa chọn: phim dữ liệu biên tập + footage Việt Nam thật dựng bối cảnh + đồ hoạ thiết kế cho phần còn lại, với sync-qa.py làm cổng bắt buộc. Loại bỏ footage-led và AI (độ tin cậy) và trình chiếu ảnh (đúng yêu cầu). Dấu hiệu nhận biết: bất cứ khi nào nội dung ghép sự kiện được nói với đồ hoạ trên màn hình, hãy xây thời gian như dữ liệu (anchor) và kiểm bằng cổng — đừng tin con mắt.

How the engine fits togetherCỗ máy ghép lại thế nào

One config file (timeline.json) drives a chain of small scripts. The voiceover timing is the master clock — every shot and every number is positioned as an offset from it, then verified.Một file cấu hình (timeline.json) điều khiển một chuỗi script nhỏ. Thời gian giọng đọc là đồng hồ chủ — mọi cảnh và mọi con số được đặt như độ lệch so với nó, rồi được kiểm chứng.

IDEAtopic + 6-beat arcMAPtimeline.json + anchorsSOURCEcurate footageBUILDcards + assembleQA GATEsync-qa.pyvoiceover timing = master clock
Technical termThuật ngữ kỹ thuậtPlain nameTên dễ hiểuRoleVai trò
narrate.pyVoiceover + timingGiọng đọc + thời gianGemini→ElevenLabs TTS; writes vo-full.mp3 and per-paragraph timing (the clock).TTS Gemini→ElevenLabs; tạo vo-full.mp3 và thời gian từng đoạn (đồng hồ).
timeline.jsonThe mapBản đồShots + overlays; every number pinned to its spoken phrase with an `at` anchor.Cảnh + overlay; mọi con số được ghim vào câu nói tương ứng bằng anchor `at`.
fetch-broll.pyFootage curatorNgười tuyển footagePexels video search + a poster contact-sheet so you pick authentic Vietnam clips.Tìm video Pexels + bảng poster để chọn clip Việt Nam thật.
card.html + render-motion.jsMotion-graphics cardsThẻ đồ hoạ độngEditorial cards (Anton type, count-ups) rendered HTML→video via Playwright.Thẻ biên tập (chữ Anton, đếm số) render HTML→video qua Playwright.
assemble.pyThe compositorBộ dựngGrade + Ken-Burns + deshake + gold logo; xfade chain locked to voice beats; ducked audio; phrase anchors.Chỉnh màu + Ken-Burns + deshake + logo vàng; chuỗi xfade khớp nhịp giọng; nhạc nền tự hạ; anchor theo câu.
sync-qa.pyThe gateCổng kiểmFAILS if any on-screen number is more than 0.6s out of sync with the voice.BÁO LỖI nếu bất kỳ con số nào lệch hơn 0.6 giây so với giọng đọc.
make-teaser.pyVertical cutdownBản cắt dọc9:16 teaser with burned captions, ending on the call-to-action.Teaser 9:16 có phụ đề, kết bằng lời kêu gọi hành động.
Read it in 30 seconds: write the map → curate authentic footage → render the cards → assemble locks every beat to its voice paragraph and anchors every number to its phrase → the gate proves the numbers are in sync → cut the teaser.
Lesson to carry forward: the voiceover timing is the single source of truth. Position shots and numbers as offsets from it, then let a script — not your eyes — verify the sync.
Đọc trong 30 giây: viết bản đồ → tuyển footage thật → render thẻ → bộ dựng khớp từng nhịp với đoạn giọng đọc và ghim mọi con số vào câu nói → cổng chứng minh số liệu đồng bộ → cắt teaser.
Bài học mang theo: thời gian giọng đọc là nguồn sự thật duy nhất. Đặt cảnh và số liệu như độ lệch so với nó, rồi để script — không phải mắt bạn — kiểm tra đồng bộ.

Four rounds of refinementBốn vòng tinh chỉnh

1
v1 — First cutv1 — Bản đầu
Generic stock footage + editorial cards. Rejected: the footage "wasn't Vietnam" and felt generic.Footage kho chung chung + thẻ biên tập. Bị từ chối: footage "không phải Việt Nam" và nhìn chung chung.
2
v2 — Editorial CNBC redesignv2 — Thiết kế lại kiểu CNBC
Authentic Vietnam footage, heavy Anton typography, kicker tabs, count-ups, and a regulation card with plain-English explanations (CBAM/EUDR/PPWR).Footage Việt Nam thật, chữ Anton đậm, nhãn kicker, đếm số, và thẻ quy định giải thích dễ hiểu (CBAM/EUDR/PPWR).
3
v3 — Full coherencev3 — Khớp toàn bộ
Every shot re-mapped to its narration line; phrase-anchored cutaways (Samsung→circuit board, CBAM→molten steel, EUDR→logging). Found and fixed a 25fps/zoompan bug that rendered the whole video half-length.Mọi cảnh được map lại đúng câu thuyết minh; cảnh chèn ghim theo câu (Samsung→bo mạch, CBAM→thép nóng chảy, EUDR→khai thác gỗ). Tìm và sửa lỗi 25fps/zoompan làm cả video ngắn còn một nửa.
4
v4 — In sync + standardizedv4 — Đồng bộ + chuẩn hoá
sync-qa.py gate (every number ≤0.5s to its word), a brighter/richer grade, gold logo top-right, deshake on aerials, and more unique footage — then packaged as the /twv-longform skill so the next video is one process.Cổng sync-qa.py (mọi số ≤0.5s so với câu nói), chỉnh màu sáng/đậm hơn, logo vàng góc phải, deshake cho cảnh flycam, và nhiều footage độc nhất hơn — rồi đóng gói thành skill /twv-longform để video sau chỉ là một quy trình.

Layered decision cardsCác quyết định theo tầng

Pin every number to its spoken phraseGhim mọi con số vào câu nói tương ứng
L1"$36 billion appears but the first appearance doesn't match the voice.""36 tỷ hiện ra nhưng lần đầu xuất hiện không khớp với giọng nói."
L2Numbers are data, not decoration — their on-screen time must equal the phrase time, not the paragraph.Số liệu là dữ liệu, không phải trang trí — thời điểm trên màn hình phải bằng thời điểm câu nói, không phải đoạn văn.
L3Even-distribution placed cards by beat; the stat cards had no anchor, so they drifted 1-2s.Phân bổ đều đặt thẻ theo nhịp; thẻ số liệu không có anchor nên lệch 1-2 giây.
L4Options: hand-time each card / proportional estimate / anchor by the phrase text itself.Lựa chọn: canh tay từng thẻ / ước lượng theo tỉ lệ / ghim theo chính chữ của câu nói.
L5The voice is the clock; timing is computed, not eyeballed.Giọng nói là đồng hồ; thời gian được tính, không nhìn bằng mắt.
L6Pick: an `at` phrase anchor + a transition-aware offset. This also exposed a bug — anchoring a beat's first shot ate the empty leading segment and silently dropped 9.5s of runtime; the fix guards that case.Lựa chọn: anchor `at` theo câu + bù trừ chuyển cảnh. Việc này lộ ra một lỗi — ghim cảnh đầu của nhịp làm mất đoạn trống đầu và âm thầm hụt 9.5 giây; bản sửa chặn trường hợp đó.
Make QA deterministic — sync-qa.py as a hard gateBiến QA thành tự động — sync-qa.py là cổng bắt buộc
L1"You have to QA very carefully... find the root cause, the pattern, then standardize it.""Phải QA thật kỹ... tìm nguyên nhân gốc, quy luật, rồi chuẩn hoá nó."
L2Reviewing by watching is unreliable and doesn't scale to future videos.Kiểm bằng cách xem thì không đáng tin và không nhân rộng cho video sau.
L4Options: manual review each render / trust the anchors blindly / a script that compares spoken vs on-screen time for every number.Lựa chọn: xem tay mỗi lần render / tin anchor mù quáng / một script so thời điểm nói vs trên màn hình cho mọi con số.
L5If it can break silently, a test must catch it.Nếu nó có thể hỏng âm thầm, một bài test phải bắt được.
L6Pick: sync-qa.py prints spoken/on-screen/Δ for every stat and FAILS over 0.6s. It's now a gate in the skill — run before every render and before publish.Lựa chọn: sync-qa.py in spoken/on-screen/Δ cho từng số và BÁO LỖI nếu quá 0.6s. Giờ là cổng trong skill — chạy trước mỗi render và trước khi đăng.
Playwright cards now, Remotion nextDùng Playwright giờ, Remotion sau
L2Cards need rich animation; the question is which renderer ships a credible video fastest without blocking future polish.Thẻ cần hoạt hoạ phong phú; câu hỏi là renderer nào ra video đáng tin nhanh nhất mà không chặn việc trau chuốt sau này.
L3Playwright recordVideo has slight timing variance; Remotion is frame-perfect but a bigger build (a React project).Playwright recordVideo lệch thời gian nhẹ; Remotion chuẩn từng khung nhưng phải dựng lớn hơn (một dự án React).
L5Ship first with what's installed; reserve the bigger lever for a focused upgrade.Ra mắt trước bằng cái đã có; để dành đòn bẩy lớn cho một lần nâng cấp tập trung.
L6Pick: Playwright + ffmpeg now. Remotion is the #1 roadmap item — see below.Lựa chọn: Playwright + ffmpeg bây giờ. Remotion là mục số 1 trong lộ trình — xem bên dưới.
fps=30 before zoompan (the half-length bug)fps=30 trước zoompan (lỗi ngắn nửa video)
L1The whole video suddenly rendered at 155s instead of 266s.Cả video đột nhiên render còn 155s thay vì 266s.
L3zoompan d=1 emits one frame per INPUT frame; a 25fps clip output at 30fps becomes 25/30 = 0.83× duration, which collapses the xfade chain.zoompan d=1 xuất một khung cho mỗi khung ĐẦU VÀO; clip 25fps xuất ở 30fps thành 25/30 = 0.83 lần thời lượng, làm sập chuỗi xfade.
L6Pick: force fps=30 before zoompan, and loop-trim b-roll to guarantee exact length. Recognition signal: any per-frame filter on mixed-fps footage needs an fps normalize first.Lựa chọn: ép fps=30 trước zoompan, và loop-trim b-roll để đảm bảo đúng độ dài. Dấu hiệu nhận biết: bất kỳ filter theo-khung nào trên footage khác fps đều cần chuẩn hoá fps trước.

What to improve next (forward QA)Nên cải thiện gì tiếp theo (QA hướng tới)

Prioritized by impact × effort. The single biggest lever is Remotion for the graphics layer; the fastest win is −14 LUFS audio.Ưu tiên theo tác động × công sức. Đòn bẩy lớn nhất là Remotion cho lớp đồ hoạ; thắng nhanh nhất là chuẩn âm −14 LUFS.

Remotion for the motion-graphics — verdict: YESRemotion cho lớp đồ hoạ — kết luận: CÓ
ImpactTác độngHighCaoEffortCông sứcHighCao
Remotion is a deterministic, frame-perfect React video framework — essentially a mature version of today's Playwright cards, plus springs/easing, @remotion/transitions, Lottie, animated charts, and word-by-word captions. Two integration paths: (a) cards-only — Remotion renders the graphics while ffmpeg keeps footage grade + the xfade chain (lower risk, big visual gain); (b) full-Remotion — the whole timeline, including footage (OffthreadVideo) and audio, composed in one project (best timing/quality, biggest refactor).Remotion là framework video React tự động, chuẩn từng khung — về cơ bản là phiên bản trưởng thành của thẻ Playwright hiện tại, cộng spring/easing, @remotion/transitions, Lottie, biểu đồ động, và phụ đề theo từng chữ. Hai cách tích hợp: (a) chỉ-thẻ — Remotion render đồ hoạ còn ffmpeg giữ chỉnh màu footage + chuỗi xfade (ít rủi ro, lợi hình lớn); (b) toàn-Remotion — cả timeline gồm footage (OffthreadVideo) và âm thanh trong một dự án (thời gian/chất lượng tốt nhất, refactor lớn nhất).
Recommended: start with (a) a cards-only proof-of-concept. Caveat: footage colour is still best graded in ffmpeg (a LUT) — Remotion can't pro-grade video. Needs `npx create-video` (not yet installed).Khuyến nghị: bắt đầu với (a) bản thử chỉ-thẻ. Lưu ý: màu footage vẫn nên chỉnh ở ffmpeg (LUT) — Remotion không grade chuyên nghiệp được. Cần `npx create-video` (chưa cài).
Lighting & colourÁnh sáng & màu
ImpactTác độngHighCaoEffortCông sứcMediumTrung bình
Replace eq+colorbalance+vignette with a film LUT (lut3d) + per-shot exposure/white-balance normalization so clips from different cameras match, plus subtle film grain, a soft highlight bloom, and light-leaks on cuts for a premium, cinematic look.Thay eq+colorbalance+vignette bằng một LUT điện ảnh (lut3d) + chuẩn hoá phơi sáng/cân bằng trắng theo từng cảnh để clip từ máy khác nhau khớp màu, thêm hạt phim nhẹ, bloom vùng sáng mềm, và light-leak khi cắt cảnh cho vẻ cao cấp, điện ảnh.
Audio masteringHoàn thiện âm thanh
ImpactTác độngMedium-HighTrung bình-CaoEffortCông sứcLowThấp
Loudness-normalize the final mix to −14 LUFS (ffmpeg loudnorm) — YouTube's reference level, instantly more 'broadcast'. Then mood-matched or AI music (MiniMax / Lyria), riser + impact SFX on the big reveals, and a light EQ + compressor on the voice bus.Chuẩn độ to bản mix cuối về −14 LUFS (ffmpeg loudnorm) — mức tham chiếu của YouTube, nghe 'phát sóng' ngay. Rồi nhạc khớp tâm trạng hoặc AI (MiniMax / Lyria), hiệu ứng riser + impact ở các điểm nhấn, và EQ + compressor nhẹ trên bus giọng nói.
Information depthChiều sâu thông tin
ImpactTác độngMediumTrung bìnhEffortCông sứcMediumTrung bình
More cited stats with on-screen source footers, a fact-density pass, and more data-viz variety (bar-races, animated map routes). Swap proportional captions for word-level sync (Groq / Whisper) so subtitles land on the exact word.Thêm số liệu có trích nguồn với chân nguồn trên màn hình, một lượt tăng mật độ dữ kiện, và nhiều kiểu data-viz hơn (đua cột, tuyến đường bản đồ động). Đổi phụ đề theo tỉ lệ sang đồng bộ theo từng chữ (Groq / Whisper) để phụ đề rơi đúng từ.
Reliability & speedĐộ ổn định & tốc độ
ImpactTác độngMediumTrung bìnhEffortCông sứcLowThấp
A one-command orchestrator (run.py: narrate → fetch → render → assemble → sync-qa → teaser) so a new video is a single command. Deshake already runs only on flagged aerial shots to keep renders fast.Một bộ điều phối một lệnh (run.py: narrate → fetch → render → assemble → sync-qa → teaser) để video mới chỉ là một lệnh. Deshake đã chỉ chạy trên cảnh flycam được đánh dấu để giữ render nhanh.

Artifact mapBản đồ tệp tạo ra

PathĐường dẫnWhatLà gìWho reads itAi dùng
~/.claude/skills/twv-longform/SKILL.mdThe standardized skill: the IDEA→MAP→SOURCE→BUILD→QA workflow + gatesSkill chuẩn hoá: quy trình IDEA→MAP→SOURCE→BUILD→QA + các cổngYou + future sessionsBạn + các phiên sau
scripts/twv-automation/longform/assemble.pyCompositor: grade, Ken-Burns, deshake, gold logo, xfade, ducked audio, phrase anchorsBộ dựng: chỉnh màu, Ken-Burns, deshake, logo vàng, xfade, nhạc tự hạ, anchor theo câuthe BUILD stepbước BUILD
scripts/twv-automation/longform/sync-qa.pyThe number↔voice gate (FAILS if any stat is >0.6s out of sync)Cổng số↔giọng (BÁO LỖI nếu số nào lệch >0.6s)QA before every renderQA trước mỗi render
scripts/twv-automation/longform/card.htmlEditorial motion-graphics templates (title, stat, cost-bars, reg-timeline…)Mẫu đồ hoạ động biên tập (tiêu đề, số liệu, cột chi phí, dòng thời gian quy định…)render-motion.jsrender-motion.js
twv-longform/china-plus-one/timeline.jsonThe map for the first video (China+1 / Vietnam)Bản đồ cho video đầu (China+1 / Việt Nam)assemble + sync-qaassemble + sync-qa
twv-longform/china-plus-one/Output/master.mp4The finished 4:26 master + a 9:16 teaser + 3 thumbnailsMaster 4:26 hoàn chỉnh + teaser 9:16 + 3 thumbnailYouTubeYouTube

Check your understandingKiểm tra hiểu biết

Why are stat cards anchored to the spoken phrase instead of spread evenly across the beat?Vì sao thẻ số liệu được ghim vào câu nói thay vì rải đều trong nhịp?
Why keep grading footage in ffmpeg even after adding Remotion?Vì sao vẫn chỉnh màu footage ở ffmpeg dù đã thêm Remotion?
In your own words: what caused the video to render at ~0.83× length, and what was the fix?Bằng lời của bạn: điều gì khiến video render còn ~0.83 lần độ dài, và cách sửa?
Mastery checklist — tick what you can explain unpromptedBảng tự đánh giá — tích những gì bạn tự giải thích được