news 2026/9/10 21:50:31

基于 Agno 的视频分类实战:用 Gemini 原生视频输入与结构化输出完成视频打标

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于 Agno 的视频分类实战:用 Gemini 原生视频输入与结构化输出完成视频打标

基于 Agno 的视频分类实战:用 Gemini 原生视频输入与结构化输出完成视频打标

【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno

导读

视频分类(Video Classification)是数据标注流水线中的一项基础原语:给整段视频片段(clip)打一个标签,模型看完整段视频后输出一个全局结论,相当于把图像分类的时间维折叠进来。本文基于 agno 仓库cookbook/data_labeling/_13_video_classification/目录中的完整示例,讲解如何用 Agno Agent + Google Gemini 实现视频的原生输入、闭集标签分类与置信度输出,并深入源码说明Video媒体对象与 Gemini 视频接入的底层原理。读完本文,你将能独立搭建一个可运行、可扩展的视频内容分类 Agent。

理解视频分类这一标注原语

视频分类要解决的核心问题,是为一段视频输出一个片段级别的标签(clip-level label)。这与图像分类是同一个原始任务,区别在于模型需要"看完"整个片段——包括连续帧、镜头切换与时间维度上的内容演变——再给出一个覆盖整段视频的单一结论。

从 cookbook/data_labeling/_13_video_classification/README.md 的说明看,这一原语适用于以下典型场景:

  • 内容审核(Content moderation):对用户上传的短视频片段进行门禁式过滤,先判定类别再决定是否放行;
  • 素材预打标(Pre-tagging):按场景类型预先为素材库中的视频添加标签,便于后续检索与推荐;
  • 安防分流(Routing):根据事件类别对摄像头片段进行路由归类。

如果业务需要的是带时间戳的类型化事件/场景提取(例如"第 3 秒到第 8 秒出现人物动作"),则应转向 cookbook/data_labeling/_14_video_extraction/README.md(视频提取),两者是互补关系:分类回答"这段视频是什么",提取回答"这段视频里发生了什么、发生在什么时候"。

运行环境与启动命令

两个示例脚本都依赖 Gemini 模型对视频的原生理解能力,因此需要准备:

  • 环境变量GOOGLE_API_KEY(Gemini API 密钥);
  • 安装 agno 及依赖(脚本中用到agnohttpxpydanticrich等库);
  • 示例视频通过公网 URL 实时下载,无需本地准备素材。

在仓库根目录下直接运行:

python cookbook/data_labeling/_13_video_classification/basic.py python cookbook/data_labeling/_13_video_classification/with_confidence.py

运行时脚本会从https://agno-public.s3.amazonaws.com/demo/sample_seaview.mp4拉取视频字节,交给 Agent 分类,并通过rich.pretty.pprint打印 URL 与结构化分类结果。

⚠️ 示例素材命名提示:README 特别说明sample_seaview.mp4是个命名误导——这段视频实际是一段短小的实验室场景(科学家通过显微镜观察样本),并非海景。因此期望的输出标签更可能是indoorpeople,而不是nature。这一点在调试结果时非常重要,避免因"期望值与实际不符"而误判模型能力。

示例一:单标签分类(basic.py)

basic.py 演示了最基础、最通用的视频分类流程,全流程仅分三步:定义输出 Schema → 创建 Agent → 传入视频运行。

第一步:用 Pydantic 定义闭集标签 Schema

from typing import Literal from agno.agent import Agent, RunOutput from agno.media import Video from pydantic import BaseModel, Field from rich.pretty import pprint class Classification(BaseModel): scene_type: Literal[ "nature", "urban", "indoor", "people", "vehicle", "animal", "other", ] = Field(..., description="Dominant scene type in the clip")

关键设计点:

  • 闭集标签Literal[...]把输出约束在 7 个候选值内(nature/urban/indoor/people/vehicle/animal/other),这正是"分类"与"提取"的本质区别——模型只能从预定义的封闭集合中挑选一个;
  • Field(..., description=...):字段描述会随 Schema 一起注入提示词,引导模型理解该字段语义("片段中的主导场景类型");
  • output_schema:Agno Agent 的output_schema参数接受任意 PydanticBaseModel,运行时会强制模型按该结构返回结构化输出。

第二步:创建 Agent

agent = Agent( model="google:gemini-3.5-flash", instructions="You classify short video clips by dominant scene type.", output_schema=Classification, )

三个参数各司其职:model指定 Google Gemini 系列模型(该 cookbook 的配套示例均使用google:gemini-3.5-flash,支持原生视频输入);instructions给出简短任务说明;output_schema绑定上述结构化输出模型。

第三步:下载视频并运行

if __name__ == "__main__": url = "https://agno-public.s3.amazonaws.com/demo/sample_seaview.mp4" video_bytes = httpx.get(url).content run: RunOutput = agent.run( "Classify this clip.", videos=[Video(content=video_bytes, format="mp4")], ) pprint({"url": url, "result": run.content})

这里展示了 Agno 媒体输入的标准姿势:

  1. httpx下载视频字节流;
  2. 构造Video(content=video_bytes, format="mp4")媒体对象;
  3. 通过agent.run(prompt, videos=[...])将视频与文本提示一起送入模型;
  4. RunOutput.content取出结构化分类结果(即Classification实例)。

示例二:带置信度的分类(with_confidence.py)

with_confidence.py 在单标签基础上增加了一个置信度维度,其工程动机在文件开头注释中写得很清楚:让下游消费者可以把低置信度片段转交人工审核或更强的模型处理。

扩展 Schema:增加 confidence 字段

class Classification(BaseModel): scene_type: Literal[ "nature", "urban", "indoor", "people", "vehicle", "animal", "other", ] = Field(..., description="Dominant scene type in the clip") confidence: Literal["high", "medium", "low"] = Field( ..., description="Confidence in the label" )

confidence同样使用Literal["high", "medium", "low"]约束为三档离散值,便于下游做确定性路由(而非解析自由文本)。

用指令约束置信度语义

比基础版更精细的是 instructions 的写法,它把三档置信度的判定标准写得非常具体:

instructions = """\ Classify the clip and report a confidence: - high - the dominant scene is unambiguous across the clip - medium - the dominant scene is identifiable but some shots break the pattern - low - the clip mixes several scene types and you had to pick """

这四条规则实际上定义了一个可操作的置信度判定协议:

  • high:主导场景在整段视频中无歧义;
  • medium:主导场景可识别,但部分镜头不符合该模式;
  • low:视频混合了多种场景类型,模型不得不"硬选"一个。

这种"把评估标准写进 instructions"的做法,比让模型自行发挥可靠得多,也是本示例值得借鉴的实战模式。

运行

run: RunOutput = agent.run( "Classify this clip with confidence.", videos=[Video(content=video_bytes, format="mp4")], )

仅提示词略有不同("Classify this clip with confidence."),其余流程与 basic 版完全一致。

源码纵览:Video 媒体对象的字段与校验

理解Video对象是掌握 Agno 多媒体输入的关键。其实现位于 libs/agno/agno/media/media.py,核心设计如下:

三种内容来源(且三选一)

字段类型说明
urlstr \| None视频的远程 URL
filepathPath \| str \| None本地视频文件路径
contentbytes \| None原始视频字节(统一规范化为 bytes)

validate_and_normalize_content校验器强制"恰好提供一个内容来源":全部为空或同时提供多个都会抛出ValueError。同时自动为对象生成id(uuid4)。

媒体元数据format(如mp4/mov/avi/webm)、mime_type(如video/mp4)、duration(秒)、width/height(像素)、fps等字段用于描述视频本身。

内容读取get_content_bytes()content → url → media_reference → filepath的优先级返回字节;若携带了media_reference(媒体被卸载到对象存储时的引用),则通过传入的MediaStorage句柄解析真实字节。此外还提供get_url(),用于生成模型或浏览器可直接拉取的 URL。

源码纵览:Agent.run 如何接收视频

视频输入是Agent.run的一等参数。在 libs/agno/agno/agent/agent.py 中,run()的签名同时接收audioimagesvideosfiles四类媒体序列,videos的类型为Optional[Sequence[Video]],随后统一派发到_run.run_dispatch(...)执行。

在 Gemini 模型一侧(libs/agno/agno/models/google/gemini.py),消息中的videos会被逐个格式化后插入消息体:

  • 若视频已上传为 Gemini File 对象(contentGeminiFile),则使用Part.from_uri(uri, mime_type)引用远端文件;
  • 否则调用_format_video_for_message:字节内容用Part.from_bytes(mime_type="video/mp4", data=...)直接内联;本地文件路径则先上传到 Gemini API 再引用。
  • 值得注意的细节:Google 官方建议单视频场景下把文本提示放在视频之后,因此代码将视频 part 插入到消息 parts 的头部位置(message_parts.insert(0, video_file))。

从这条调用链可以看出,Agno 对"远程 URL、本地文件、字节流"三种视频来源做了统一抽象,上层业务代码只需构造Video对象,底层自动完成上传与格式化。

与视频提取(_14_video_extraction)的边界划分

为方便决策,将两个相邻目录的能力边界对比如下:

维度_13_video_classification(本文)_14_video_extraction
输出粒度片段级单一标签(闭集)类型化对象:事件、场景描述、带时间戳的动作
典型 Schemascene_type: Literal[...]场景列表 /(action, start, end)结构化记录
典型场景审核门禁、素材打标、安防路由视频归档索引、长视频章节生成、(video, labels)训练集构建
是否需要时间信息不需要需要(action_timestamps.py输出秒级起止时间)

规则可以概括为一句话:只需要"这段视频是什么"就选分类;需要"里面发生了什么、何时发生"就选提取

工程实践要点

结合示例与源码,总结几条可直接复用的实践建议:

  1. Literal强制闭集:分类任务的标签必须是有限集合,Literal让非法输出在 Schema 层面就无法产生,配合output_schema做到"结构即约束";
  2. 把置信度判定标准写进 instructions:三档置信度的判定规则越明确,模型输出越稳定,下游路由(人工审核 / 升级模型)就越可靠;
  3. 利用Field(description=...)传递字段语义:描述文本会参与提示词构建,帮助模型理解字段含义;
  4. 视频来源灵活:远程 URL、本地路径、原始字节三种输入方式对应url/filepath/content三个字段,cookbook 示例采用字节流方式(httpx下载),生产环境可改用文件路径或预先上传;
  5. 警惕素材命名与内容的错位sample_seaview.mp4实际是实验室场景,跑通示例后应以"视频真实内容"而非文件名来校验输出。

延伸阅读

  • 进阶示例:本目录的完整脚本见 cookbook/data_labeling/_13_video_classification/basic.py 与 with_confidence.py;
  • 相关原语:需要时间戳级事件提取时,参考 cookbook/data_labeling/_14_video_extraction/README.md 及其三个示例脚本(basic.pyscene_descriptions.pyaction_timestamps.py);
  • 媒体对象实现:libs/agno/agno/media/media.py 中的Video类与get_content_bytes/get_url
  • 运行入口:libs/agno/agno/agent/agent.py 中run()videos参数与调度逻辑;
  • Gemini 视频接入:libs/agno/agno/models/google/gemini.py 中视频消息格式化与文件上传逻辑。

【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 21:50:21

Telegram Monet未来路线图:Material You动态色彩适配计划

Telegram Monet未来路线图:Material You动态色彩适配计划 Telegram Monet是一款基于Material 3色彩系统为Telegram创建主题的工具,它能够帮助用户轻松生成符合Material You设计规范的个性化主题。本文将详细介绍Telegram Monet的未来发展路线图&#xf…

作者头像 李华
网站建设 2026/9/10 21:47:23

Jan Agent 长会话如何监控上下文占用并手动触发 /compact 压缩?

Jan Agent 长会话如何监控上下文占用并手动触发 /compact 压缩? 【免费下载链接】jan Jan is an open source alternative to ChatGPT that runs 100% offline on your computer. 项目地址: https://gitcode.com/GitHub_Trending/ja/jan 在 Jan Agent 终端控…

作者头像 李华
网站建设 2026/9/10 21:42:14

Internet Computer:区块链世界计算机架构解析与开发实践

1. 从"世界计算机"到Internet Computer:区块链的终极形态 1990年代,当蒂姆伯纳斯-李发明万维网时,他构想的是一种去中心化的信息共享系统。但今天的互联网早已背离初心,被科技巨头垄断。而Internet Computer&#xff08…

作者头像 李华
网站建设 2026/9/10 21:39:01

FlatBuffers Python 使用指南:库结构、读写与 NumPy 向量加速

FlatBuffers Python 使用指南:库结构、读写与 NumPy 向量加速 【免费下载链接】flatbuffers FlatBuffers: Memory Efficient Serialization Library 项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffers 本篇指南基于 FlatBuffers 官方文档中 Pyt…

作者头像 李华