自動駕駛 - 當使用者輸入 /short-form-video-editor 時該怎麼做
使用者上傳影片(可選擇性上傳標誌圖片)並輸入指令。不問問題,直接完成整個工作;只有在遇到真正阻礙時才停止(找不到影片、沒有 ffmpeg)。指令後面的額外文字 = 風格/品牌筆記,請套用它們。
- 尋找輸入:會話中最新上傳的影片(
ls -t /root/.claude/uploads/*/*.{mp4,mov,webm}或訊息中提供的路徑);標誌 = 如有附加的圖片(無標誌 -> 跳過浮水印/英雄畫面/片尾標誌,使用乾淨無文字的片尾)。語言 = 使用asr_chunks.py ... auto自動偵測。 - 定位工具包:此技能的資料夾(包含此 SKILL.md 的目錄)內有
template/。在一個新的專案資料夾中工作:當儲存庫已在會話中時,在 Video-editing 儲存庫克隆內建立為projects/<slug>-<YYYYMMDD>/,否則在暫存區中。cp -r template/. <project>/。 - 檢查/安裝相依套件(一次):
ffmpeg、Node + Playwright Chromium(/opt/pw-browsers,切勿執行playwright install)、pip install numpy pillow sherpa-onnx、scripts/fetch_asr_model.sh。無法連線到 huggingface;可以使用 GitHub releases、npm 和 PyPI。 - 從頭到尾執行以下工作流程,自行決定設計(從標誌中取品牌色;否則使用珊瑚/青綠科技配色;從
reference/scene-patterns.md中選擇符合實際語音的場景)。 - 交付:使用
SendUserFile傳送 mp4(顯示渲染),然後附上簡短摘要:規格、添加了哪些圖形、需要手動驗證的低信賴度轉錄片段、影片解析度說明、「音訊未經聽覺審聽」。將專案(不含work/)和最終的 mp4 儲存到儲存庫中,並推送到會話指定的分支(如果未指定則推送到main)。除非被要求,否則不要建立 PR。 - 60 秒的影片預計需要 15-25 分鐘(轉錄約 3 分鐘,渲染約 4 分鐘,編碼約 2 分鐘)。開始時用一行告知使用者,然後安靜工作直到完成。
配音模式 - 翻譯 + 新語音 + 唇形同步(在 Glow 片段上測試過一次:阿拉伯語 -> 英語)
當使用者想要另一種語言的影片「且嘴唇要跟著文字動」時使用。
- 腳本:如同編輯模式般進行轉錄 + 驗證,然後自己撰寫翻譯為
data/phrases.<lang>.json=[[win_start, win_end, "text with *key words and DISPLAY|spoken overrides (NBSP inside multi-word tokens)"], ...]。保留原始的短語視窗,以便攝影機/圖形節拍能夠存活;可以合併相鄰的視窗。每個視窗預算約 2.5-3 字/秒(英語)——壓縮而非倉促;保留原意,不要有新的主張。口語覆蓋範例:*COSRX|Cosrex、Axis-Y|Axis\u00a0Y。 - 模型:
scripts/fetch_dub_models.sh(加上用於驗證的fetch_asr_model.sh)。 - 語音(預設 = 複製成說話者):建立
work/ref.wav= 4-5 個乾淨的、以停頓分隔的片段(約 15 秒)來自說話者的原始語音(16k 單聲道,串接)。python3 -I scripts/tts_clone.py data/phrases.en.json work/ref.wav 8 <total_seconds>->work/voice_en.wav+data/transcript.source.json,包含實際的語音跨度。YourTTS(coqui,fetch_dub_models.sh會下載它)以零樣本方式複製音色;腳本會為每一行產生 N 個錄音,保留 Whisper 回讀與腳本最匹配的錄音,然後進行時間拉伸(0.72-1.25 倍,保留音高)以填充原始視窗的約 90%。在 Glow 片段上驗證的數據:中位音高 144 Hz vs 說話者 154 Hz(原本的 Kokoro 語音 123 Hz),長頻譜相似度 0.96 vs 0.90,每一行都能正確回讀。透過DISPLAY|spoken以語音拼寫品牌名稱(並將其排除在評分之外 - 自動)。備用方案tts_phrases.py= 原本的 Kokoro 語音(清晰但非說話者)。腔調:模型會轉移音色/音高,而非原本的口音 - 不要承諾埃及腔英語;說明實際達成的效果。 - 在原始解析度的影格上進行唇形同步:
ffmpeg -t <end> -i src -vf fps=30 work/raw/%05d.png;ffmpeg -i work/voice_en.wav -ac 1 -ar 16000 work/en16k.wav;MODELS=work/models python3 -I scripts/lipsync2.py work/raw work/en16k.wav work/ls --model wav2lip_gan_96.onnx --enhance 0.7(先用--range a b測試;完整運行在 4 個 CPU 上約需 25 分鐘處理 1700 個影格:Haar 邊界框、每個影格上的 2dfan4 地標,然後是每個影格的 Wav2Lip + GFPGAN)。lipsync2 = 地標對齊的 FFHQ-512 裁剪、平滑地標、在地標臉部框上使用 Wav2Lip、混合 0.7 的 GFPGAN 修復、嘴型遮罩(絕不觸及鼻子)、貼回。然後執行scripts/01b_upscale_lipsynced.sh。不要使用舊的lipsync.py(粗糙的 Haar 裁剪:模糊的嘴唇、舌頭狀偽影 - 使用者稱其為「非常糟糕」)。EDTalk-256 已經嘗試過,效果更差(鬼影嘴巴)。模型:來自 facefusion-assets GitHub release 的 2dfan4、gfpgan_1.4、wav2lip_gan_96。 - 視覺同步證明:嘴巴裁剪的聯繫表,每個圖塊下方有音訊包絡 - 嘴巴在靜音間隙中必須閉合,並在條形圖升起時張開/變化。像素相關性指標在這裡雜訊太大;不要依賴它們。
- 圖形:
python3 -I scripts/build_transcript.py work/en16k.wav(在來源 json 中設定max_chars約 22 以適用英語),重新產生composition/transcript.js,然後改寫scene.js副本和新語言的觸發詞(LTR:.row/.chunk方向 ltr,使用 Inter 字體,打擊起點靠左,流程箭頭向右)。多詞組 token 在轉錄中是單獨的詞:查詢單字(ts('skin',0,43.5)),絕不要用ts('your skin')。 - 像往常一樣渲染(
LAST_SRC_FRAME=<n> scripts/02_render_all.sh、提示、音效)並與VOICE=work/voice_en.wav OUT=out/name-en.mp4 scripts/03_mix_and_encode.sh混合。 - 在摘要中誠實說明:Wav2Lip 在大約 100px 的臉部解析度下會產生柔軟、略微平滑的嘴巴(仔細看可見),頭部/手部動作仍是原始說話者的,語音是合成的,說話者應核准其肖像的配音版本,考慮標註其為 AI 配音。說出任何來源為低信賴度的翻譯短語。
短影音編輯器(字幕 + 動態圖形 + 音效)
兩種模式:編輯(保留語言,添加字幕/圖形/音效)和配音(翻譯成另一種語言、新語音、根據新音訊重新製作嘴唇動畫 - 當使用者說英語/翻譯/配音/唇形同步時觸發)。管線已在一個 57 秒的埃及阿拉伯語藥妝廣告(Glow Cosmetics)上驗證。輸出:1080x1920 @30、H.264/AAC。-14 LUFS。
工作範例專案:projects/glow-kbeauty-reel/ 在 https://github.com/MuhammadToffaha/Video-editing
定義「專業,非樣板」的規則
- 保持說話者、語音和意圖不受影響。不要捏造主張(數字、「100%」、價格)。如果圖形需要未經口頭說出的文字,請保持通用(類別名稱、標題)。
- 每個視覺效果都支援一個口語短語,並在該詞上觸發(
ts('word')),而非在短語開始時觸發。卡片在下一個進入之前退出;沒有重疊的鬼影。 - 統一的視覺語言:品牌色(從標誌取色) + 白色 + 深色墨水玻璃面板,拉丁標籤使用 Inter,Cairo(阿拉伯語)用於標題/字幕。薄荷色僅用於成功狀態。
- 佈局區域(1080x1920,說話者的臉大約在 y 790-1110):卡片在 y 235-735(絕不遮蓋臉部,即使在 1.15 倍縮放後),字幕在 y~1545,底部 220 像素和頂部 130 像素保留給平台 UI,不放主要內容。為每個來源重新檢查臉部位置。
- 留存裝置,適度使用:句子開始時推近快照(1.12-1.15 倍),輔以緩慢漂移,每 2-4 秒一個圖形,醒目詞字幕高亮,刪除線/勾選/計數微型動畫,當品牌被提及時的品牌英雄時刻,品牌結尾卡片。
- 音效:卡片進入時有咻聲,元素上有啪/滴答聲,成功時有鈴聲,標誌有砰聲。音量小(約低於語音 -10 dB)。除非使用者提供,否則不要有音樂。
工作流程
- 檢查:
ffprobe、聯繫表(ffmpeg -vf "fps=1/6,scale=239:-1,tile=5x2"),找出尾端結束卡片(WhatsApp/CapCut 黑色影格)並記錄說話者位置。來源通常是低解析度(手機/WhatsApp):使用 lanczos 升頻,告知使用者影片會顯得柔和,但圖形會保持清晰。 - 專案:
cp -r <skill>/template/. my-project/ && cd my-project;cp <logo> assets/;python3 -I scripts/extract_logo.py assets/logo_original.png assets/logo_white.png(印出品牌十六進位色碼)。更新composition/style.css和#wm/#outro中的--coral/--brand。 - 準備:
END=<trim seconds> scripts/01_prepare.sh input.mp4(影格、16k 波形、語音)。 - 轉錄(沙箱中無法存取 HF;GitHub releases 可以):
scripts/fetch_asr_model.sh;然後python3 -I scripts/asr_chunks.py work/asr16k.wav <lang|auto> 3.2 a,用 2.4 和 4.5 重複。Whisper 會截斷區塊尾部;自行合併 3 個假設並使用你自己的語言知識進行修正。- 不確定的詞語/品牌名稱:
python3 -I scripts/asr_probe.py work/asr16k.wav ar,en 14.0-16.8 14.5-16.6 ...(en通道會拼寫拉丁品牌名稱)。只相信在重疊視窗中一致的結果;將其餘的列為最終訊息和 README 中的低信賴度。不要在猜測的名稱上建立圖形。
- 計時:
python3 -I scripts/pauses.py work/asr16k.wav-> 停頓是可靠的短語邊界。將data/transcript.source.json寫為[start, end, "text"]短語(參見data/transcript.source.example.json;*word= 重音藥丸;在多詞的拉丁名稱內使用 NBSP;RTL 文字中的拉丁品牌:避免將阿拉伯語的و前綴黏附在它們上,寫成و Brand)。然後執行python3 -I scripts/build_transcript.py work/asr16k.wav和echo "window.TRANSCRIPT=$(cat data/transcript.json);" > composition/transcript.js。它會根據音節權重將單詞時間分佈到每個短語內,並對齊到能量谷點,然後形成平衡的 2-4 字字幕區塊。合理性檢查:沒有單詞起始於靜音內。 - 在
composition/scene.js中設計場景(參見reference/scene-patterns.md)。使用card(t0,t1,{y,h,html})、pop、fade、draw、cue、ts。將範例場景作為模式:鉤子卡片、品牌晶片(骨幹插槽,在每個名稱被說出時填充)、類別磁磚、帶有移動點和勾選的 A->B 匹配圖、刪除線晶片、流程節點、星級評分、清單列、路線圖、長條圖、信任環圈、品牌英雄揭露、品牌片尾。設定finish(<seconds>)= 語音結束 + 約 1.7 秒片尾。 - 渲染 + 品質檢查:首先渲染幾個測試影格(
node scripts/render.mjs <f> <f+1> work/test),使用 Pillow 建立聯繫表,仔細觀察它們。然後執行scripts/02_render_all.sh(4 個工作線程,總計約 8 fps)、node scripts/render.mjs cues work/cues.json && python3 -I scripts/sfx.py work/cues.json work/sfx.wav、OUT=out/name.mp4 scripts/03_mix_and_encode.sh。如果來源以結束卡片結尾,請傳遞LAST_SRC_FRAME=<n>以凍結最後一個乾淨的影格。 - 交付:傳送 mp4(SendUserFile),說明規格、低信賴度的轉錄位置、影片解析度限制,以及音訊未經耳聽審聽(你無法聽到) - 僅使用響度計和起始點 vs 能量測試進行檢查。
已解決的陷阱(無需重學)
- Python 的
str.split()會在 NBSP 上分割 - 改用split(' ')(已在 build_transcript.py 中)。 - 在無頭 Chromium 中,使用 CSS
scaleY對 SVG<rect>進行動畫化會導致翻轉/偏移 - 改為對attr:{y,height}進行補間。筆劃繪製:draw(path,t,d)。 - 起始隱藏的元素需要 CSS
opacity:0(類別hid)和帶有immediateRender:false的補間;每個補間都必須是可尋址的(工作線程直接跳到它們的起始影格)。 - 只有在影片影格位於同一頁面(
#bg圖片)時,帶有backdrop-filter的卡片才能產生模糊效果 - 這就是為什麼影格是在頁面內合成的。 - 空的模糊卡片看起來有缺陷:要么在其觸發詞上啟動卡片,要么顯示變暗的佔位列/插槽,在口語提及時亮起。
- 阿拉伯語需要真實的字形塑造:Chromium + Cairo woff2(按 unicode-range 分割阿拉伯/拉丁)有效;Pillow/ffmpeg drawtext 則不行。
- Whisper(sherpa-onnx 版本)沒有單詞時間戳記且會截斷尾部;因此採用短視窗 + 停頓錨定。
- opencv 5.x 沒有
CascadeClassifier(請鎖定 4.10.0.84);Haar 臉部框會對手/襯衫產生誤報,並錯過約 30% 的影格 -> 使用中位數框異常值剔除 + ROI 第二輪 + 插值(已在 lipsync.py 中)。 - Kokoro/Whisper 風格的 TTS 會將
COSRX讀成字母:請使用DISPLAY|spoken覆蓋。 - GitHub MCP 的
create_repository可能回傳 403 - 請要求使用者建立儲存庫,然後使用add_repo+ 克隆(如果路徑已存在,請克隆到新目錄)。