~/blog/minimax-h3-effect-embeddings-rtx5090

MiniMax-H3 on RTX 5090 · part 4

[Benchmark] MiniMax-H3 十個效果 embedding 實測:放在提示詞開頭會靜默失效

cat --toc

TL;DR

H3 的十個效果 embedding 全跑過一遍。最大的坑是位置:embedding: 放在提示詞最開頭時效果不會出現,移到句子中間才會,而且全程不警告、畫面照樣會變,所以「產物不一樣」不能當生效證據。第二件事是它們不是關鍵字,是 50 到 142 個預先編好的向量,你的提示詞寫越長就跟它們搶越兇。全部 1344×768、124 幀,生成時零成本。

十個效果各兩秒。每支都是 1344×768、124 幀,一次生成連音軌一起出來。

前言

你花錢請了一個很會拍動作戲的攝影師,結果整場戲你站在他旁邊,一格一格告訴他鏡頭要怎麼推、人要站在哪。他照樣會拍,只是拍出來的東西跟你自己拿手機拍差不多。

第一篇把 H3 在一張 5090 上跑起來,第二篇把出片時間砍掉一半,第三篇用參考圖把角色鎖回來。這篇換另一個東西:Comfy-Org 的 repo 裡放著十個效果 embedding,噴火、子彈時間、四季流轉都在裡面。

官方文件列了名字,也給了 embedding:名稱 的語法,然後就沒有了。十個我全跑過一遍;裝起來三分鐘,難的是後面兩件事:一個位置的坑,還有提示詞到底該怎麼寫。

這十個檔案是社群做的,10.7 MB,丟進資料夾重啟就好

先把東西裝上。十個 .safetensors 放在 Comfy-Org/MiniMax-H3embeddings/ 目錄下,抓下來丟進 ComfyUI/models/embeddings/,重開 ComfyUI。需要 ComfyUI 0.34.0 以上。

十個加起來 10.7 MB。這批檔案出自社群,不是 MiniMax 官方:silveroxides 開了 PR #50、Lexius merge 進 Comfy-Org 的 repo。Comfy 官方文件有列出它們、也給了語法,但沒有一個使用範例,也沒寫提示詞要怎麼配合。這篇補的就是那一塊。

官方文件說要在 CLIPTextEncode 節點引用。實測 MiniMaxH3ImageToVideoprompt 欄位一樣吃得到,所以你手上既有的 H3 workflow 不用改接線,直接把 marker 寫進提示詞就行。

marker 放在提示詞開頭,效果不會出現;移到句子中間就會

第一次掛 fire_breath 的時候,我把 marker 寫在提示詞最前面。生出來的龍很好看,沒有火。

我以為是效果不夠強,於是把提示詞改短、把龍的姿勢寫得更明確。還是沒有火。

三組對照用同一個 seed、同一個場景、14 步、1344×768,唯一的差別是 marker 放在哪裡:

提示詞開頭有沒有火
embedding:minimaxh3_fire_breath [Shot 1] A dragon…沒有
embedding:minimaxh3_fire_breath [Shot 1] A dragon…(前面補一個空白)沒有
[Shot 1] embedding:minimaxh3_fire_breath A dragon…噴火

三臂對照:同一個 seed、同一個場景,只有 embedding: 在提示詞裡的位置不同。放在最開頭與開頭補空白都沒有火,接在 [Shot 1] 後面才噴火

第二列是我當時的第一個念頭:既然叫做位置問題,那前面補一個空白應該就好。補了,還是沒有火。

所以規則是「放句子中間」,而不是「前面要有空白」。 實務上不用特別記,H3 的提示詞格式本來就以 integrated_multimodal_description: [Shot 1] 開頭,把 marker 接在 [Shot 1] 後面就對了。

我對成因的解釋,被自己的查核推翻了

原本我寫的是這樣:ComfyUI 在 comfy/sd1_clip.py:594(釘在 commit 6c62ca0,master 的行號會漂移)用 re.split(r'(?<=\s)embedding:', ...) 切提示詞,(?<=\s) 這個 lookbehind 要求前面有空白,marker 放在最前面時 split 不觸發,整串就當普通文字編碼。

那個 regex 確實長這樣,但它不足以解釋我量到的東西。往下讀第 602 行:

to_tokenize = [split[0]]
# ...
for word in to_tokenize:
    if word.startswith(self.embedding_identifier) and self.embedding_directory is not None:

split 沒切開的時候,第一段仍然會過 startswith 這一關。也就是說,光看這段程式碼,開頭的 embedding: 應該還是認得出來的。

實測結果是真的,我對它的解釋是錯的。 真正的成因在哪一層我還沒定位到 —— H3 的 embedding 檔案裡張量叫 qwen3vl_32b,走的文字編碼器跟 SD1 那條不同,差異可能在那裡,但我沒有證據,就不寫成結論。

有兩件事跟成因無關,可以直接用:

不會有任何警告。 程式碼裡的 logging.warning 是給「你指定的 embedding 檔案不存在」用的,跟這個情況不是同一件事。你的 console 從頭到尾都不會報錯。

畫面真的會變。 沒生效的那幾發跟對照組的 md5 不一樣,因為那串字面文字本身就是 token,會改變 conditioning。拿「產物有變」當生效證據,就會誤判它已經生效 —— 我就是這樣多繞了一圈。

embedding 不是關鍵字,是 50 到 142 個凍起來的向量

知道位置以後,下一個問題是提示詞要怎麼配合。這件事得先知道 embedding 到底是什麼東西。

打開任何一個檔案,裡面是一個 [N, 5120] 的張量。N 是列數,從 art_is_explosion 的 50 一路到 four_seasons 的 142。5120 則是 H3 的 conditioning 寬度,所以這些張量插得進任何吃文字 conditioning 的位置。

ComfyUI 拿到之後,會把多列 embedding 展開成每列一個 conditioning token。所以 embedding:minimaxh3_fire_breath 不是去查一張表、換出一個關鍵字,是把 118 個預先編碼好的向量接進你的提示詞。

那 118 個向量是什麼?是別人寫的一段「噴火長什麼樣」的描述,過一次文字編碼器,然後凍起來。你載入的是一整段已經寫好的文字,不是一個詞。

每個 embedding 檔是 [N, 5120] 的張量,N 從 50 到 142;ComfyUI 把每一列展開成一個 conditioning token,接在你自己的提示詞旁邊,兩邊共用同一份條件預算

這代表一件事:你的提示詞越長、寫得越具體,留給那 118 個向量的 conditioning 空間就越少。

提示詞只要做三件事:給對象、不描述效果、不取消效果

所以提示詞的寫法跟平常反過來。不是寫得越詳細越好,是留空間。三條:

  1. 給效果一個能作用的對象。 fire_breath 要一隻龍,bullet_time 要一個旋踢,four_seasons 要一棵孤樹,blooming_flowers 要一畦空花圃。沒有對象,那些向量沒地方落。
  2. 不要自己描述那個效果。 你寫「一顆巨大的橘色火球從嘴裡噴出」,等於拿自己的句子去覆蓋掉那 118 個向量。它們比你寫得好,不然你裝它幹嘛?
  3. 不要指定你希望效果改變的那個東西。 這條最容易踩:在運鏡類的 embedding 前面寫「站著不動、面對鏡頭」,等於把你要的效果直接抵銷掉。

第三條我踩過。bullet_time 的第一版我把人物寫成「站定、面向鏡頭」,因為想確保臉是清楚的。鏡頭確實繞了,但繞著一個站著不動的人繞,出來像 3D 掃描。

運鏡類三個:只改鏡頭怎麼動,主體要留路給它走

bullet_time:雨中旋踢,鏡頭環繞。背景橫掃過去,人定在畫面中央。

bullet_time 有 94 個向量。這支最能示範「留空間」是什麼意思:主體要在做一個值得凍結的動作,而且景別要夠寬,環繞才有地方走。給它一張大頭照,鏡頭沒有路可以繞。

spiral_ascent:人物升空,地平線跟著旋轉。

spiral_ascent 131 個向量。餵它一個頭上有天空的人物就夠了。

truman_show:郊區街道,一個人仰望,鏡頭往後拉開成廣角。

truman_show 90 個向量。它除了運鏡還帶一整套氛圍:修剪整齊的草坪、平淡而均勻的日光,還有那種被人看著的感覺。那 90 個向量還包含場景設定,不只有鏡頭路徑;自己再寫太多場景描述,兩邊就容易互相干擾。寫一句「郊區街道上一個人仰望」就夠了。

事件類四個:往畫面裡加一件正在發生的事

fire_breath:龍蓄力,然後噴出火球。記得取消靜音,音軌是同一次生成出來的。

fire_breath 118 個向量。這支的音量記得打開,音軌是同一次生成一起出來的,沒有經過後製。

dark_magic:石拱門下的兜帽人物,片尾雙手竄出紅色能量。

dark_magic 59 個向量。它要看得到手,兜帽把人整個包起來就沒地方發。

storm_magic:舉手,天空壓下來。

storm_magic 137 個向量,是四個事件類裡氛圍感最強的一個。它加的事件是天氣,不是物件,所以要留一大片天空給它。

art_is_explosion:靜物水果背後炸開火光。

art_is_explosion 只有 50 個向量,十個裡最小。50 個大概等於一句「這個構圖裡有爆炸」,所以它跟「桌上三顆水果」這種平凡主體也搭得起來。

時間變化類兩個:不動鏡頭、不加物件,動的是時間

這兩個是我寫這篇的原因。

four_seasons:同一棵樹,秋葉、落盡、雪地。

four_seasons 142 個向量,十個裡最大的一個。

blooming_flowers:裸土冒芽,一路開到滿園盛開。

blooming_flowers 123 個向量。

影片只有 124 幀。運鏡類要用這些幀數呈現移動,事件類要呈現一次爆發;這兩個效果要呈現的是整段變化。季節變化要交代的東西比繞一圈鏡頭多很多,所以 four_seasons 是最大的檔案,很合理。

主體選擇在這一類最關鍵:一棵樹,一片空花圃。場景越熱鬧,需要前後保持一致的東西就越多,能拿來呈現轉變的幀數也越少。

kiss_camera 把運鏡跟事件綁在一起,拆不開

kiss_camera:鏡頭從兩張臉之間推進,兩人最後靠在一起。

kiss_camera 97 個向量,橫跨兩類:運鏡與事件被綁在同一個 embedding 裡。要的是這個節拍時剛剛好,只想要那個推鏡頭的時候就不行,兩件事會一起來。

向量數就是意見大小:照這張表挑主體

十個排在一起,照向量數由小到大。這表看「餵它什麼」那一欄,那是你提示詞裡唯一需要寫清楚的東西:

embedding向量數餵它什麼類型
art_is_explosion50任何靜態主體事件
dark_magic59看得到手的人物事件
truman_show90開闊戶外的一個人運鏡+氛圍
bullet_time94動作中的身體、寬景別運鏡
kiss_camera97兩張臉運鏡+事件
fire_breath118有嘴的生物事件
blooming_flowers123裸土、空花圃時間
spiral_ascent131頭上有天空的人物運鏡
storm_magic137人物、大片天空事件+氛圍
four_seasons142一棵樹、開闊地面時間

由小到大讀下來,「餵它什麼」那一欄跟著變具體:50 個向量,隨便給個靜物就行;142 個向量,你得把主體挑對。

這些片全是原生 1344×768:低解析生完再修臉,邊界一定看得見

十支片都用同一組設定:1344×768、124 幀、24 fps,也就是 5.167 秒。兩個數字都不是隨便挑的。

解析度:H3 原生短邊是 768,而且兩邊都要是 32 的倍數。官方文件另外警告不要用 1.0 百萬像素的預設,它會產出 1376×768,超過模型的像素面積上限。

幀數:124 = 17×7+5。時長會被卡在 17k+5 這個級距上,所以 120 幀不是合法的長度。

那為什麼不用省算力的低解析生完再放大?我試過那條路,而且試得很完整。864×480 生完,接 T8 節點包的修臉鏈:偵測 124/124 幀、零退回、修完的臉五官成形,連眼鏡都成形了(480p 原片裡是融化的)。整條流程確實跑得通。

問題是貼合邊界肉眼可見,像一個橢圓形被 key 上去。掃過的參數:feather 12 / 64 / 96 / 128 來源像素、color_match 一路開到 1.0、ellipse 與 full_crop 兩種貼合區、blend 降到 0.7。全部都還看得到邊。

邊界是「裁一塊出來重畫、再貼回去」這個原理本身帶來的,不是參數沒調好。原生 768p 大約是 4 倍像素、4 倍等待,這 4 倍我認了。

這十個檔案給你的,是那段你不用自己寫的話

回到開頭那個攝影師。你請他來是因為他知道怎麼拍那場戲;你要做的不是告訴他鏡頭怎麼走,是把演員放到定位,然後閉嘴。

十個 embedding 就是十個這樣的攝影師,10.7 MB,一個檔案裡裝著 50 到 142 句你不用自己寫的話。你的提示詞只負責一件事:給它一個值得拍的東西。

進階:完整參數、零成本量測,與三條測過但沒留下的加速

不讀這節不影響使用;前面照做就能生出這十支片。這節是給想重現、或想接著往下調的人。

完整生成參數

十支片與所有對照組共用這一組:

GPU              RTX 5090 × 1
解析度            1344 x 768        (H3 原生短邊 768,兩邊都是 32 的倍數)
幀數              124 = 17×7+5      → 24 fps = 5.167 秒
步數              14
sampler          res_multistep
scheduler        simple
Spectrum solver  開啟,shift 12 / 3
權重              pruned_int8_convrot   20.97 GB
每支片耗時         206–260 秒

Spectrum solver 在 768p 下的加速幅度,比先前的 480p 基準更大。這跟一般加速技巧的特性相反:多數技巧在解析度越高時加速效果越差,Spectrum 剛好相反。

實測看不出 embedding 增加生成時間

量過:bullet_time 帶 embedding 212.0 秒,同 seed 同提示詞的對照組 206.4 秒。差距落在跑次之間的雜訊裡。

理由很直接:它們是 conditioning,不是額外的計算。

十個檔案的形狀與大小

art_is_explosion   [ 50, 5120]    512 kB
dark_magic         [ 59, 5120]    604 kB
truman_show        [ 90, 5120]    922 kB
bullet_time        [ 94, 5120]    963 kB
kiss_camera        [ 97, 5120]    993 kB
fire_breath        [118, 5120]   1.21 MB
blooming_flowers   [123, 5120]   1.26 MB
spiral_ascent      [131, 5120]   1.34 MB
storm_magic        [137, 5120]   1.40 MB
four_seasons       [142, 5120]   1.45 MB
                                --------
                                 10.7 MB

5120 是 H3 的 conditioning 寬度,所以這些張量插得進任何吃文字 conditioning 的地方。

sampler 要跟著 LoRA 家族走,混用不會報錯

res_multistep 對應 lightx2v 家族的蒸餾 LoRA,euler 對應 PDD。混用時不會報錯,但畫面品質會變差。

從別的教學抄一份 workflow、但留著它原本的 sampler,品質就是在這裡掉的。這個坑很難自己發現,因為你不會看到任何錯誤訊息,只會覺得「這個模型好像也就這樣」。

三條測過但沒留下的加速

BlockCache(T8mars/comfyui-minimax-h3-blockcache-T8)。作者自己的數字是 RTX 4060 Ti + INT8 ConvRot 上 485.8 秒降到 443.8 秒(1.09 倍),最好一次 403.2 秒(1.20 倍)。問題是它與 Spectrum solver 互斥,而 Spectrum 在 768p 下的加速效果更明顯。不採用。

步數降到 14 以下。Part 2 已經寫過:20 步降到 14 步是白拿的,再往下不是。

低解析生成再修復。完整實測寫在前面「這些片全是原生 1344×768」那節:修臉鏈跑得通、臉也修好了,但貼合邊界怎麼調都還在。

相關連結

常見問題

為什麼我加了 embedding,生出來卻沒有效果?
九成是位置放錯。實測同 seed 同場景三發,`embedding:` 放在提示詞最開頭時效果不會出現,移到句子中間就會 —— 例如接在 `[Shot 1]` 後面。在開頭補一個空白沒有用,一樣沒有效果。全程不會有任何警告,而且畫面照樣會變,所以「生出來的東西不一樣」不能當作它生效的證據。
MiniMax-H3 的效果 embedding 是官方出的嗎?
不是。十個檔案是社群貢獻,由 Lexius 與 silveroxides 上傳到 Comfy-Org 的 repo,總共 10.7 MB。Comfy 官方文件有列出它們、也給了 `embedding:名稱` 的語法,但沒有附任何使用範例,也沒有寫提示詞該怎麼配合。
用 H3 生效果影片該用什麼解析度?
1344×768,兩邊都是 32 的倍數。H3 原生短邊就是 768。低解析生完再修臉那條路我實測過:修臉鏈機制上跑得通,但貼合邊界肉眼可見,feather、color_match、blend 全掃過還是看得到邊。官方文件也警告不要用 1.0 百萬像素的預設,它會產出 1376×768,超過模型的像素面積上限。
掛上效果 embedding 會不會讓生成變慢?
不會。同 seed 同提示詞下,`bullet_time` 帶 embedding 是 212.0 秒、不帶是 206.4 秒,差距都在誤差範圍內。它們是 conditioning,不是額外的計算,十個檔案加起來也只有 10.7 MB。

接著讀

不想錯過新文章?

訂閱我確保不漏接!

隨時一鍵退訂。