现场是这样的。用 openai 1.55 的 SDK 调 gpt-4o 做视频理解,自己按 1fps 抽帧后把 base64 塞进 image_url,接口返回 400 invalid_image_url,原文是 Invalid image URL or data,同一段代码换单张 jpg 能通。
中间走过弯路,把「data URL 前缀写成了 data:image/jpg 导致类型对不上」当成主因,改完现象没变。
排查方向其实有限,先把可能性排一排。抽帧后没有转成 RGB,带 alpha 通道的 png 不被接受;单帧 base64 超过 20MB 上限,视频首帧是 4K 原图;一帧里塞了多张图拼图,宽高比超出 2000 像素限制。
先把抽出的帧统一转成 RGB 的 jpeg 并压到 1280 宽
python -c "from PIL import Image;im=Image.open('f0.png').convert('RGB');im.thumbnail((1280,1280));im.save('f0.jpg',quality=85)"
然后打印每帧的字节数与实际 MIME
python -c "import os,base64;b=open('f0.jpg','rb').read();print(len(b),base64.b64encode(b)[:24])"
补一个最小请求只发两帧排除体积因素
curl https://api.openai.com/v1/chat/completions -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d @two_frames.json
等前面都确认过,再按抽帧脚本批量重跑并记录失败帧号
python frames.py --fps 1 --max-side 1280 --out frames/
别只看报错消失,验证要多做一步。两帧的最小请求返回 200 且 choices 里有描述文本,整段视频重跑不再出现 invalid_image_url,失败帧号为 0。
提醒一点。视频本身没有专门的入参,接口只认一帧一帧的图片,所以抽帧的格式、体积、宽高比三项都要自己控住,别指望服务端兜底。这类问题最好一次改到位,反复小改反而容易把原因搅混。
