接生成式影片 API 的十個坑(fal.ai 實戰)
每一條都是真的花錢踩過才知道的,不是讀文件想到的。 專案無關 —— 換一家 vendor 大部分還是成立。 情境是一條 AI 短片產線:選題 → 生 clip → 配音效 → 剪成片,跑在 fal.ai 上。
0. 先講最貴的教訓
文件沒寫的事,它照樣會發生;文件寫了的事,你送的欄位名可能根本不對。
這兩句話底下是 2026-08~09 一支片燒掉的學費。下面十條,前四條會直接花錢。
1. 💰 計費單位不是你以為的那個
fal 在 response header 回 x-fal-billable-units。它跟「秒數」不是同一個東西。
| 模型 | 要求 | 實際計費 | 比例 |
|---|---|---|---|
| Wan 3.0 Prime i2v | 5s | 14 單位 | 2.8 |
| MiniMax H3 | 5s(實際 5.184s) | 6 單位 | 1.2(= ceil 秒數) |
| MMAudio V2 | 5s | 5 單位 | 1.0 |
Wan 那條:估 $0.84、實收 $1.96。如果你的預算 gate 是拿「秒數 × 牌價」算的, 它會放行本該擋下的請求 —— 而且是每一次都低估,不是偶爾。
做法:把 header 記進帳本,寫一支工具從帳本反推每個模型的比例, 存進模型設定,估價時乘上去。沒對過帳的模型要明說「這個數字可能低估」。
2. 💰 已承諾 ≠ 已花費
送出時記「估價」是對的(防併發把預算灌爆),但完成後要用實收覆蓋它。
我們的帳本一開始只數 submitted 的估價,completed 的實收從來沒進過帳:
當天 gate 以為花了 $1.68,實際 $3.92 —— 低估 2.33 倍。
一個 request 一筆帳:submitted 掛估價 → completed 用實收蓋掉 → reversed 整筆丟掉。 ⚠️ 逾時不算失敗:job 還在 vendor 那邊跑、照樣扣款,估價要留著。
3. 💰 預設值會咬人
MiniMax H3 的 resolution 預設是 2K($0.13/s),而 768P 是 $0.06/s。
不明送 = 你照 768P 估價、按 2K 付錢。Wan 的 resolution 預設 1080p 也一樣。
凡是影響計價的欄位一律明送,不要讓它吃預設。
4. 💰 配音效會把影像重新編碼
MMAudio 吐回來的是「同一支影片 + 音軌」。同解析度同 fps,但 bitrate 從 14.9 Mbps 掉到 2.2 Mbps(9.3MB → 1.4MB)。檔案照樣能播, 所以沒有人會發現 —— 每配一次音效就悄悄掉一代畫質。
做法:只拿它的音軌(stream copy),影像用原檔。零重編碼。
5. 🔴 schema 沒有那個欄位 ≠ 不會有那個輸出
MiniMax H3 的 OpenAPI schema 沒有 generate_audio,所以我斷定它不產音訊。
第一支真跑:有音軌,峰值 -2.97 dBFS。它預設就配聲音,而且沒有參數關得掉。
schema 描述的是你能控制什麼,不是它會做什麼。 → 產出一定要量(有沒有音軌、幾秒、多大、什麼解析度),不要憑 schema 推斷。
6. 🔴 不認得的欄位會被靜默忽略
送錯名字不會報錯。所以:
| 語意 | Kling | Wan | MiniMax H3 |
|---|---|---|---|
| 音訊輸出 | generate_audio |
audio(而且 default=true) |
(沒有) |
| 首幀 | — | start_image_url |
image_url |
| 來源圖 | image_url |
— | reference_image_urls(array) |
Wan 那個 audio default=true 特別陰:「不送」不等於「關」。
→ 欄位名由每個模型自己宣告,不要跨模型共用一組。 → 模型不吃某個輸入時要當場擋,不能塞進 payload 讓 vendor 忽略 —— 「你以為接上了、實際上沒有,而錢已經花了」。
7. 🔴 dry-run 印的 body 必須等於 live 送的 body
我們的 dry-run 少了三個參數(negative_prompt / start_image_url / end_image_url),
所以它印的 body 跟真的要送的不一樣。dry-run 的唯一用途就是花錢前核對 ——
差一個欄位就是核對了個寂寞。
更糟的是它製造假證據:曾經有人根據 dry-run 的 body 回報「negative_prompt 被靜默丟掉」,那次結論碰巧對,但推論的依據是錯的。
→ 用反射比對兩邊的簽名,加新參數忘了穿過去就紅。
8. 查參數不用花錢也不用讀行銷頁
fal 有公開的 OpenAPI schema:
curl -s "https://fal.ai/api/openapi/queue/openapi.json?endpoint_id=<ENDPOINT_ID>" \
| python3 -c "import json,sys;[print(k,':',v.get('type'),'—',str(v.get('description',''))[:90]) \
for n,sc in json.load(sys.stdin)['components']['schemas'].items() if 'Input' in n \
for k,v in (sc.get('properties') or {}).items()]"
加任何模型進產線前先打這個。 比讀模型頁的行銷文字準,而且零成本。
⚠️ endpoint id 的前綴會變:alibaba/wan-3.0-prime/… 是 200、fal-ai/wan-3.0-prime/… 是 404。
(價錢 schema 裡沒有,還是要看模型頁。)
9. 🎬 「參考圖」與「首尾幀」是兩種機制,別混
| 參考圖 reference-to-video | 首尾幀 image-to-video | |
|---|---|---|
| 那張圖是什麼 | 角色 / 風格參考,模型自己畫第一幀 | 就是第 0 格畫面 |
| 拿去中性背景的定裝照餵它 | 首幀乾淨,角色照樣鎖住 | 背景原封不動進成品 |
| 張數 | 多張(H3 最多 9,前 5 張免費) | 1(+ 尾幀 1) |
| 解的是 | 跨鏡角色一致 | 構圖 / 接點精準 |
我們踩的:拿綠幕定裝照當 start_image → 成品前 1 秒是「綠幕變形成賣場」的過渡。
換成參考圖之後首幀就乾淨了。
兩條通常是同一家的不同 endpoint、同價 —— 不是誰取代誰,是用在不同鏡頭。
10. 🎬 模型不聽話之前,先確認話有送出去
我們的分鏡每一拍都有「機位」欄,作者也認真寫了 (「貼著輸送帶的低角度特寫,淺景深」)。但那一欄只存進資料庫,從來沒進過 prompt —— 於是每一段都生出同一種中景。
看起來像模型不聽話。實際上是話沒送出去。
補上之後,同一個模型立刻給出低角度、淺景深、主體在背景失焦的鏡頭。
同一類:prompt 模板的作用域。我們的「視覺不變量」
(dancing, bright saturated colors, clean solid-color background)寫給某一個頻道,
卻被無條件套用在所有產線上 —— 情境劇因此一直被要求純色背景。
換再多模型也沒用,因為 prompt 自己在要那個東西。
一句話總結
| 症狀 | 先查 |
|---|---|
| 比預期貴 | 計費單位(1)、實收沒回填(2)、預設解析度(3) |
| 畫質變差 | 有沒有被重新編碼(4) |
| 出現沒要的東西 | schema 管不到的預設行為(5) |
| 參數好像沒作用 | 欄位名對不對(6)、dry-run 是不是漏印(7) |
| 模型「不聽話」 | 話有沒有真的送出去(10) |
| 首幀怪 | 用錯機制(9) |