news 2026/9/5 2:26:53

智能体视频理解实战:基于Gemini构建会看视频的Agent

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
智能体视频理解实战:基于Gemini构建会看视频的Agent

近期在做 AI Agent 项目时,我经常遇到一个很现实的问题:Agent 能读文档、能调用接口、能聊天,但一旦让它“看懂一段视频”,方案就变得很零碎。有人先把视频抽成帧,再交给多模态模型逐张识别,最后自己拼接时间线;也有人直接把视频丢给模型,结果报格式不支持或上下文超限。

Google DeepMind 为最新 Gemini 模型带来的智能体视频理解能力,正在改变这个局面。它让 Gemini 模型可以直接承接视频内容,与智能体的规划、工具调用和决策流程结合,让开发者在较短时间内写出“会看视频”的 Agent。这篇文章会从技术背景聊到概念拆解,再给出一套可以运行的视频理解智能体示例,最后整理接入主流智能体平台时的常见问题和工程建议。

如果你正准备做视频内容问答、会议纪要、视频质检或任意需要“看懂视频再行动”的智能体应用,这篇文章应该能帮你少走不少弯路。

1. 背景:为什么智能体需要视频理解能力

1.1 Agent 的感知层不能只停留在文本

智能体(Agent)与传统问答系统的最大区别,在于它具备“感知 → 决策 → 行动”的闭环。过去几年,大多数 Agent 的感知层集中在文本、数据库和结构化 API 上,因为文本最容易标准化的。图像能力普及后,大家开始让 Agent 看懂截图、平面图、商品图。

但视频是另一种维度。

视频不是一张图片的简单堆叠,它包含时间顺序、运动轨迹、因果关系、人物交互、镜头切换和音频信息。如果你只把视频拆成几帧图片,模型很容易丢失“先在 A 点运动,三秒后进入 B 点”这类时序信息。Google DeepMind 对 Gemini 模型进行智能体视频理解能力的增强,本质上是要解决这个感知缺口。

对开发者来说,这意味着视频不再需要被粗暴地转成“图集”才能输入模型。Gemini 可以直接作为一个组件,被 Agent 调用,从一段视频中提取出结构化事件,再传递给后续决策模块。

1.2 Gemini 模型在视频理解上的技术特点

Gemini 系列是原生多模态模型,从设计上就支持文本、图像、音频、视频和代码的混合输入。在智能体场景下,视频理解能力的提升主要体现在三个层面:

第一,模型能够把视频当作上下文的一部分来理解,不只是识别画面中的物体,还可以回答“这几秒内发生了什么”“这个动作从哪个时间点开始”。第二,视频中的音频轨迹能和画面内容联合理解,例如在会议录像中同时判断发言人和说话内容。第三,模型输出可以做到结构化,直接生成时间线、摘要、标签或风险规则,方便下游系统继续处理。

实际开发中,我们可以把这种能力封装成一个工具函数。Agent 决定需要视频信息时,调用工具上传视频并提出问题,模型返回结构化结果。这个过程就是“智能体 + 视频理解”的常见形态。

1.3 典型的落地场景

视频理解类智能体并不是概念玩具,它已经在不少业务场景中具备实用价值。

例如会议场景中可以自动分析回放视频,提取决议、待办和发言人时间线;内容生产场景可以把一段长视频自动转成短视频脚本或标题建议;智慧零售场景可以分析店内监控片段,识别顾客动线和货架交互;安全运维场景则可以做视频流事件的二次确认,由 Agent 汇总多个摄像头画面中的异常状态。

在这些场景中,视频本身只是输入,最终价值来自 Agent 的后续动作:把分析结果写入工单、发送通知、更新数据库,或调用另一个业务模块。因此,Gemini 模型提供的视频感知层越稳定,整套智能体能力就越可靠。

2. 概念拆解:视频理解与智能体如何结合起来

2.1 视频理解不等于“把视频变成图片”

很多开发者早期接触视频理解时,会下意识地写一段抽帧脚本:每 2 秒截一张图,再用多模态模型逐张识别。这种方式能解决一部分简单问题,但存在明显局限。

抽帧会丢失大量信息。模型无法感知两帧之间的连续动作,也无法直接理解音频内容。视频中的运动速度、方向、交互关系,往往需要连续时间窗口才能判断。假如一段视频是“一个人先举起杯子,再喝水”,只抽取 3 张关键帧也许还能猜出来,但如果是“缓慢推门、停顿、进门、关门”,抽帧数量和时间点稍不合适,模型就会答错。

Gemini 这类原生多模态模型则可以直接接收视频内容,模型内部会进行帧采样和时序建模,开发者不需要手动控制抽帧策略。当然,这并不意味着开发者完全不用优化输入,后面第 4 节我会专门提到工程上的处理方式。

2.2 Agent 如何调用视频理解能力

在智能体架构中,视频理解通常作为一项“工具”存在,而不是让 Agent 每轮都上传完整视频。

这里可以做一个类比:人类员工不会每做一件事都重新看一遍监控录像,而是在需要确认某个事实时,才去调取对应片段。智能体也一样。Agent 的核心循环是:

  • 接收用户目标;
  • 分析当前任务需要哪些信息;
  • 如果需要视频内容,调用视频理解工具;
  • 得到结构化结果后,再决定下一步动作;
  • 循环直到完成任务。

Gemini 模型可以作为这个流程中的“视频理解引擎”。Agent 负责调度,Gemini 负责从视频中提取关键信息。两者各司其职。

2.3 一次完整理解任务的输入输出

要让这种方式跑通,开发者需要明确调用层协议。一次视频理解任务的核心输入是:

  • 视频文件路径或可公开访问的视频地址;
  • 用户问题或指令;
  • 可选的上下文信息,例如行业背景、输出要求。

模型输出可以是自然语言,也可以是 JSON。工程上更推荐使用 JSON,因为智能体的后续代码要处理结构化数据。比如:

{ "summary": "用户在15秒内完成了商品扫码和支付动作的组合验证", "events": [ { "start": 2.5, "end": 6.8, "event": "扫码" }, { "start": 10.1, "end": 14.6, "event": "支付确认" } ], "risk_flags": [] }

拿到这类结果后,Agent 可以继续写工单、做统计或发起人工复核。

3. 环境准备与开发前配置

3.1 基础运行环境

本文示例以常见 Python 环境为例。建议使用 Python 3.10 或 3.11,操作系统可以是 Windows、macOS 或 Linux。视频理解对网络请求和文件处理有一定要求,开发机最好能稳定访问 Gemini API 服务。

在终端创建虚拟环境:

python -m venv venv source venv/bin/activate

Windows 环境下激活命令是:

venv\Scripts\activate

进入虚拟环境后,再安装本文需要的官方 Python SDK。

3.2 安装 Gemini Python SDK

在较新的 Gemini API 使用方式中,Google 官方推荐使用google-genaigoogle-generativeaiSDK。不同项目阶段可能使用不同版本,这里需要特别注意:示例代码里的 API 风格要和你实际安装的 SDK 版本保持一致。

以社区常见的google-generativeai为例,可以通过 pip 安装:

pip install google-generativeai

如果你的项目已经采用了 Google 新版 GenAI SDK,则需要安装:

pip install google-genai

由于两家 SDK 的方法名和参数存在一定差异,建议你在运行示例前先查看本地安装版本:

pip show google-generativeai pip show google-genai

版本需要根据你的项目实际情况调整,本文示例以配置思路为主,重点演示完整链路。

3.3 配置 API Key 和模型名称

请先到 Google AI Studio 或对应云服务控制台,为你的账号开通 Gemini API 权限,并创建一个 API Key。不要直接把 Key 硬编码在代码里,更不要提交到 Git 仓库。

推荐在项目根目录创建.env文件,但不要提交:

GEMINI_API_KEY=你的_API_KEY GEMINI_MODEL_NAME=你的_模型名称

在 Python 中加载环境变量,最简单的方案是使用python-dotenv

pip install python-dotenv

然后创建config.py

import os from dotenv import load_dotenv load_dotenv() GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") GEMINI_MODEL_NAME = os.getenv("GEMINI_MODEL_NAME") if not GEMINI_API_KEY or not GEMINI_MODEL_NAME: raise ValueError("请先配置 GEMINI_API_KEY 和 GEMINI_MODEL_NAME")

具体模型名称并非固定值,需要以你的账号实际能访问的模型为准。你可以通过官方模型列表页查看,也可以在代码中通过 SDK 提供的模型查询能力获取。使用哪款模型取决于服务开通情况,所以这里没有写死型号。

3.4 示例项目结构

为了便于查看,我把示例代码整理成如下结构:

video-agent-demo/ ├── .env ├── config.py ├── video_agent.py ├── sample_video.mp4 └── requirements.txt

其中requirements.txt内容如下:

google-generativeai python-dotenv

如果使用的是新版 SDK,则把google-generativeai改成google-genai。测试时可以先用一段 10 到 30 秒的短视频,不要太长,便于观察 API 返回结果。

4. 完整实战:实现一个视频摘要智能体

4.1 需求分析

我们要开发一个最小可用的“视频摘要 Agent”。用户传入一段视频,Agent 需要完成以下任务:

  • 理解视频中的整体主题;
  • 列出一系列关键事件,并标注大致时间范围;
  • 如果视频里出现可能的异常点,单独输出风险提示。

为了让这个 Agent 有“智能体”的感觉,我先设计一个简单循环:

  1. 用户输入问题;
  2. Agent 调用视频理解工具;
  3. 模型返回结构化摘要;
  4. Agent 根据摘要内容,再次判断是否需要追问细节;
  5. 最终输出结果。

这里的 Agent 逻辑没有使用复杂框架,方便大家理解核心链路。如果你已经有 LangChain、Dify 或扣子工程,也可以把下面的“视频理解函数”直接封装成一个工具接入。

4.2 编写视频理解核心代码

首先创建video_agent.py,我会把视频上传、状态轮询和生成过程封装在同一个类中。

import os import time import json import google.generativeai as genai from config import GEMINI_API_KEY, GEMINI_MODEL_NAME genai.configure(api_key=GEMINI_API_KEY) class VideoUnderstandingAgent: def __init__(self): self.model = genai.GenerativeModel(GEMINI_MODEL_NAME) def upload_video(self, video_path: str): """上传视频文件到 Gemini 服务,并返回文件对象。""" print(f"开始上传视频:{video_path}") video_file = genai.upload_file(path=video_path) print("上传完成,等待服务端处理...") return video_file def wait_for_video_ready(self, video_file, timeout: int = 300): """轮询文件状态,等待视频进入 ACTIVE 状态。""" start_time = time.time() while time.time() - start_time < timeout: file_info = genai.get_file(video_file.name) state_name = file_info.state.name.upper() print(f"视频状态:{state_name}") if state_name == "ACTIVE": return True if state_name == "FAILED": raise RuntimeError("视频文件处理失败,请检查文件格式和大小") time.sleep(5) raise TimeoutError("视频处理超时") def create_analysis_prompt(self, question: str) -> str: """构造用于分析视频的系统提示词。""" prompt = f""" 你是一个视频理解助手。请根据视频内容回答用户的问题。 要求: 1. 输出 JSON 格式,不要输出额外解释。 2. 字段包括 summary、events、risk_flags。 3. summary 是视频整体摘要。 4. events 是事件列表,每个事件包含 start、end、event 字段。 5. risk_flags 是潜在风险或异常事件数组。 用户问题:{question} """ return prompt.strip() def analyze(self, video_path: str, question: str): """执行一次完整的视频理解任务。""" video_file = self.upload_video(video_path) self.wait_for_video_ready(video_file) prompt = self.create_analysis_prompt(question) response = self.model.generate_content([video_file, prompt]) raw_text = response.text.strip() # 如果返回内容中包裹了 ```json,需要先清理 if raw_text.startswith("```"): raw_text = raw_text.strip("`") if raw_text.startswith("json"): raw_text = raw_text[4:].strip() result = json.loads(raw_text) return result if __name__ == "__main__": agent = VideoUnderstandingAgent() result = agent.analyze( video_path="sample_video.mp4", question="请总结这段视频的主要事件和潜在风险" ) print(json.dumps(result, ensure_ascii=False, indent=2))

4.3 代码说明

第一段代码中的upload_video方法负责把本地视频上传到 Gemini 服务。为什么要先上传而不是直接传文件地址?因为视频文件通常较大,模型服务需要一个预处理过程,上传后得到的文件对象可以被后续生成请求引用。

wait_for_video_ready方法会轮询文件状态。刚上传的视频一般会处于PROCESSING状态,意味着服务端还在采样和解码。我们必须等它变为ACTIVE后再发起生成请求,否则可能报错或返回空结果。

create_analysis_prompt方法设计了固定的 JSON 输出结构。这一步在工程上很重要。如果没有输出约束,模型可能返回大段文字,Agent 后续解析会非常痛苦。通过 prompt 约束输出字段,我们可以把视频理解结果直接用于自动化流程。

analyze方法把整个调用串起来。先上传,再等待,最后把视频文件对象和提示词一起传给generate_content。这对应 Gemini 多模态输入的基本方式:视频文件对象会作为上下文的一部分被模型理解。

4.4 加入简单的 Agent 追问逻辑

上面的示例已经能完成单次视频问答。不过用户希望的是“智能体”,也就是在拿到初步摘要后,如果发现某些事件不够清楚,还能继续追问。

下面我在同一个类中增加一个ask方法,用于在同一段视频上继续追问:

def ask(self, video_file_ref, question: str): """基于已上传的视频文件继续提问。""" prompt = self.create_analysis_prompt(question) response = self.model.generate_content([video_file_ref, prompt]) return response.text

这里的video_file_ref可以是之前上传后得到的video_file对象。用它继续提问,能避免重复上传视频,节省时间和带宽。

不过要注意一个工程细节:上传后的视频文件通常有有效期,不同服务策略可能不同。开发完功能后,如果视频文件超过保留期,需要重新上传。

改造main入口,模拟一次简单的 Agent 多轮调用:

if __name__ == "__main__": agent = VideoUnderstandingAgent() upload_result = agent.upload_video("sample_video.mp4") agent.wait_for_video_ready(upload_result) first_result = agent.analyze("sample_video.mp4", "请总结这段视频的主要事件和潜在风险") print("第一轮结果:") print(json.dumps(first_result, ensure_ascii=False, indent=2)) # Agent 继续追问 second_result = agent.ask( video_file_ref=upload_result, question="请补充事件 2 的细节,比如人物动作和关键对话" ) print("第二轮追问结果:") print(second_result)

在这个简化设计中,Agent 还没用到真正的外部工具调用决策。它更像一个“可以连续对话的视频理解助手”。如果你的项目采用 LangChain 或 Dify,可以把analyze_video注册成一个工具,让大模型在决策过程中判断“是否要调用视频工具、传入什么参数、在什么时机调用”。

4.5 运行与验证

在项目根目录准备好sample_video.mp4,然后执行:

python video_agent.py

正常情况下,控制台会输出类似下面的日志:

开始上传视频:sample_video.mp4 上传完成,等待服务端处理... 视频状态:PROCESSING 视频状态:PROCESSING 视频状态:ACTIVE 第一轮结果: { "summary": "视频记录了一次物流仓库的分拣流程,操作员完成扫码和上架。", "events": [ { "start": 1.2, "end": 5.3, "event": "扫描包裹二维码" } ], "risk_flags": [] }

当然,实际输出会因为你使用视频内容、模型和提示词不同而不同。上面只是结构示意。

如果你遇到“模型返回的不是合法 JSON”的情况,可以尝试在提示词中加入“只输出 JSON,不要解释”。这不是模型能力不足,而是提示词约束不够强,后面第 5 节会继续说明。

4.6 使用 REST 风格调用的备选思路

某些环境不方便安装完整 SDK,或者你想把视频理解能力封装成内部 HTTP 服务,也可以参考 OpenAI 兼容接口的思路。Gemini API 本身也提供可直接调用的端点,开发者可以在服务端封装一层统一鉴权。

例如核心思路是:

  • 先把视频上传到文件服务;
  • 拿到可访问的文件 URI;
  • 在请求体中传入视频 URI 和文本提示词;
  • 解析返回内容。

由于不同时期接口格式差异较大,这里不写死请求体。开发时建议先看官方文档或直接使用 SDK,因为 SDK 会自动处理上传、鉴权和重试逻辑。

5. 把视频理解能力集成到主流智能体平台

5.1 Dify 智能体平台接入思路

很多团队现在使用 Dify 搭建智能体工作流。Dify 的核心思想是“工作流 + 工具”。要接入 Gemini 视频理解,最简单的方式是开发一个自定义工具,把视频理解模块封装成 HTTP 接口。

在 Dify 中,你可以创建一个自定义工具,输入参数包括:

  • video_url:视频文件的访问地址;
  • question:用户对视频提出的问题。

工具执行后返回结构化 JSON。Dify 工作流中再判断这个 JSON,决定下一步动作。

这里的关键不是纠结平台字段,而是先保证你的视频理解服务可以作为一个无状态 API 对外提供。用 FastAPI 封装一个简单接口可能更实用,这也是微服务集成的常见做法。

5.2 扣子(Coze)及其他平台的接入思路

扣子等平台同样支持“插件/工具”机制。你可以创建插件,插件内部调用一个远端服务接口。视频文件一般由用户上传到对象存储,插件再将对象 URL 传给视频理解服务。

这种“模型平台 + 自有服务”的结构,能够规避一个大问题:平台内部并不能直接访问你本地的私有文件路径。因此,开发者需要先把视频从 Agent 平台的附件区域转成可访问 URL,再把 URL 传给 Gemini 视频理解模块。

如果你的业务不想自建服务,也可以观察平台是否已经提供 Gemini 视频理解或类似的官方插件。每个平台的插件生态变化很快,以你实际使用的平台控制台为准。

5.3 工具化封装带来的扩展性

把视频理解能力封装成独立工具,不仅为了接入多个平台,也为了后续复用。

一个成熟的视频理解工具应当提供四个方法或接口:

  • 视频质量检查;
  • 视频摘要生成;
  • 指定时间范围的事件查询;
  • 风险规则提醒。

底层调用 Gemini,上层暴露统一输入输出。这样不同业务端只需要调整提示词,而不用改动核心调用流程。

6. 常见问题与排查思路

6.1 常见报错和处理方法

在视频理解功能开发过程中,报错是很正常的。我把常见问题整理成一个表格,方便你按图索骥。

问题现象常见原因解决思路
调用时报model not found使用了没有开通权限的模型名称到官方控制台确认模型是否支持视频输入和当前账号配额
视频一直处于 PROCESSING视频过大或者服务端处理排队压缩视频、缩短时长、适当降低分辨率,再重新上传
status_code=503错误服务暂时过载或账号没有可用实例增加重试策略、降低并发,确认账号配额后再发起请求
视频处理失败格式不支持或文件损坏转成 MP4 等通用格式,建议使用 H.264 编码
返回内容不是 JSON提示词约束不足强化输出格式约束,或对返回结果做二次格式化
API Key 无效环境变量加载失败或 Key 已轮换检查.env文件路径和 Key 是否过期,不要在代码中硬编码
文件对象过期上传视频后等待时间过长解析结果后及时保存,必要时重新上传文件

503错误通常是服务端或配额层问题,不是视频文件本身的问题。如果并发任务很多,建议加入随机退避重试,不要把同一个请求无限循环重发。

6.2 关于地区可用性的工程建议

在接入 Gemini API 时,部分开发者可能遇到与地区可用性相关的错误提示。这一点需要特别说明:模型和 API 服务的地域可用性属于服务条款约束范围,应该以官方发布的信息为准。

如果你的企业业务所在地无法直接调用,正确的做法是检查云资源所属区域是否符合官方支持范围;或者通过企业已有的、经过授权的合规网关接入。不要尝试使用非官方渠道绕过限制,因为这样既可能造成账号风险,也不利于生产环境长期稳定。

从工程角度来说,地区可用性问题不应写在业务代码里反复重试,而应该在部署架构阶段提前确认。团队可以把视频理解服务部署在合规区域内,并做好监控告警。

6.3 视频文件过大的处理方式

很多视频理解任务失败,不是模型能力问题,而是视频本身太大。Gemini API 虽然支持长视频,但单次请求文件大小和处理时间仍然有上限。

我建议在上传前做一个预处理:

  • 按需截断时间段,避免整个小时视频一次性分析;
  • 将大视频转码为 MP4;
  • 如果只关注画面内容,可以适当降低码率;
  • 如果业务需要长视频分析,可以先切分多个片段,再让 Agent 聚合各片段结果。

一个简单的ffmpeg截取命令示例:

ffmpeg -i input.mp4 -ss 00:00:00 -to 00:00:30 -c copy output_30s.mp4

把 30 秒以上的视频切短之后,再调用视频理解工具,稳定性会好很多。

6.4 输出解析不稳定的处理

模型偶尔会输出包含 Markdown 代码块包裹的 JSON,所以解析前需要清理。更稳妥的方式是在 Agent 层增加一个“输出校验”步骤。

如果字段缺失,可以让模型重新生成一次,而不是直接抛异常。这样虽然多一次调用,但能明显提升用户体验。

7. 最佳实践与工程建议

7.1 提示词结构要贴近业务

视频理解模型的通用知识很多,但不同业务需要调用的注意力完全不同。同样一段监控视频,安全团队关注的是侵入行为,运营团队关注的可能是顾客动线。

所以建议你不要使用“帮我总结视频”这类泛泛提示词,而是把行业背景和关键评分维度写清楚。比如:

你是零售门店运营分析助手。请从这段视频中识别: 1. 顾客进入门店后的移动路径; 2. 在货架前的停留时长; 3. 是否存在长时间无人服务的情况。

模型在明确输出要求后,返回结果会更稳定。

7.2 控制视频长度与上下文成本

视频理解对 token 的消耗明显高于纯文本。一次完整视频分析的成本取决于视频时长、采样密度和输出长度。生产环境里,同一段视频不应该被反复上传解析。

可以考虑设计一个简单的缓存机制。例如用视频文件的 MD5 值作为键,把摘要结果存入 Redis 或数据库。当相同视频再次提交时,直接返回历史结果。这样既能降低成本,也能让反馈速度更快。

7.3 结构化输出比自然语言更可靠

Agent 工程中,结构化输出非常关键。调用 Gemini 时,建议在提示词中明确字段名、类型和示例。如果平台支持 JSON Schema 约束,也可以直接启用。结构化输出能让后续代码不再依赖脆弱的关键词匹配。

7.4 安全合规与最小权限

视频数据往往包含大量隐私信息,例如人脸、声音、地理位置、时间戳。接入视频理解能力前,你需要明确几个问题:视频来源是否合法?分析用途是否明确告知了相关方?处理后的数据保存在哪里?保留周期是多久?

生产环境里,API Key 应当保存在密钥管理系统或服务端环境变量中,不应该下发到前端。视频文件如果是敏感数据,建议在传输和存储环节启用加密。

同时,Agent 的动作危险程度也要控制。视频理解结果只能作为“参考判断”,涉及高风险操作时,应该由人工确认或严格按照业务权限规则执行。

7.5 视频理解工具的调用设计

如果你要做一个真正的智能体,而不是单个问答脚本,我建议把视频理解封装成独立工具,并设置清晰的参数格式。

工具可以命名为video_analyze,参数如下:

  • video_pathvideo_url
  • question
  • need_detail_events
  • start_time
  • end_time

这样模型在规划时,可以只截取感兴趣的片段进行分析,而不是每次处理整个视频。

7.6 日志与可观测性

视频理解任务链路较长,如果失败,很难一眼定位是上传失败、处理超时还是模型输出格式错误。建议在关键节点打印日志。

一个最小实践的日志结构可以包含:

task_id video_file_name video_duration upload_status processing_duration model_name first_token_latency output_format_valid

有了 task_id,后续无论是排查线上问题,还是分析成本,都能做到有据可查。


现在你可以在自己的 Agent 里加一个“会看视频”的技能了。建议先选一段不超过 30 秒的业务视频,跑通最小闭环,再把单次调用慢慢升级成带缓存、多片段聚合和工具调用的完整链路。视频理解的价值,最终要看 Agent 拿到这些信息后能把事情推进到什么程度。动手写完第一个可运行的流程后,你会发现这个能力并没有想象中那么复杂。

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

智能鱼缸对比评测:当贝鱼缸2SUltra和米家鱼缸2Pro

桌面智能鱼缸怎么选&#xff1f;预算卡在599元这一档&#xff0c;当贝鱼缸2SUltra和米家鱼缸2Pro是绕不开的两台。它们外观都是50缸、同价竞争&#xff0c;但真养过一轮、把做工和参数拆开看&#xff0c;差距比价签上大得多&#xff1a;当贝鱼缸在缸体材质、过滤、灯光显色、静…

作者头像 李华
网站建设 2026/9/5 2:21:59

Cadence Allegro PCB设计:彻底掌握取消高亮对象的4种方法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 2:21:57

从数据分析视角拆解MOBA翻盘局:关键节点、资源控制与团队决策

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 2:16:39

基于计算机视觉的射击训练低血糖实时检测系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 2:14:16

Flutter OH 原生侧权限申请说明

Flutter OH 应用在调用某些系统功能时&#xff08;如网络、相机、定位、存储等&#xff09;&#xff0c;需要在 ohos 原生侧声明相应权限。若未正确申请权限&#xff0c;可能导致 API 调用失败或应用崩溃。 权限声明位置 在 ohos/entry/src/main/module.json5 文件的 module 内…

作者头像 李华
网站建设 2026/9/5 2:13:49

Claude Code与Playwright MCP:AI驱动的Web自动化测试实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华