【学习笔记】Antigravity 评音频的骚操作:把 MP3 包成黑屏 MP4,骗多模态模型"听"歌打分

11 min

给 AI 一堆 MP3 让它评听感,它的工具却读不了音频。于是它自己开了个后门:把音频塞进一张黑屏里、包成 MP4,再让多模态模型”看视频”——顺带把声音也听了。 技巧很妙,但留下一道更值得追问的题:它到底是真的听到了,还是看着文件名和提示词编的?

任务是什么

把 12 段 ACE-Step 1.5 生成的音频样本(播客片头 Jingle、三情绪 BGM 对照、转场 whoosh、中英文人声歌曲、4 分钟长结构等),连同一份详细的评分提示词,一起丢给 Antigravity(Google Gemini 3.1 Pro 驱动的编程助手),让它做纯听感评测——提示词遵循度、音质与无伪影、情绪匹配度、场景可用性、人声真实感等维度,1–5 分制打分。

提示词里还特意交代:只评听感,不要评判时长、码率等技术参数。换句话说,这是个考验”模型到底有没有在听”的任务。

结果就出现了开头那一幕。

核心戏码:view_file 不吃音频,那就”伪装”成视频

Antigravity 读本地文件靠一个叫 view_file 的工具。整个突破限制的过程,是在对话日志里完整上演的”试错三连”:

尝试操作结果
① 直接读 MP3view_file(07.mp3)unsupported mime type audio/mpeg
② 转成 WAV 再读ffmpeg mp3→wavview_file(07.wav)unsupported mime type audio/wave
包成黑屏 MP4ffmpeg 音频 + 纯黑画面 → MP4,再 view_file(07.mp4)✅ 成功,“听”到了

两次音频格式都被工具的 MIME 白名单挡在门外(支持 text/image/pdf/video,唯独不收 audio)。换一般人到这一步就放弃了,转去说”我无法听音频”。但 Gemini 3.1 Pro 走了第三条路——既然工具只认视频,那就把音频伪装成视频

关键命令长这样:

ffmpeg -f lavfi -i color=c=black:s=320x240 -i input.mp3 \
  -c:v libx264 -c:a aac -shortest -y out.mp4

拆开看就一句话:生成一段 320×240 的纯黑画面(color=c=black),把 MP3 当音轨塞进去(-c:a aac),用 -shortest 让视频长度跟音频对齐,输出 MP4。 画面是死的黑屏,意义全在音轨——而多模态模型”看视频”时原生会处理音轨,于是音频就这样”搭车”进了上下文。

这一步成了。Antigravity 随后用 PowerShell 一条命令批量把剩下的样本全转成 MP4,逐个 view_file “听”完,给出了一份覆盖 12 段、几十个维度的完整评测报告。

一个被它自己抓到的 bug:黑屏时长把音频截断了

批量转换那一步踩了个隐蔽的坑。最初的命令带了个 d=10(黑屏时长 10 秒):

ffmpeg -f lavfi -i color=c=black:s=320x240:d=10 -i input.mp3 ...

配上 -shortest(取最短流为准),所有超过 10 秒的样本全被截到了 10 秒。十几段的 BGM、人声歌曲原本都是 10–30 秒甚至更长,批量转完通通变 10 秒残废。

有意思的是,模型在后续的思考链里自己意识到了这个问题——原话是”my ffmpeg command was cutting the output to 10 seconds”,于是回头对两段关键长样本(15 秒的片尾 Outro、4 分钟的长结构歌曲)重新转了一次完整版(去掉 d=10,让 -shortest 以音频长度为准)。这个”犯错→自查→修正”的闭环,全程没有用户介入。

小结一下这条命令的正确形态:不要给黑屏设固定时长,让无限长的 color 源 + -shortest 自动对齐音频,就不会截断。

但最该追问的是:它真的”听到”了吗?

技巧很漂亮,可信度却要单独拎出来打问号。我把对话日志翻到底,发现几个值得警惕的信号。

信号一:评测结果”圆满”得不太真实。 12 段样本、每段 4–7 个维度,几乎清一色 5/5 满分。真实的人耳主观听感不会这么一致地给满分——尤其是”提示词遵循度”这种维度,按提示词逐项核对,居然段段满分。

信号二:具体描述和用户给的生成参数高度重合。 比如它说某段 BGM 出现了”尤克里里、拍手声和木吉他”——而这些乐器正是用户提示词里写明的生成参数。它评”中文女声自然、英文男声略带机器感”——文件名就叫 16_vocal_chinese / 17_vocal_english,外加”ACE-Step 是国产模型、中文应有优势”这个先验,闭着眼也能编出方向正确的结论。

信号三:日志里 view_file 的返回是空占位符。 每次成功读取 MP4 后,日志记录的内容只有一句 "The following is the entire, complete content of the requested file."——文本化的 transcript 看不到任何音视频数据真的进了上下文(当然,这可能是多模态 part 在文本日志里只能这么显示,不能据此断言音频没进去)。

我的判断:技术上成立,但”听感”要打折

把这几条放一起看,更合理的解释是:MP4 绕路在工程上是真的成立的——Antigravity 的 view_file 读视频时会把整个文件(含 AAC 音轨)作为 inline data 注入 Gemini 请求,而 Gemini 3.x 原生支持音频理解,所以音轨大概率确实进了多模态管道。中英文人声自然度的差异,如果完全没听到、纯靠先验去编,能编对方向但不太容易编得那么具体。

但**“音频进了上下文” ≠ “评价是基于真实听感的”。更可能的真相是:模型在多模态理解 + 先验补全**之间打了个混合——听了一部分,再用文件名、提示词里的乐器/情绪清单把空缺”圆”上,于是呈现出一篇面面俱到、却过于圆满的报告。提示词里最该被独立检验的”提示词遵循度”,反而因为模型能直接看到原始提示词,结构性地注定拿高分——它在”看着答案批卷子”。

所以这份评测当定性参考可以(模型大致能区分情绪、能识别中英文人声差异),当严格的听感 benchmark 不行——尤其”提示词遵循度”那一栏的可信度要从根本上怀疑。

这事教会我什么

1. 一个可复用的多模态”搭车”技巧。 任何”工具支持视频但不支持音频”的多模态 agent,都可以用 ffmpeg + 黑屏 让音频搭视频的便车进上下文。不只是 Antigravity,Claude Code、ZCode 这类 coding agent 遇到”读不了 mp3/wav”时,这招通用。命令记一条就够:

ffmpeg -f lavfi -i color=c=black:s=320x240 -i in.mp3 -c:v libx264 -c:a aac -shortest -y out.mp4

2. AI 给 AI 打分,天然有”看着答案批卷子”的风险。 让模型评”提示词遵循度”,却把原始提示词一并喂给它——等于把标准答案塞进考卷。要做可信的 AI 音乐评测,提示词和样本得分开发放:给评测模型听样本时,刻意隐瞒生成时用的 prompt,让它先盲听描述听到了什么,再人工对照原 prompt 打分。否则”遵循度”永远是虚高。

3. “圆满”本身就是个危险信号。 一份主观听感评测如果几乎全是满分,要么是样本真的完美,要么是评测者在用先验补全而非真实感知。面对 AI 输出的评价,过于一致的正面结论,比有褒有贬更值得怀疑

4. 会自己开后门的 agent,也得会自查。 这次最让我意外的不是绕路本身,而是它自己发现了时长截断 bug 并修正,全程没等用户提醒。这说明当前的 agent 已经能在”工具不达标→绕路→绕路出错→自查→再绕”这条链上闭环——能力在涨,但人盯着的责任没减轻,尤其当输出是一份”看起来很专业”的评测时。

附:对话日志在哪

这次 Antigravity 对话的完整记录(含 thinking、工具调用、任务日志)都在本地:

C:\Users\<用户名>\.gemini\antigravity\brain\<conversation-id>\.system_generated\
├── logs\transcript.jsonl        # 紧凑版对话记录
├── logs\transcript_full.jsonl   # 完整未截断对话
└── tasks\task-*.log             # ffmpeg 等后台任务日志

想复盘任何一次 Antigravity 协作的全过程(包括模型每一步在想什么、调了什么工具、哪里报错重试),直接翻这个目录就行——比看界面里的对话气泡全多了。