Qwen3.8-27B 的视频输入怎么传:那段被整体注释掉的抽帧示例
翻 Hugging Face 上 Qwen/Qwen3.8-27B 的 model card 时,Video Input 这一小节很容易被一眼扫过去——代码块挺长,看着像是”视频输入的完整用法都在这儿了”。但把它按行拆开会发现,这个代码块里真正会执行的部分很短,而所有关于”怎么控制抽帧”的内容,是以注释形态存在的。
下面这篇就只做一件事:把这段示例的文本形态,以及它牵出的几个参数在仓库里能核到什么、核不到什么,逐条摆出来。核对日 2026-08-16,对应模型仓快照 1d4bf0f。
先定位:这段在 model card 的哪儿
README.md 全文 583 行。Quickstart 相关的小节标题行是这样排的:## Quickstart 在 README.md:225,往下依次是 ### Serving Qwen3.8(:229)、### API Usage(:243)、#### Chat Completions API(:270),再往下才是四个具体输入形态的示例:##### Text-Only Input(:282)、##### Image Input(:343)、##### Video Input(:375)、##### Instruct (or Non-Thinking) Mode(:423),最后是 ##### Disable Preserved Thinking(:469)。
从 ## Quickstart(225 行)到 ## Best Practices(496 行)之间一共 6 个代码块,1 个 shell 加 5 个 python。Video Input 的那个 python 块占 README.md:377-420。
顺带记一句 Quickstart 段首的原文(README.md:227):For streamlined integration, we recommend using Qwen3.8 via APIs. 而 ### Serving Qwen3.8 那一小节里没有任何一条服务启动命令,只有一个提示块和三条指向外部框架文档站的链接——这里只作为背景记一句位置,不展开。
会执行的那个请求,比想象中短
README.md:377-403 是会执行的那一段,原样照抄如下。下面这些代码、命令与参数一律是 model card 原文的文本,我们没有部署过任何推理框架、也没有发出过其中任何一个请求;模型仓内容随上游更新变动,看到的行号与措辞以官方最新说明为准。
from openai import OpenAI
# Configured by environment variables
client = OpenAI()
messages = [
{
"role": "user",
"content": [
{
"type": "video_url",
"video_url": {
"url": "https://qianwen-res.oss-accelerate.aliyuncs.com/Qwen3.5/demo/video/N1cdUjctpG8.mp4"
}
},
{
"type": "text",
"text": "How many porcelain jars were discovered in the niches located in the primary chamber of the tomb?"
}
]
}
]
chat_response = client.chat.completions.create(
model="Qwen/Qwen3.8-27B",
messages=messages,
)
值得注意的是这个请求没有传的东西:没有 extra_body,没有任何采样参数,没有 reasoning_effort。它就是一条 OpenAI 兼容格式的 Chat Completions 调用,content 是一个数组,里面一项 "type": "video_url" 带 video_url.url,一项 "type": "text" 带问题文本。图像那节(README.md:345-373)的结构与此对称,只是键名换成 image_url。
前置环境按 README.md:274-280 是 pip install -U openai,然后配 OPENAI_BASE_URL 与 OPENAI_API_KEY 两个环境变量,README 原文这里用的是 your-base-url / your-api-key 两个占位符。
另外一个小细节:示例视频 URL 的路径段里写的是 /Qwen3.5/demo/,而模型是 Qwen3.8-27B。同样的路径段也出现在 README.md:357 和 :440 两处图像示例里。只记录这个差异,不做延伸。
那十三行注释,是这段示例真正的信息量所在
README.md:405-417 这一整段每一行都以 # 开头,处于注释状态,原样照抄:
# When vLLM is launched with `--media-io-kwargs '{"video": {"num_frames": -1}}'`,
# video frame sampling can be configured via `extra_body` (e.g., by setting `fps`).
# This feature is currently supported only in vLLM.
#
# By default, `fps=2` and `do_sample_frames=True`.
# With `do_sample_frames=True`, you can customize the `fps` value to set your desired video sampling rate.
# chat_response = client.chat.completions.create(
# model="Qwen/Qwen3.8-27B",
# messages=messages,
# extra_body={
# "mm_processor_kwargs": {"fps": 2, "do_sample_frames": True},
# },
# )
其中 README.md:411-417 这七行是被注释掉的那次 client.chat.completions.create(...) 调用本体,README.md:416 那行 # }, 行尾在原文里还带一个空格。也就是说:model card 里唯一一次出现 mm_processor_kwargs 的地方,是一段注释掉的代码;如果直接复制这个代码块,被执行的仍然是上面那个不带 extra_body 的请求。
这不是说这段注释没用——恰恰相反,README 关于视频抽帧的全部说明都压缩在这五行文字注释里。逐条看它说了什么、没说什么。
五个参数,README 各自说到哪一步
| 参数 | 出处 | README 说明的内容 | README 未说明的内容 |
|---|---|---|---|
--media-io-kwargs '{"video": {"num_frames": -1}}' | README.md:405(注释行内) | 它是”用 extra_body 配置抽帧”这条路径的前提,即 vLLM 需以此参数启动 | num_frames 的含义、-1 代表什么、其它取值、是否有默认值 |
num_frames | README.md:405 | 仅作为 --media-io-kwargs 的 JSON 内层键出现 | 语义未单独说明;全 README 中只出现这 1 次 |
fps | README.md:406、409、410、415 | 可通过 extra_body 设置;By default, fps=2;do_sample_frames=True 时可自定义 | 取值范围、上限,以及与 num_frames 的关系 |
do_sample_frames | README.md:409、410、415 | 默认为 True;为 True 时可自定义 fps | 设为 False 时的行为 |
mm_processor_kwargs | README.md:415(注释行内) | 作为 extra_body 的键,值为 {"fps": 2, "do_sample_frames": True} | 还接受哪些字段、由哪个组件消费;全 README 只出现这 1 次 |
再加一条限定,出自 README.md:407 原文:This feature is currently supported only in vLLM. ——即”用 extra_body 配置视频抽帧”这一能力,model card 明写当前只有 vLLM 支持。
三处对不上的地方,只陈述位置
第一处:fps=2 与 do_sample_frames=True 这两个默认值,在随仓配置文件里找不到对应字段。
README.md:409 写的是 By default, fps=2anddo_sample_frames=True“。而 video_preprocessor_config.json 全文 21 行,逐个用 Python in 检查 fps、num_frames、do_sample_frames、max_pixels、min_pixels 五个关键词,结果全为 False;preprocessor_config.json 与 config.json 同样不含(config.json 里 fps 的检查结果也是 False)。README 未说明这两个默认值由哪一层提供。这一层我们没能在本仓库里核实——这是权重仓,没有源码工程可查。
第二处:带 --media-io-kwargs 的完整启动命令,README 全文里不存在。
README.md:405 以注释形式提到”当 vLLM 以 --media-io-kwargs ... 启动时”,但全文出现 vllm serve 的位置只有一处,在 ## Best Practices 第 3 条 “Processing Ultra-Long Texts” 下的 README.md:542,那条命令是讲 YaRN 长上下文的,里面并不含 --media-io-kwargs,而且命令中间还带着 README 原文自己写的 ... 省略占位。别处也没有给出完整命令。
第三处:chat 模板对 image_url 与 video_url 的判定条件不对称。
chat_template.jinja:8 的图像分支写的是 {%- if 'image' in item or 'image_url' in item or item.type == 'image' %},三个条件,其中包含 image_url;chat_template.jinja:19 的视频分支写的是 {%- elif 'video' in item or item.type == 'video' %},两个条件,不含 video_url。而 Video Input 示例传的正是 "type": "video_url" 加 "video_url": {...}(README.md:387-390)。
这两处文本的差异就是事实本身。请求在到达模板之前是否会被推理框架改写,我们无法从这个仓库里核实,所以也不推断运行时会发生什么。
顺便记下模板命中后的渲染结果:图像渲染为 '<|vision_start|><|image_pad|><|vision_end|>'(chat_template.jinja:18),视频渲染为 '<|vision_start|><|video_pad|><|vision_end|>'(:29);add_vision_id 为真时会在占位符前加 'Picture N: ' / 'Video N: ';system 消息里带图或带视频会直接抛异常,chat_template.jinja:10 是 raise_exception('System message cannot contain images.'),:21 是对应的视频版本。这几个特殊 token 在 tokenizer_config.json 的 added_tokens_decoder 里对得上:248053 <|vision_start|>、248054 <|vision_end|>、248055 <|vision_pad|>、248056 <|image_pad|>、248057 <|video_pad|>;config.json:5 的 image_token_id 是 248056,config.json:121 的 video_token_id 是 248057。
那视频预处理配置里到底有什么
既然抽帧那三个键都不在,不妨把 video_preprocessor_config.json 全部 9 个键列完(文件共 21 行):
| 字段 | 值 | 行号 |
|---|---|---|
size.longest_edge | 25165824 | :3 |
size.shortest_edge | 4096 | :4 |
patch_size | 16 | :6 |
temporal_patch_size | 2 | :7 |
merge_size | 2 | :8 |
image_mean | [0.5, 0.5, 0.5] | :9-13 |
image_std | [0.5, 0.5, 0.5] | :14-18 |
processor_class | "Qwen3VLProcessor" | :19 |
video_processor_type | "Qwen3VLVideoProcessor" | :20 |
它和图像那份 preprocessor_config.json 只有三处不同:size.longest_edge(16777216 对 25165824)、size.shortest_edge(65536 对 4096)、以及末尾的类型键(image_processor_type 对 video_processor_type)。归一化参数、patch_size=16、temporal_patch_size=2、merge_size=2、processor_class 这几项两个文件完全一致。
还有一处口径差异要记:README.md:561 原文说 the size parameter in the released video_preprocessor_config.json is conservatively configured,并建议把 longest_edge 改为 469762048(原文括注对应 224k video tokens),示例 JSON 是 {"longest_edge": 469762048, "shortest_edge": 4096};而仓库实际发布值是 25165824(video_preprocessor_config.json:3)。shortest_edge 两处一致,都是 4096。README 同时写明也可以通过引擎启动参数覆盖默认值,并给了两个外部 PR 链接(README.md:566,vLLM PR 34330 / SGLang PR 18467)——那两个链接的内容不在本仓库内,我们没有访问,所以这条做法的实现细节这里核不到。
至于 longest_edge 这个数值的单位与换算,README 只在视频那处括注了一个对应关系,没有给通用公式;preprocessor_config.json 里 16777216 / 65536 对应多少 token,仓库里没有说明,这里不做任何推算。
想动这块时,能查到哪一步
把上面的东西倒过来用,判定动作大致是这样的:
- 想确认自己传的视频结构对不对——去比对
README.md:377-403这个会执行的请求,看键名是video_url还是别的。 - 想确认抽帧参数能不能传——先看你的推理框架是不是 vLLM,因为
README.md:407明写这个能力当前只在 vLLM 支持;再看服务是不是带--media-io-kwargs起的,README 只说了这是前提,没给完整命令。 - 想确认
fps=2这个默认值从哪来——在preprocessor_config.json、video_preprocessor_config.json、config.json三个文件里搜fps,三处都搜不到,这条线在模型仓内到此为止,只能回到框架侧的文档。 - 想确认视频尺寸相关的默认值——直接看
video_preprocessor_config.json:3-4,并记住 README 建议值与发布值不是一个数。
### Serving Qwen3.8 那节把”具体怎么起服务”指向了 SGLang、vLLM、TokenSpeed 三个外部文档站(README.md:238-240)。这三个站的内容不在本文覆盖范围内,抽帧那条路径的完整参数语义,多半得回到框架自己的文档去找。
最后补一句 model card 自己的限定:README.md:16 写托管版本会带更多生产特性,原文结尾是 The service is coming soon. Stay tuned for updates.——采集时那些托管特性是”即将推出”状态,不能当成现有能力。config.json:120 里 transformers_version 的值是 5.8.0.dev0,也是个开发版版本号。这类标记照实记下来,比事后被口径差异绊一跤要省事。
延伸阅读
- 从头读起:Qwen3.8-27B 是什么:一个模型仓里有哪些文件、各自负责什么
- 本专题共 35 篇,完整分组目录见专题页
- Qwen3.8-27B 的图像输入怎么传:示例字段与预处理配置的对应
- Qwen3.8-27B 的视频 fps:README 说默认 2,配置里没有这个键
本文依据 Hugging Face 仓库 Qwen/Qwen3.8-27B 的 model card 与随仓配置文件
(config.json、generation_config.json、preprocessor_config.json、chat_template.jinja 等)整理,
核对日 2026-08-16,对应仓库快照 1d4bf0f。
本文内容为 model card 与配置文件口径,我们没有下载权重、没有部署、也没有推理过这个模型,
因此不涉及生成质量、推理速度与显存占用的任何描述;文中所有评测数字均为 model card 自述,我们没有复现。
模型仓库内容随上游更新而变动,请以官方最新说明为准。
安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。