ADK 眼镜试戴视频生成流水线(Video VTO / Glasses)实战指南:从 Veo 拼贴生成到质检后处理的完整实现
2026/9/15 13:24:41 网站建设 项目流程

ADK 眼镜试戴视频生成流水线(Video VTO / Glasses)实战指南:从 Veo 拼贴生成到质检后处理的完整实现

【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samples

本文以 ADK(Agent Development Kit)示例仓库 genmedia-for-commerce 中的眼镜(Glasses)视频虚拟试戴(Video VTO)模块为核心,系统讲解其从"模特照片 + 产品图 → 拼贴画(Collage)→ Veo 视频生成 → 绿幕裁剪与质检过滤"的完整实现链路,并深入剖析批量化生成、后台去背、Gemini 抖动检测等源码级细节。读完本文,你将掌握如何在 ADK Agent 与 MCP 工具层面调用run_glasses_video_generate/run_glasses_video_regenerate两个视频生成工具,理解其 REST API 参数语义,并能据此为自己的电商营销视频场景搭建可复用的生成与质检方案。

一、模块定位:Video VTO 与 Image VTO 的分工

genmedia4commerce仓库中,眼镜虚拟试戴(VTO,Virtual Try-On)能力被拆分为两个模块:

  • Image VTO(图像):基于 Nano Banana 完成去背景、创建眼镜佩戴帧(create-frame)、帧编辑(edit-frame)与图像增强(enhance-image),其完整概述见 image_vto/glasses/README.md;
  • Video VTO(视频,即本文主题):在图像能力之上,用 Veo 把拼贴画动画化为营销视频,并完成绿幕裁剪、人脸校验与抖动检测等后处理。

两个模块由 Router Agent 统一路由,对外暴露的 MCP 工具与 REST API 如下表所示:

能力维度MCP 工具REST 端点核心模型
图像glasses_vtoglasses_enhanceglasses_edit_frame/api/glasses/*(图像相关)Nano Banana
视频run_glasses_video_generaterun_glasses_video_regenerate/api/glasses/generate-video/api/glasses/regenerate-videoVeo + Gemini

视频流水线的总体链路为:

Model Image + Glasses Image → 去背景 → 创建拼贴画 → Veo 生成视频 → 后处理(绿幕裁剪/人脸校验/抖动检测)→ 输出 MP4

二、目录结构与职责划分

视频 VTO 模块的核心文件分布在两个目录中,职责清晰分离:

genmedia4commerce/workflows/video_vto/glasses/ # 流水线业务实现 ├── pipeline.py # 视频生成与再生成的整体编排(run_generation_pipeline / run_regeneration_pipeline) ├── generate_video_util.py # Veo 视频生成、拼贴画创建、后处理(绿幕裁剪) ├── glasses_eval.py # 视频抖动检测(Gemini)、颜色检测(OpenCV)、人脸检测(Vision API) ├── custom_template.py # AI 驱动的广告结构化 Prompt 生成 ├── men_templates.jsonl # 男性模特视频模板 ├── women_templates.jsonl # 女性模特视频模板 └── videos/ # 模板视频素材(men/、women/) genmedia4commerce/mcp_server/video_vto/glasses/ # MCP / API 暴露层 ├── glasses_mcp.py # MCP 工具:run_glasses_video_generate、run_glasses_video_regenerate └── glasses_api.py # REST API 路由(前缀 /api/glasses)

值得强调的是:pipeline.py是编排层,负责把"去背景 → 拼贴 → Veo → 后处理"串成一条完整链路;generate_video_util.py只负责拼贴画与 Veo 生成等原子能力;glasses_eval.py则是质检层。分层设计使得"生成"与"校验"可以独立演进、独立测试。

三、核心流水线:从图片到视频的完整编排

3.1 生成流水线run_generation_pipeline

入口函数run_generation_pipeline位于 pipeline.py,其执行流程可拆解为四个阶段:

  1. 去背景(Background Removal):若传入model_image_bytesmodel_side_image_bytesproduct_image_bytes,会以ThreadPoolExecutor(max_workers=3)并行调用共享工具workflows/shared/image_utils.replace_background,对三张图同时去背景(阈值参数为0.01),大幅压缩预处理耗时;
  2. 拼贴画创建(Collage Creation):根据zoom_level计算留白margin = (6 - zoom_level) * 100,再调用create_collage把模特正面图(可选侧面图)与眼镜产品图合成到纯色背景画布上,输出 PNG 字节并做 Base64 编码返回(collage_data字段)——这一数据在"再生成"时可直接复用;
  3. Veo 视频生成:将拼贴画字节与 Prompt 交给generate_veo,默认生成 4 条、每条 8 秒;
  4. 后处理与过滤:非动画模式下,用ProcessPoolExecutor并行对每条视频执行post_process_video——先做绿幕裁剪,再用 Gemini 做抖动检测,任一环节失败即丢弃该视频;最终只保留通过质检的视频,并返回{"videos": [...], "filenames": [...], "collage_data": "..."}

关键设计点:

  • 并行化:去背景用线程池(IO 密集),后处理用进程池(CPU 密集),两条并行路径互不干扰;
  • 容忍部分失败:只要仍有视频通过质检就正常返回,仅记录Some videos failed post-processing告警日志;全部失败时在生成阶段返回空列表(同时仍返回collage_data以便重试),而在再生成阶段则抛出异常;
  • 动画模式:当is_animation_mode=True时跳过拼贴与全部后处理,直接用模特图做 Veo 动画,产物文件名以animation_video_*.mp4命名,否则为collage_video_*.mp4

3.2 再生成流水线run_regeneration_pipeline

再生成(Regeneration)的意义在于:第一次生成时拼贴画可能已通过质检,但用户想换 Prompt 或增加视频条数,无需重复去背景与拼贴步骤。请求体由RegenerationRequest(pydantic 模型)承载:

class RegenerationRequest(BaseModel): prompt: str collage_data: str # Base64 编码的拼贴画 number_of_videos: int = 1 bg_color: str = "0,215,6,255" is_animation_mode: bool = False

run_regeneration_pipeline直接base64.b64decode(collage_data)还原拼贴画字节,跳过预处理,随即进入 Veo 生成与后处理阶段(动画模式同样跳过后处理)。背景色解析做了容错:tuple(map(int, req.bg_color.split(",")))失败时回退到默认绿色(0, 215, 6, 255)

四、Veo 生成工具:拼贴画创建与批量视频生成

4.1 拼贴画创建create_collage

create_collage 是视频质量的地基,函数签名与关键参数如下:

def create_collage( model_image_bytes=None, glasses_image_bytes=None, model_side_image_bytes=None, target_width=3840, # 画布宽,默认 4K 宽 target_height=2160, # 画布高 horizontal_margin=600, # 左右留白 vertical_margin=300, # 上下留白 image_spacing=300, # 图间间距 model_vertical_spacing=50, # 上下堆叠的两张模特图之间的间距 bg_color=(0, 215, 6, 255), # 默认绿色(便于后续抠像) ):

其核心策略是等比缩放、绝不裁剪或拉伸(全部使用Image.Resampling.LANCZOS高质量重采样),并针对输入图片数量分三种布局:

  • 单图:居中放置,按最受限的维度计算缩放比例;
  • 双图:左右并排,两图强制等高对齐,按content_width / (ar1 + ar2)求解公共高度;
  • 三图(模特正面 + 模特侧面 + 眼镜):左侧上下堆叠两张模特图(等高度、垂直间距 50px),右侧放置眼镜产品图,眼镜高度超出可用高度时按比例整体回缩。

从源码可推断,zoom_level(0–6)通过margin = (6 - zoom_level) * 100反向控制留白:zoom_level越大留白越小、画面主体占比越高;horizontal_marginvertical_margin之比为 2:1,符合横版电商视频的构图习惯。画布默认 3840×2160(4K),保证 Veo 生成时输入足够清晰。

4.2 批量视频生成generate_veo

generate_veo 解决了 Veo API 的单次请求条数上限问题:

  • 定义MAX_VIDEOS_PER_BATCH = 4,当请求条数超过 4 时自动拆分批次(如 6 →[4, 2],10 →[4, 4, 2]);
  • 多批次时用ThreadPoolExecutor(max_workers=len(batch_sizes))并行提交所有批次,再汇总结果,避免串行等待;
  • 单批次内部调用共享工具workflows/shared/veo_utils.generate_veo,使用模型常量VEO_MODEL = "veo-2.0-generate-001",并显式设置person_generation="allow_adult"enhance_prompt=False

4.3 绿幕裁剪后处理process_veo_video_model_on_fit

Veo 生成的视频开头通常包含一段纯绿幕帧,process_veo_video_model_on_fit 负责将其裁掉:

  1. 用共享工具workflows/shared/video_utils.extract_frames_as_bytes_list抽取全部帧;
  2. fps=24、分析频率fps_to_analyze=2(每秒抽 2 帧)、跳过前start_secs_to_skip=1秒为默认参数,抽取前 3 秒内的两批采样帧;
  3. 调用find_color_drop_frame(基于背景色占比的"颜色骤降并稳定"检测)与get_index_single_person(人脸检测),分别得到绿幕消失帧与"画面中仅剩一人"的帧;
  4. 取两者较大值作为裁剪起点,若裁剪后剩余时长超过 3 秒(original_seconds > 3)则判定视频过短、直接丢弃(返回None);
  5. workflows/shared/video_utils.create_mp4_from_bytes_to_bytes以 24fps、质量 7 重新封装为 MP4。

五、质检层:Gemini 抖动检测 + OpenCV 颜色检测 + Vision API 人脸检测

glasses_eval.py 汇集了三种互补的质检手段,是"失败视频过滤"的依据:

5.1 Gemini 2.5 视频抖动检测check_video_for_glitches

函数将视频字节与提示词组装为多模态内容,通过流式接口generate_content_stream(模型名来自环境变量MODEL_NAME_GENERATED_3)让 Gemini 以"高端时尚品牌数字内容质检专员"的身份审查视频。系统提示词 VIDEO_QC_SYSTEM_PROMPT 明确了审查基线:

  • 不应误报:短视频刻意极简、模特动作缓慢、无音轨是品牌标准风格,不得标记为异常;
  • 应报异常:可见的绿幕/蓝幕、乱码占位文本、剪辑软件界面元素/水印、画面撕裂或像素化等制作痕迹,以及漂浮图形、流体模拟等超现实 VFX;
  • 输出必须是 JSON 格式:{"is_glitched": true, "reason": "..."}

调用时设置了temperature=1response_modalities=["TEXT"]thinking_configthinking_budget=-1表示开启完整思考)以及系统指令注入;响应文本用正则\{[^}]*"is_glitched"[^}]*\}抽取 JSON 并解析,解析失败时返回None由上层兜底。

5.2 OpenCV 颜色检测

  • detect_color_background:将图像从 BGR 转到 HSV 空间,围绕目标色相的 HSV 区间(饱和度/明度下限默认 0.3)用cv2.inRange计算目标色像素占比;
  • find_color_drop_frame:对帧序列计算目标色占比的一阶差分,找到"占比骤降且后续变化稳定(stability_threshold=0.005)"的帧索引,即绿幕消失的起点。

5.3 Vision API 人脸检测

get_index_single_person将每帧构造为FACE_DETECTIONAnnotateImageRequest,通过batch_annotate_images一次性批量标注,再经is_video_valid判断:允许 0 或 1 人,出现第 2 人即视为异常;找到"从某帧起持续只有一人"的起点索引。两个关键判定值idx_bgidx_face任一为-1(未找到)都会让该视频被判为不合格。

六、AI 广告 Prompt 生成:custom_template.py

6.1 结构化广告 Promptgenerate_custom_template

generate_custom_template 用 Gemini(temperature=0response_mime_type="application/json")把用户的自然语言草稿扩展为结构化广告分镜。输出遵循StructuredPromptpydantic 模型,字段含义如下:

字段说明
subject模特外貌描述,模板为"A beautiful [gender] model is wearing the same [眼镜描述]…",最多三句
action模特动作/姿态,要求"以广告专业经验设计表情与动作"
scene拍摄场景,未指定时返回"Clean, minimalist studio environment with a uniform, soft grey background."
camera_angles_and_movements镜头角度与运动,未指定时返回" A static close-up shot, framed from the chest up."
eyeglasses/sunglasses眼镜/太阳镜外观描述(材质、框色、镜腿),二选一返回,另一个为None
lighting灯光设置,未指定时返回"Uniform lighting and no reflection on the (eyeglasses|sunglasses) lenses."
custom_field用户自定义字段的改写增强,无输入时为None

系统提示词强调:用户可能用意大利语或英语输入,但输出必须为英语;可结合输入的模特图/产品图判断是眼镜还是太阳镜。API 层(/generate-custom-prompt)在返回前还会补默认transition_sentence(有模特图为Instantly transition to:,否则为Instantly turn off the scene.)并剔除空值字段。

6.2 动画增强 Promptgenerate_animation_prompt

generate_animation_prompt 用于动画模式:把用户的一句话动画描述改写成"描述场景而非下达指令"的叙述式文案(例如把"Maintain naturalistic facial expressions…"改写为"The facial expressions are natural and the eyewear remains the hero product."),要求不超过 5 句话、语言简单、始终聚焦眼镜本身,且不偏离用户原始意图。

七、模板体系:men_templates.jsonlwomen_templates.jsonl

预置模板以 JSONL 存储,每行包含video_pathproduct_img与结构化video_prompt。以男性模板为例(men_templates.jsonl),三个模板分别对应"扶镜特写(m_wearing)""缓步走近(m_walking2)""转头正视(m_turn)"三类经典广告动作:

{"video_path": "/glasses/videos/men/m_walking2.mp4", "product_img": "/glasses/images/brown.png", "video_prompt": { "input_subject": "The person in the picture is wearing the exact same eyeglasses as in the photo...", "subject": "A beautiful male model, approximately 20 years old, is wearing the same Havana tortoiseshell eyeglasses...", "action": "The person walks confidently and slowly towards the camera from a medium distance then stops...", "scene": "Minimalist studio with a solid light grey background.", "camera_angles_and_movements": "Medium shot, static, positioned at eye-level.", "lighting": "Uniform lighting and no reflection on lenses.", "allowed_photos": ["45"] }}

/get_templates端点会读取这两个 JSONL 文件并原样返回(glasses_api.py),前端可据此让用户先选"模板视频+产品图"再微调 Prompt,降低生成成本与不确定性。

八、MCP 工具与 REST API:两种调用姿势

8.1 MCP 工具(供 ADK Agent 使用)

glasses_mcp.py 把流水线封装为两个异步 MCP 工具,内部用run_in_threadpool避免阻塞事件循环:

  • run_glasses_video_generate(model_image_base64, product_image_base64="", model_side_image_base64="", prompt="", number_of_videos=4, background_color="0,215,6,255", zoom_level=0, is_animation_mode=False):创建拼贴画并生成视频,返回{"videos": [...], "filenames": [...], "collage_data": "..."};Base64 非法时返回{"error": ...}zoom_level会被钳制到 0–6;
  • run_glasses_video_regenerate(prompt, collage_data_base64, number_of_videos=1, background_color="0,215,6,255", is_animation_mode=False):基于既有拼贴画重新生成,避免重复预处理。

8.2 REST API(供前端/脚本使用)

glasses_api.pyAPIRouter(prefix="/api/glasses")暴露以下端点:

端点方法说明
/get_templatesGET返回男/女模板视频列表
/generate-promptPOST由 JSON 结构化字段拼接单一 Prompt 字符串
/generate-custom-promptPOST自然语言 + 图片 → 结构化广告 Prompt(multipart)
/generate-animation-promptPOST文本 + 模特图 → 增强动画 Prompt
/generate-videoPOST拼贴生成视频(multipart)
/regenerate-videoPOST基于collage_data再生成(JSON)
/merge-videosPOST合并多个视频片段并支持变速

8.3 端到端调用示例

以下 Python 示例演示标准"Model-on-Fit"模式(model_image+product_imagemultipart/form-data):

import requests import base64 with open("model_front.jpg", "rb") as f: model_data = f.read() with open("glasses.png", "rb") as f: glasses_data = f.read() response = requests.post( "http://localhost:8000/api/glasses/generate-video", data={ "prompt": "A professional model wearing stylish sunglasses in a modern studio", "number_of_videos": 2, "background_color": "0,215,6,255", "zoom_level": 3, }, files={ "model_image": ("model.jpg", model_data), "product_image": ("glasses.png", glasses_data), }, ) result = response.json() for i, video_b64 in enumerate(result["videos"]): with open(f"output_{i}.mp4", "wb") as f: f.write(base64.b64decode(video_b64))

其中zoom_level=3对应留白(6-3)*100 = 300像素;若想对同一拼贴换 Prompt 重生成,可把响应中的collage_data回传给/regenerate-video

九、环境变量与配置

模块所需环境变量(配置于config.env):

变量说明默认值
PROJECT_IDGoogle Cloud 项目 IDmy_project
GENAI_LOCATION/GLOBAL_REGIONGemini API 区域global
VEO_LOCATIONVeo API 区域global
NANO_LOCATIONNano Banana API 区域global
MODEL_NAME_GENERATED_3抖动检测使用的 Gemini 模型名无(需显式配置)

pipeline.pyglasses_mcp.py均通过os.getenv("PROJECT_ID", "my_project")os.getenv("GLOBAL_REGION", "global")构造genai.Client(vertexai=True, ...)glasses_eval.py的 Vision API 客户端使用quota_project_id指向同一PROJECT_ID。注意抖动检测使用的模型名必须通过MODEL_NAME_GENERATED_3显式指定,否则 Gemini 调用会失败。

十、常见问题排查

"All videos failed processing"(所有视频均未通过处理)

  • 原因多为模特正脸不清晰,get_index_single_person无法稳定检出"仅一人";
  • 建议改用正面朝向、面部清晰的模特图,并优先选择front视角;
  • 可临时调小number_of_videos(如 2)观察是否有视频通过校验,用于定位是生成质量问题还是校验过严。

抖动视频被过滤

  • 这是预期行为——check_video_for_glitches专门过滤低质量输出,避免不合格素材流入电商页面;
  • 可通过增加生成条数(如 8 条,触发[4, 4]双批次并行)提高留存率。

绿幕未被正确裁剪

  • 确认background_color与实际拼贴背景一致,默认绿色0,215,6,255是经过find_color_drop_frame验证的最佳选择;
  • 若自定义背景色,需同时保证detect_color_background的 HSV 阈值能覆盖该颜色。

再生成时报错

  • run_regeneration_pipeline在全部视频失败时会抛出异常(区别于首次生成返回空列表),此时应检查collage_data是否完整、Prompt 是否与拼贴内容匹配,或降低number_of_videos重试。

十一、结语

眼镜 Video VTO 模块为"模特佩戴眼镜营销视频"的自动化生产提供了完整参考实现:pipeline.py负责编排与容错、generate_video_util.py负责拼贴与 Veo 批量生成、glasses_eval.py用 Gemini + OpenCV + Vision API 三重质检把关,custom_template.py则把自然语言一键转成专业广告分镜。无论是通过 MCP 工具让 ADK Agent 直接调用,还是通过 REST API 集成到电商前端,这套"生成—校验—过滤—重试"的架构都值得作为电商内容生产类 Agent 的蓝本复用。如需了解图像侧(Nano Banana 帧生成)与前端组件的完整配合,可继续阅读 image_vto/glasses/README.md 与仓库根目录的 README.md。

【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samples

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询