這個網站是怎麼運作的

從你按下「開始生成」到拿到影片,中間發生的每一件事,以及我們為什麼這樣設計。 這頁寫得比一般的「技術說明」細,因為裡面每一個決定都是踩過坑之後才定案的。

整條流程

  1. 照片上傳到本機伺服器,存進暫存資料夾
  2. 如果你選的是人像動作,先用 OpenCV 做一次人臉偵測
  3. 照片轉送到本機的 ComfyUI
  4. 一段文字指令 + 你的照片,交給 MiniMax H3 影像轉影片模型
  5. 模型產生 73 格畫面(3.04 秒 @ 24fps)
  6. ffmpeg 把影片接成「正放 + 倒放」的乒乓循環,並移除音軌
  7. 成品回傳給你,網頁再用 CSS 疊上相框

全部跑在同一台實體機器上。你的照片當然會經由網路傳到我們的伺服器,這是任何網頁服務都免不了的。 但它不會再被送到任何第三方 AI API,中間沒有別的服務參與,處理完就只留在我們的硬碟上,七天後刪除。

為什麼是 73 格

MiniMax H3 的畫面數必須是 17n + 5。24fps 的 3 秒是 72 格,不符合, 往上進位到最近的合法值就是 73 格,也就是 3.04 秒。乒乓之後 146 格、6.08 秒。

指令裡一個字都不提鏡頭

這是最違反直覺的一條。模型有「畫面慢慢推近」的傾向,直覺的解法是在指令裡寫 「不要 zoom」「鎖死鏡頭」「static shot」。我們實際量過背景的位移量:

指令怎麼寫背景位移量(越小越穩)
完全不提鏡頭6.6
寫 static shot20.6
寫完整的鎖鏡頭句子39.2

寫得愈用力,畫面推得愈兇。原因大概是這類詞彙在訓練資料裡總是跟運鏡描述一起出現, 提到它反而是在提醒模型「這裡有鏡頭運動這回事」。所以現在的指令完全不出現 camera、shot、zoom 這些字。

相框不讓模型畫

同樣的道理。指令裡一提到 picture frame,模型就真的在畫面裡畫一個金色相框, 而且會歪、會抖、四個角對不齊。現在相框改由網頁用 CSS 疊在影片外面, 永遠是正的,換顏色也不用重跑。

主詞必須跟照片內容一致

人像動作的指令寫的是「The person…」。如果照片裡根本沒有人,模型不會忽略這個詞, 它會生一個人出來,還會把鏡頭推近到那張憑空出現的臉上。這是我們實際遇到的狀況。

解法是把動作分成兩組:動物組整段改用 the animal,並在結尾加上 No people appear。同一張照片、同一個模型,換了主詞就正常了。 另外上傳時的人臉偵測會攔一次,避免使用者不小心選錯。

為什麼要做成乒乓循環

如果直接把 3 秒影片設成 loop,播到結尾跳回開頭時會有一個明顯的跳格, 因為最後一格跟第一格對不起來。把影片倒放接在後面,接縫兩側是同一格, 循環就完全看不出接點。代價是有方向性的動作(揮手)會有一點倒帶感。

速度:慢的其實不是運算

我們用 websocket 逐節點量過一支 3 秒影片的時間分布:

階段耗時
解讀照片內容(文字編碼器)約 17.7 秒
取樣(讓照片動起來)約 11 秒
VAE 解碼(沖洗畫面)約 11.4 秒
其餘把模型搬進顯示卡

顯示卡是 RTX 5070 Ti,只有 16GB 顯示記憶體,但這套模型光是文字編碼器加上主模型 就超過 30GB,塞不進去,每跑一次都得把權重串流進顯示卡。 所以真正的瓶頸是搬資料,不是計算。我們把文字編碼器換成更小的量化版本 (25.3GB → 14.6GB)、把取樣步數從 6 步降到 4 步(那個加速用的 LoRA 本來就是為 4 步設計的)、 再拿掉根本用不到的音訊解碼之後,單張從 60~80 秒(最糟到 137 秒)降到穩定的 42~45 秒, 畫質用同一組隨機種子比對過,看不出差別。

那還能更快嗎:十四種做法,實測之後只留下三種

上面那三個決定是當初一邊做一邊定的。2026-09-02 我們把它重新量了一次, 這次把每個旋鈕單獨拆開來測:同一張照片、同一段提示詞,每組跑三次取中位數, 並且輪流交錯跑(不是一組跑完再換下一組),因為這台機器愈跑愈熱、耗時會一路下滑, 一組只跑一次量到的數字是不能比的。

量測本身踩到的兩個坑,寫在這裡給想自己測的人:一、ComfyUI 會依節點輸入做快取, 參數與種子完全相同的工作直接回傳上次結果(實測 0.3 秒),要重測必須換種子避開。 二、文字編碼器的輸出也會被快取——只要提示詞、照片、尺寸、幀數沒變就會沿用, 所以「只改步數」的那幾組,總時間裡根本不含編碼器,跟基準線放在一起比會得到完全錯誤的結論。 下面的表因此分段列出,不看總時間。

設定取樣VAE 解碼文字編碼器
4 步(現行)18.1 秒10.5 秒(快取)
2 步17.1 秒6.8 秒(快取)
6 步24.9 秒6.8 秒(快取)
8 步33.0 秒6.7 秒(快取)
取樣器換 res_multistep16.9 秒6.7 秒(快取)
解析度 448×57611.4 秒7.4 秒9.0 秒
解析度 704×92829.7 秒16.4 秒4.1 秒
39 格(1.6 秒)15.3 秒8.8 秒3.5 秒
107 格(4.5 秒)28.6 秒15.1 秒3.6 秒
EasyCache20.3 秒11.6 秒3.5 秒
LazyCache18.9 秒9.7 秒(快取)
不掛加速 LoRA・4 步17.5 秒11.4 秒16.1 秒
不掛加速 LoRA・20 步104.0 秒10.0 秒(快取)
文字編碼器換 int8(25.3GB)20.4 秒11.6 秒30.6 秒

採用的

試過但放棄的

真正還能換到時間的只有兩個旋鈕

解析度和長度,而且它們是取樣與 VAE 解碼一起變:448×576 是取樣 11.4/VAE 7.4 秒, 704×928 是 29.7/16.4 秒;39 格是 15.3/8.8 秒,107 格是 28.6/15.1 秒。 換句話說,要再更快,只能讓畫面變小或變短——那不是優化,那是取捨。 現在的 576×768 × 73 格是我們認為還看得下去的下限。

⚠️ 畫質的部分要誠實:我們把 14 組的成品各抽一格排在一起比對過, 在測試用的那張照片上,看不出 2/4/6/8 步之間有明顯差距—— 每格的差異比較像是眨眼動作剛好停在不同階段,不是清晰度不同。 所以這一節只講「時間花在哪裡」,不宣稱哪個步數畫質比較好;那需要另一套設計過的比較方法。

排隊與取消

只有一張顯示卡,所以工作是排隊處理的。首頁會顯示目前有幾件在排, 輪到你之前進度列會顯示「前面還有幾件」。按下取消時:如果你的工作還在排隊, 就直接從佇列移除;如果正在跑,會先確認正在跑的確實是你這一件,再送出中斷指令, 不會誤殺別人的工作。

斷線不會白做

工作狀態是寫在伺服器磁碟上的,不是只存在瀏覽器裡。你關掉分頁、重新整理、 手機把瀏覽器切到背景被系統凍結,回來都會自動接回進度。 即使伺服器本身重啟,重啟後也會去問 ComfyUI 那件工作跑完了沒,接著把成品收回來。

用到的東西

親自試一次

站上其他工具

全部跑在同一台家用機器上;資料類工具用的是政府公開資料,每個都有寫清楚限制。