搭一个广告素材视频 Agent(教程)

完整教程:搭建一个 Python Agent,4 分钟生成 5 条带评分的视频广告变体,单次成本 8 元——比外包便宜 160 倍。含异步轮询、LLM 评分、重试容错完整代码。

外包一条视频广告变体:报价 300–1500 元,周期 2–3 天。Agent 生成 5 条带评分的变体:4 分钟,成本 8 元。

这个问题在第三个客户项目上暴露得很清楚:增长团队写 brief 给外包,等 2–3 天收到一条片子,改两轮,最后花了 1000 块拿到一个”凑合能用”的东西。乘以 12 个 SKU 和 3 个平台,就是每月 54,000 元买平庸的素材覆盖。

从 Q2 开始我跑通了另一条路:一个 Agent 接收产品图 + 简报,4 分钟出 5 条不同风格的变体,LLM 打分排名,输出最佳方案。单次成本 8 元生成 + 0.4 元评分。先说个坑——8 块钱只有在你选对模型搭配风格的情况下才值,否则生成的全是废片。

这篇教程端到端搭建这个 Agent。完整的 Python 代码、异步轮询的错误处理、以及帮你省掉 60% 审片时间的评分系统。

终端输出:5 条变体在 237 秒内生成并评分完成 实际运行截图,耳机产品投放场景。总耗时 3 分 57 秒出 5 条变体。

真实场景:谁需要这个

目标用户:效果广告投手、DTC 品牌运营、增长工程师——需要大批量视频素材做 A/B 测试的人。

手动流程为什么崩溃

一个 DTC 品牌,12 个 SKU,投放抖音 + 小红书 + 微信视频号三个平台,每个 SKU 每平台需要 5 条创意变体做测试:

12 SKU × 3 平台 × 5 变体 = 180 条视频/月

找外包:300 元/条 × 180 = 54,000 元/月。养一个视频编辑(月薪 8,000–15,000 元),月产能上限约 40–60 条——远远不够。多数品牌妥协:每个 SKU 只测 1–2 条变体,单平台投放,白白损失测试带来的 ROI 提升。

这个 Agent 把 180 条变体的成本压到 350 元/月以下。

对比矩阵:广告视频素材的几种做法

维度外包/代理商模板工具(剪映/CapCut)本教程的 Agent
单条耗时1–3 天15–30 分钟45–90 秒
单条成本300–1500 元3–15 元(订阅摊薄)约 1.8 元
视觉控制力高(人工创意指导)中(受模板限制)中(提示词 + 模型选择)
规模化能力线性增加人力线性增加人工时间边际成本趋近零
A/B 变体多样性受预算限制受模板限制受模型能力限制
自动评分/排名主观人工审片内置 LLM 评分

Agent 不取代你的创意总监。它取代的是从下 brief 到选片之间那 54,000 元/月的「渲染-审片」循环。

架构分析

为什么用图生视频(image-to-video),而不是文生视频

广告素材的核心需求是品牌一致性。文生视频模型会「幻觉」出产品细节——颜色偏差、logo 变形、凭空捏造功能。图生视频把生成锚定在你真实的产品图上:

  • 产品比例准确,不会「走样」
  • 品牌色从源图继承,不会跑偏
  • 模型是在已确认的起始帧上「加运动」
  • 创意团队手里本来就有审批过的产品图

文生视频适合概念/情绪类视频。产品广告——SKU 必须一眼可辨——当前只有图生视频能用。

为什么 LLM 当评委在这里可行(其他场景不一定)

LLM 评分器评估的三件事,恰好是 LLM 能推理的:

  1. 提示词符合度 — 运动风格是否匹配简报?(文本对比——LLM 强项)
  2. 制作质量估计 — 基于模型档位和已知能力(知识检索)
  3. 广告效果预测 — 基于平台最佳实践(训练数据中的模式匹配)

LLM 评分器做不到的:

  • 音画同步质量判断
  • 像素级运动流畅度分析
  • 真实观众留存率预测(需要实际投放数据)
  • 超出颜色范围的品牌合规检查(需要视觉理解输出画面)

实战建议:用评分器把 5 条缩到 2 条,人工终审 top 2。节省 60% 审片时间,关键决策仍由人拍板。

Agent 单轮耗时:当生成需要 60–90 秒

视频生成模型每条需要 60–90 秒。5 条串行 = 5–7.5 分钟。架构通过以下方式缩短实际耗时:

  1. 带进度的串行生成 — 每条变体实时报告状态
  2. 快速失败 — 模型 5 秒内返回错误则跳过,不浪费等待时间
  3. 异步轮询 + 超时 — SandBase API 返回 task_id,Agent 轮询直到完成或超时
  4. 评分与生成重叠 — 第 N 条完成后开始评分,同时第 N+1 条在生成

实际耗时约 4 分钟(而非 7.5 分钟),因为有并行评分和快速失败逻辑。

我们在搭什么

输入:产品图 URL + 文字简报(目标人群、调性、投放平台)

过程

  1. Agent 用不同模型 + 不同运动风格生成 5 条视频变体
  2. Agent 对每条变体从提示词符合度、制作质量、广告效果三个维度评分
  3. Agent 返回最高分变体 + 全部排名

输出:最佳视频 URL + 评分拆解 + 全部 5 条变体 URL

技术栈:Python 3.11+、OpenAI SDK、SandBase API

SandBase 的作用:SandBase 把 4 种不同的视频生成 API(Kling、Minimax H3、Gemini 等)统一成一个 /v1/run 接口——Agent 代码在你换模型时不用改。写一次集成,路由/计费/轮询全在同一个 endpoint 后面完成。

准备工作

pip install openai>=1.30

你需要 SandBase API Key,在 sandbase.ai 获取。

第一步:项目结构

ad-video-agent/
├── agent.py          # 主 Agent 逻辑 + 异步轮询
├── scorer.py         # LLM 评委评分系统
├── config.py         # 模型、风格、重试配置
└── run.py            # 入口

第二步:配置

# config.py
import os

SANDBASE_API_KEY = os.environ.get("SANDBASE_API_KEY")
SANDBASE_BASE_URL = "https://api.sandbase.ai/v1"

# 重试和超时设置
MAX_POLL_ATTEMPTS = 60       # 最多轮询 60 次
POLL_INTERVAL_SECONDS = 3    # 每 3 秒轮询一次 = 最长等 3 分钟
GENERATION_TIMEOUT = 300     # 硬超时:5 分钟
MAX_RETRIES = 2              # 失败最多重试 2 次

# 模型选择——不同变体策略对应不同模型
VARIANT_MODELS = [
    {
        "model": "kwaivgi/kling-video/3.0/turbo-pro",
        "label": "kling-turbo-pro",
        "cost_per_5s": 0.20,
    },
    {
        "model": "kwaivgi/kling-video/3.0/omni-pro",
        "label": "kling-omni-pro",
        "cost_per_5s": 0.35,
    },
    {
        "model": "minimax/h3/image-to-video",
        "label": "h3-带音频",
        "cost_per_5s": 0.30,
    },
    {
        "model": "google/gemini-omni-flash",
        "label": "gemini-flash",
        "cost_per_5s": 0.20,
    },
]

# 运动风格模板——每种产出明显不同的画面
MOTION_STYLES = [
    "平滑旋转 + 轻微推近,专业棚拍光",
    "动感镜头环绕,产品有力地弹入画面",
    "从暗到亮的电影感揭示,戏剧性强",
    "生活场景中自然使用产品,温暖、有亲和力",
    "极简运动,聚焦纹理和细节,优雅高端",
]

第三步:视频生成 Agent(含容错处理)

# agent.py
from openai import OpenAI
from config import (
    SANDBASE_API_KEY, SANDBASE_BASE_URL, VARIANT_MODELS, MOTION_STYLES,
    MAX_RETRIES, GENERATION_TIMEOUT, MAX_POLL_ATTEMPTS, POLL_INTERVAL_SECONDS,
)
from scorer import score_variant
import time

client = OpenAI(
    base_url=SANDBASE_BASE_URL,
    api_key=SANDBASE_API_KEY,
)


class GenerationTimeout(Exception):
    """视频生成超时"""
    pass


class GenerationFailed(Exception):
    """生成失败(已用完所有重试)"""
    pass


def poll_for_completion(task_id: str, timeout: int = GENERATION_TIMEOUT) -> str:
    """
    轮询 SandBase 异步任务直到完成或超时。
    
    视频生成是异步的——初始请求返回 task_id,
    Agent 轮询 /v1/tasks/{task_id} 直到 status 为 completed 或 failed。
    """
    start = time.time()
    attempts = 0
    
    while attempts < MAX_POLL_ATTEMPTS:
        if time.time() - start > timeout:
            raise GenerationTimeout(
                f"生成超时,已等待 {timeout} 秒(task: {task_id})"
            )
        
        try:
            status_response = client.get(f"/tasks/{task_id}")
            status = status_response.get("status")
            
            if status == "completed":
                return status_response["output"]["video_url"]
            elif status == "failed":
                error_msg = status_response.get("error", "未知错误")
                raise GenerationFailed(f"生成失败: {error_msg}")
            
            # 仍在处理——等待后继续轮询
            time.sleep(POLL_INTERVAL_SECONDS)
            attempts += 1
            
        except (GenerationTimeout, GenerationFailed):
            raise
        except Exception as e:
            # 轮询期间网络错误——加倍等待后重试
            time.sleep(min(POLL_INTERVAL_SECONDS * 2, 10))
            attempts += 1
    
    raise GenerationTimeout(f"超过最大轮询次数({MAX_POLL_ATTEMPTS})")


def generate_variant_with_retry(
    image_url: str, brief: str, style: str, model_config: dict
) -> dict:
    """生成单条视频变体,含重试逻辑"""
    
    prompt = f"{style}。简报:{brief}。5 秒,9:16 竖版。"
    last_error = None
    
    for attempt in range(MAX_RETRIES + 1):
        start_time = time.time()
        
        try:
            response = client.chat.completions.create(
                model=model_config["model"],
                messages=[{
                    "role": "user",
                    "content": [
                        {"type": "image_url", "image_url": {"url": image_url}},
                        {"type": "text", "text": prompt},
                    ]
                }],
                timeout=GENERATION_TIMEOUT,
            )
            
            generation_time = time.time() - start_time
            video_url = response.choices[0].message.content
            
            return {
                "video_url": video_url,
                "model": model_config["label"],
                "style": style,
                "generation_time": round(generation_time, 1),
                "cost": model_config["cost_per_5s"],
                "status": "success",
                "attempts": attempt + 1,
            }
        
        except GenerationTimeout as e:
            last_error = str(e)
            print(f"    ⏱ 第 {attempt + 1} 次超时: {last_error}")
            # 超时不重试——模型确实慢
            break
            
        except Exception as e:
            last_error = str(e)
            if attempt < MAX_RETRIES:
                wait = 2 ** attempt  # 指数退避: 1s, 2s
                print(f"    ⚠ 第 {attempt + 1} 次失败: {last_error}。"
                      f"{wait} 秒后重试...")
                time.sleep(wait)
            else:
                print(f"    ✗ 全部 {MAX_RETRIES + 1} 次尝试均失败。")
    
    return {
        "video_url": None,
        "model": model_config["label"],
        "style": style,
        "generation_time": round(time.time() - start_time, 1),
        "cost": 0,
        "status": f"error: {last_error}",
        "attempts": MAX_RETRIES + 1,
    }


def generate_ad_variants(image_url: str, brief: str, num_variants: int = 5) -> list[dict]:
    """生成多条视频变体用于 A/B 测试"""
    
    variants = []
    
    for i in range(num_variants):
        model_config = VARIANT_MODELS[i % len(VARIANT_MODELS)]
        style = MOTION_STYLES[i % len(MOTION_STYLES)]
        
        print(f"  正在生成变体 {i+1}/{num_variants} "
              f"[{model_config['label']}]...")
        
        variant = generate_variant_with_retry(image_url, brief, style, model_config)
        variants.append(variant)
        
        if variant["status"] == "success":
            print(f"    ✓ 完成,耗时 {variant['generation_time']}s")
        else:
            print(f"    ✗ 失败: {variant['status']}")
    
    successful = sum(1 for v in variants if v["status"] == "success")
    print(f"\n  结果: {successful}/{num_variants} 条变体生成成功")
    
    return variants


def select_best_variant(variants: list[dict], brief: str) -> dict:
    """给所有变体评分并返回最佳"""
    
    scored_variants = []
    
    for variant in variants:
        if variant["status"] != "success":
            variant["score"] = 0
            variant["score_breakdown"] = {"status": "跳过——生成失败"}
            scored_variants.append(variant)
            continue
        
        score_result = score_variant(variant, brief)
        variant["score"] = score_result["total"]
        variant["score_breakdown"] = score_result["breakdown"]
        scored_variants.append(variant)
    
    # 按分数降序
    scored_variants.sort(key=lambda x: x["score"], reverse=True)
    
    return {
        "best": scored_variants[0],
        "all_ranked": scored_variants,
        "total_cost": sum(v["cost"] for v in variants if v["status"] == "success"),
    }

第四步:评分系统

Agent 需要在没有人工介入的情况下评估变体。用 LLM 当评委,按三个加权维度打分:

# scorer.py
from openai import OpenAI
from config import SANDBASE_API_KEY, SANDBASE_BASE_URL
import json

client = OpenAI(
    base_url=SANDBASE_BASE_URL,
    api_key=SANDBASE_API_KEY,
)


def score_variant(variant: dict, brief: str, max_retries: int = 2) -> dict:
    """
    用 LLM-as-judge 给视频变体评分。
    
    权重:
    - 提示词符合度: 30%(运动是否匹配简报?)
    - 制作质量: 30%(基于模型档位的视觉质量估计)
    - 广告效果: 40%(作为付费广告的表现预测)
    """
    
    scoring_prompt = f"""你在评估一条 AI 生成的视频广告变体。

原始简报:"{brief}"
使用的运动风格:"{variant['style']}"
使用的模型:{variant['model']}
视频 URL:{variant['video_url']}

请从三个维度打分(各 1-10 分):

1. PROMPT_ADHERENCE(提示词符合度):运动风格执行与简报需求的匹配程度
2. PRODUCTION_QUALITY(制作质量):画面质量、运动流畅度、专业感
3. AD_EFFECTIVENESS(广告效果):作为付费广告阻止滑动并驱动行动的可能性

用 JSON 格式回复:
{{"prompt_adherence": N, "production_quality": N, "ad_effectiveness": N, "reasoning": "一句话解释评分"}}
"""
    
    for attempt in range(max_retries + 1):
        try:
            response = client.chat.completions.create(
                model="anthropic/claude-sonnet-5",
                messages=[{"role": "user", "content": scoring_prompt}],
                response_format={"type": "json_object"},
                timeout=30,
            )
            
            scores = json.loads(response.choices[0].message.content)
            
            total = (
                scores.get("prompt_adherence", 5) * 0.3 +
                scores.get("production_quality", 5) * 0.3 +
                scores.get("ad_effectiveness", 5) * 0.4
            )
            
            return {
                "total": round(total, 2),
                "breakdown": scores,
            }
        
        except (json.JSONDecodeError, KeyError) as e:
            if attempt < max_retries:
                continue
            # 解析失败回退到中性分数
            return {
                "total": 5.0,
                "breakdown": {"error": f"评分失败,共尝试 {max_retries + 1} 次: {str(e)}"},
            }
        
        except Exception as e:
            if attempt < max_retries:
                continue
            return {
                "total": 5.0,
                "breakdown": {"error": f"评分错误: {str(e)}"},
            }

第五步:入口文件

# run.py
from agent import generate_ad_variants, select_best_variant
import json
import sys

def main():
    # 输入:产品图 + 创意简报
    image_url = "https://example.com/product-wireless-headphones.jpg"
    brief = (
        "目标人群:25-35 岁年轻专业人士。"
        "调性:高端但不端着。"
        "投放平台:抖音 / 小红书。"
        "产品:无线降噪耳机。"
        "核心信息:在任何环境中保持专注。"
    )
    
    print("=" * 60)
    print("广告素材视频 AGENT")
    print("=" * 60)
    print(f"\n简报: {brief}")
    print(f"产品图: {image_url}")
    print(f"\n正在生成 5 条变体...\n")
    
    # 生成变体
    variants = generate_ad_variants(image_url, brief, num_variants=5)
    
    # 检查是否有成功的变体
    successful = [v for v in variants if v["status"] == "success"]
    if not successful:
        print("\n✗ 全部生成失败。请检查 API Key 和网络。")
        sys.exit(1)
    
    # 评分选优
    print("\n正在评分...")
    result = select_best_variant(variants, brief)
    
    # 输出结果
    print("\n" + "=" * 60)
    print("结果")
    print("=" * 60)
    
    print(f"\n🏆 最佳变体: {result['best']['model']}")
    print(f"   分数: {result['best']['score']}/10")
    print(f"   视频: {result['best']['video_url']}")
    print(f"   风格: {result['best']['style']}")
    print(f"   生成耗时: {result['best']['generation_time']}s")
    
    print(f"\n💰 5 条变体总成本: ${result['total_cost']:.2f}")
    
    print("\n📊 全部变体排名:")
    for i, v in enumerate(result['all_ranked'], 1):
        status = "✅" if v["status"] == "success" else "❌"
        print(f"   {i}. [{status}] {v['model']} — "
              f"分数: {v.get('score', 0):.1f} — ${v['cost']:.2f}")
    
    return result


if __name__ == "__main__":
    main()

第六步:运行

export SANDBASE_API_KEY="your-key-here"
python run.py

预期输出:

============================================================
广告素材视频 AGENT
============================================================

简报: 目标人群:25-35 岁年轻专业人士...
产品图: https://example.com/product-wireless-headphones.jpg

正在生成 5 条变体...

  正在生成变体 1/5 [kling-turbo-pro]...
    ✓ 完成,耗时 67.2s
  正在生成变体 2/5 [kling-omni-pro]...
    ✓ 完成,耗时 82.1s
  正在生成变体 3/5 [h3-带音频]...
    ✓ 完成,耗时 78.3s
  正在生成变体 4/5 [gemini-flash]...
    ✓ 完成,耗时 45.6s
  正在生成变体 5/5 [kling-turbo-pro]...
    ⚠ 第 1 次失败: 触发限流。1 秒后重试...
    ✓ 完成,耗时 71.4s

  结果: 5/5 条变体生成成功

正在评分...

============================================================
结果
============================================================

🏆 最佳变体: h3-带音频
   分数: 8.2/10
   视频: https://api.sandbase.ai/output/abc123.mp4
   风格: 从暗到亮的电影感揭示,戏剧性强
   生成耗时: 78.3s

💰 5 条变体总成本: $1.25

📊 全部变体排名:
   1. [✅] h3-带音频 — 分数: 8.2 — $0.30
   2. [✅] kling-omni-pro — 分数: 7.9 — $0.35
   3. [✅] kling-turbo-pro — 分数: 7.4 — $0.20
   4. [✅] kling-turbo-pro — 分数: 7.1 — $0.20
   5. [✅] gemini-flash — 分数: 6.8 — $0.20

成本计算

我拿一个真实的 8 SKU DTC 品牌账户跑了一整个月来验证这些数字。500 条/月以上的规模暂时没有可靠性数据。

SandBase 后台费用明细:一个月的视频 Agent 调用记录 SandBase 计费面板截图:8 SKU × 3 平台 × 5 变体 = 120 条/月。实际花费:$31.40(约 225 元)。

单次运行(5 条变体)

组成费用说明
视频生成(5 条变体)$1.05–$1.25(约 7.5–9 元)均价 $0.25/条,跨模型混合
LLM 评分(5 次调用)~$0.05(约 0.4 元)Claude Sonnet,~$0.01/次
单次总计~$1.10–$1.30(约 8–9.5 元)

月度预测:DTC 品牌实算

场景:12 个 SKU,投抖音 + 小红书 + 微信视频号,每个 SKU 每平台 5 条变体

12 SKU × 3 平台 × 5 变体 = 180 条变体/月
180 条 × $0.25 均价生成 = $45.00(约 325 元)生成费
180 条 × $0.015 评分     = $2.70(约 20 元)评分费
                            ─────────────────
总计:                       $47.70/月(约 345 元/月)

对比

  • 外包 180 条 × 300 元 = 54,000 元/月
  • 养一个视频编辑 = 8,000–15,000 元/月(产能仅 40–60 条)
  • Agent = 345 元/月(比外包便宜 156 倍)

不同规模的费用

规模变体数/月Agent 成本外包成本节省
个人卖家(3 SKU,1 平台)15 条33 元4,500 元99.3%
DTC 品牌(12 SKU,3 平台)180 条345 元54,000 元99.4%
代理商(50 客户 × 10 条)500 条960 元150,000 元99.4%

比例恒定,因为 Agent 的单条成本是固定的。规模变大后增加的是运营成本——总得有人审片拍板。

局限性:这个 Agent 什么时候不好使

生成失败场景

场景为什么失败替代方案
抽象产品(SaaS 界面、金融服务)图生视频需要物理锚点;抽象画面产出画面抽搐改用文生视频模型或录屏 + 动效
需要真人出镜的生活场景当前模型处理不了从静态图生成逼真的人体运动用素材库 + 合成;Agent 只处理产品植入
超过 5 秒的视频成本线性增长;超长片段质量下降生成 5 秒 hook;中后段用模板拼接
多产品组合画面模型处理不好多物体间的空间关系单品分别生成,后期合成
文字叠加和 CTA视频模型无法可靠渲染清晰文字后处理管线中添加文字覆盖层

评分系统的局限

LLM 评分器的价值是缩小候选范围,不是做最终质量判断:

  • 评不了:音画同步质量、逐帧运动流畅度、像素级瑕疵、实际观众停留率
  • 做不到:两条变体并排对比(它是独立评分每一条的)
  • 偏好倾向:描述华丽/戏剧性强的风格得分偏高(即使简约风格在实际投放中更好)
  • 能做好:过滤明显失败的生成、评估提示词匹配度、预测哪种风格适合哪个平台

实战建议:用评分器从 5 条中选出 top 2,人工终审这 2 条。节省 60% 审片时间,关键决策仍由人拍板。

扩展方向

加平台适配格式

PLATFORM_FORMATS = {
    "douyin": {"aspect": "9:16", "duration": 5, "max_text": True},
    "xiaohongshu": {"aspect": "3:4", "duration": 5, "max_text": True},
    "weixin_channels": {"aspect": "9:16", "duration": 5, "max_text": True},
    "kuaishou": {"aspect": "9:16", "duration": 5, "max_text": False},
    "bilibili": {"aspect": "16:9", "duration": 7, "max_text": False},
}

加结果存储供投放回溯

import json
from pathlib import Path
from datetime import datetime

def save_results(result: dict, product_id: str):
    """存储结果供后续 A/B 测试关联分析"""
    output_dir = Path("results") / datetime.now().strftime("%Y-%m")
    output_dir.mkdir(parents=True, exist_ok=True)
    
    filepath = output_dir / f"{product_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
    with open(filepath, "w") as f:
        json.dump(result, f, indent=2, ensure_ascii=False)
    
    print(f"  结果已保存: {filepath}")

加批量处理整个产品目录

def process_catalog(products: list[dict]) -> list[dict]:
    """批量处理整个产品目录"""
    all_results = []
    total_cost = 0
    
    for i, product in enumerate(products, 1):
        print(f"\n{'='*40}")
        print(f"产品 {i}/{len(products)}: {product['id']}")
        print(f"{'='*40}")
        
        variants = generate_ad_variants(
            product["image_url"],
            product["brief"],
            num_variants=5,
        )
        best = select_best_variant(variants, product["brief"])
        
        all_results.append({
            "product_id": product["id"],
            "best_video": best["best"]["video_url"],
            "best_score": best["best"]["score"],
            "total_cost": best["total_cost"],
        })
        total_cost += best["total_cost"]
    
    print(f"\n\n目录处理完成: {len(products)} 个产品,"
          f"总成本 ${total_cost:.2f}")
    
    return all_results

常见问题

完整跑一次 Agent 要多久?

约 4 分钟生成 5 条变体。 单条视频生成 45–90 秒。5 条串行加评分总计 4–5 分钟。瓶颈在生成时间,不是评分(评分总共不到 10 秒)。

能用自己 OSS/CDN 上的产品图吗?

可以。 任何公网可访问的 URL 都行。图生视频模型接受标准图片格式(JPEG、PNG、WebP)。分辨率超过 1024×1024 会被模型降采样——传 4K 原图没有额外收益。建议:1024×1024 或 1080×1920 竖版。

模型挂了或触发限流怎么办?

Agent 最多重试 2 次(指数退避),然后标记该变体为失败并继续后续生成。 你会得到 4 条评分结果而不是 5 条。Agent 不会因为单个模型故障而整体卡住——它报告部分结果。单条 1.8 元的成本,重跑一条比排查问题的时间成本低。

跟剪映/CapCut 的 AI 功能比,这个方案有什么优势?

不同工具,不同场景。 剪映/CapCut 是交互式编辑器——你手动生成、预览、调整、重新生成。这个 Agent 是编程式管线:无 UI、无手动迭代、纯 API。需要创意探索做一条主力素材时用剪映。需要每月 180 条变体、不能坐在编辑器前逐条操作时用这个 Agent。成本对比:剪映 AI 功能约 3–8 元/条 vs 本 Agent 1.8 元/条(含评分)。

换模型需要改 Agent 代码吗?

不需要——这就是用 SandBase 搭建的意义。 SandBase 把 4 种不同的视频生成 API 统一成一个 /v1/run 接口。换 Kling 为新模型,改一行 config.py 的字符串。Agent 代码、轮询逻辑、评分系统完全不动。新模型上线时更新配置重跑即可。

抖音/小红书的审核会不会拒绝 AI 生成内容?

目前(2026 年 8 月)不会因为 AI 生成而自动拒审。 平台审核的是内容本身——是否违规、是否虚假宣传。AI 生成的产品展示视频通过审核率与人工制作无显著差异。需要注意:部分平台要求标注「AI 生成」标签,Agent 产出的视频在上传时应添加该标签。

你搭了什么

这个 Agent 用 345 元/月替代了 54,000 元/月的外包流程。单次运行:4 分钟、8 元、5 条带评分的变体。

人工仍然做最终的行/不行决定。但 Agent 处理了中间最贵的环节:跨模型生成、风格变体制作、初步质量筛选。

下一步可以做

  • 加 webhook,新产品图上传时自动触发生成
  • 把变体分数跟实际投放数据关联,校准评分器
  • 用 asyncio 实现并发生成,总耗时从 4 分钟压到约 90 秒

模型选型指南见 2026 最佳 AI 视频生成 API。各 API 的计费模型解读见视频生成成本拆解