【直播切片工作台】第11章:剪辑项目模型 VideoProject

简介: 本章详解剪辑项目模型 `VideoProject`:以双层选段(clips0粗筛、clips1精修)为核心,聚合素材、提示词、画布与发布元数据;约束常量统一校验LLM输出与前端输入,实现AI与人工协同的高精度短视频生产。

第11章:剪辑项目模型 VideoProject

本章深入 internal/model/video_project.go:一个剪辑项目如何把「素材 + 提示词 + 选段 + 画布 + 元数据」打包成一张加工单。核心是 clips0(粗选区间)与 clips1(精修选段)的双层选段设计,以及短视频标题/描述/话题的约束常量族。

流程

剪辑项目是 AI 与人工协同的交界面。创建时用户提供 name、live_id(关联素材,需其 ASR 已完成)、prompt_id(提示词,默认 1);可选携带 clips0 粗选区间(人工圈定「值得 AI 关注的大范围」)。此后 clips 的流转有两条路:

  • 一键成片:AI 切片阶段读取 clips0(空则全片)+ 提示词 + ASR 段落 → LLM 挑选句段 → 直接回写 clips1(带文本与词级时间戳)→ 草稿阶段裁剪生成。
  • 协同模式:AI 切片回写 clips1 后任务结束 → 人工在前端调整 clips1(增删改区间、改正文本)→ 手动发起草稿任务。

画布 Width/Height 决定剪映工程分辨率(0 表示未设置,创建任务时按素材分辨率自动补齐);EnableCaptions 控制草稿是否加字幕轨;Title/Description/Topics 三个字段在 AI 切片成功后由 Worker 从 LLM 结果回写,作为短视频发布时的元数据(前端发布面板可直接复用)。

输入输出视角:项目输入是「素材 ID + 提示词 ID + 可选粗选」,输出是「clips1 + 元数据」,中间被任务驱动演进。项目本身不存任务状态——运行中任务通过 GET /video-projects/:id/running-tasks 实时查询。

实现

双层选段的设计意图:

  • clips0 []ClipRange:只有毫秒区间,无文本。粗筛粒度(分钟级),表达「这段直播值得看」。
  • clips1 []ClipWithText:带逐句文本与可选词级时间戳。精修粒度(秒级),是草稿裁剪与字幕的直接数据源。词级 words 由 AI 切片 Worker 从 ASR 段落的 words 中截取对应时间窗写入,字幕对齐因此能精确到字。

约束常量族把产品规则写成代码(按 Unicode 码点计数,避免「汉字一个字算仨字节」的坑):

VideoProjectTitleMinRunes       = 2   // 标题 2~12 字
VideoProjectDescriptionMaxRunes = 128 // 描述上限
VideoProjectTopicMinRunes       = 2   // 话题每个 2~12 字
VideoProjectTopicsMaxCount      = 6   // 共 2~6 个

这些常量与 AI 切片的提示词输出格式(第 36 章的 aiSliceUserPromptOutputFormat)严格对齐——LLM 被要求按同样约束产出,Worker 校验再回写,模型输出与数据契约由同一组常量约束。

其他实现细节:

  • DefaultVideoProjectPromptID = 1:种子数据保证 ID=1 的提示词存在(第 14 章),新建项目缺省即有可用提示词。
  • ProjectSource 字段记录项目来源(如手动创建 / 导入),为多入口创建留审计痕迹。
  • PromptID 无外键约束(注释明示):删提示词不级联,service 层换提示词时校验存在性。
  • 列表视图 VideoProjectListItem 只含摘要字段,巨大的 clips JSONB 不进列表页。

📌 设计决策

  • 双层 clips 而非一层带标记:粗选与精修语义不同(范围 vs 句段),类型系统直接区分(ClipRange vs ClipWithText),避免同一结构里塞可空字段。
  • 元数据回写到项目而非仅存任务:一次 AI 切片产出可服务多次草稿生成与人工微调后重发,避免「重新切片才能改标题」。
  • 画布尺寸存在项目上、任务创建时快照到 task:草稿任务可被请求参数覆盖画布,项目值只是默认来源(见第 12 章 task.Width 注释)。

代码示例

项目实体全貌(节选注释):

// internal/model/video_project.go
type VideoProject struct {
   
    ID       uint   `gorm:"primaryKey" json:"id"`
    Name     string `gorm:"size:64;uniqueIndex" json:"name"`
    LiveID   uint   `gorm:"column:live_id;not null;index;comment:关联直播素材ID" json:"live_id"`
    // PromptID 提示词 ID(对应 llm_system_prompt.id),无外键约束,默认 1。
    PromptID uint   `gorm:"column:prompt_id;not null;default:1;index" json:"prompt_id"`

    Clips0 []ClipRange    `gorm:"column:clips0;serializer:json;type:jsonb;not null;default:'[]';comment:视频切片列表毫秒" json:"clips0"`
    Clips1 []ClipWithText `gorm:"column:clips1;serializer:json;type:jsonb;not null;default:'[]';comment:带文本与词级时间戳的切片列表毫秒" json:"clips1"`

    Width           int    `gorm:"not null;default:0;comment:剪映草稿工程宽度像素" json:"width"`
    Height          int    `gorm:"not null;default:0" json:"height"`
    EnableCaptions  int    `gorm:"column:enable_captions;not null;default:1;comment:是否添加字幕0否1是" json:"enable_captions"`
    Title           string `gorm:"size:64;not null;default:'';comment:短视频标题" json:"title"`
    Description     string `gorm:"size:512;not null;default:''" json:"description"`
    Topics          []string `gorm:"column:topics;serializer:json;type:jsonb;not null;default:'[]'" json:"topics"`
    ProjectSource   string  `gorm:"column:project_source;size:32;not null;default:''" json:"project_source"`
}

草稿流水线消费 clips 的入口(第 38 章详述):

// internal/draft/builder.go(节选)
clips := req.Clips
if len(clips) == 0 {
   
    if req.Project == nil {
   
        return nil, fmt.Errorf("clips 为空且未提供 project")
    }
    clips, err = prepare.ResolveClipRanges(req.Project) // 从项目解析 clips
    if err != nil {
   
        return nil, err
    }
}
// 合并间隔 ≤500ms 的相邻片段,减少 ffmpeg 调用与草稿碎片
clips = prepare.MergeAdjacentClipRanges(clips, prepare.ClipMergeGapMS)

小结

  • 项目 = 素材 + 提示词 + 双层选段 + 画布 + 发布元数据的聚合体,是 AI 与人工的协作界面。
  • clips0 管范围、clips1 管句段,类型即语义;词级时间戳让字幕精确到字。
  • 约束常量族同时约束 LLM 提示词与数据校验,单一事实源。

思考题

  1. clips1 的人工编辑与 AI 重跑同时发生时,如何设计「保留人工修改」的合并策略?
  2. Title/Topics 回写项目后,多次切片会互相覆盖,是否应改为「每次任务一份元数据」?

项目信息

  • GitHub仓库:github.com/Chyona/live-mixer
  • 项目案例:gogoshine.com
相关文章
|
2月前
|
存储 人工智能 前端开发
【直播切片工作台】
live-mixer 是面向直播回放的端到端AI切片工作台,基于Go+React构建。通过DB任务队列(乐观锁)、同进程Worker、JSONB存储与接口化依赖,实现ASR转写、AI智能选段、剪映草稿自动生成及成片导出,全流程轻量高效。(239字)
|
1月前
|
JSON 文字识别 API
open-code-review 接百炼:7 档 qwen 模型审同一份代码,一次 PR 的总账与耗时实测
本文实测 open-code-review 接入百炼 qwen 系列模型的完整方案:内置 dashscope provider,支持 7 档 qwen 模型;单价差 40 倍,单次审查成本差 545 倍;qwen3.7-plus 为性价比拐点(23.4 秒、满分、¥0.0799 内);详解配置、成本估算与门禁选型。
open-code-review 接百炼:7 档 qwen 模型审同一份代码,一次 PR 的总账与耗时实测
|
1月前
|
人工智能 自然语言处理 API
阿里云Token Plan全面升级:模型 + Agent 工具,一次配齐千问、Qoder等各类 Agent工具
阿里云Token Plan完成重磅升级,原有价格不变、权益全面扩容,新增Harness Agent全链路开发权益,以Credits统一计量覆盖千问、DeepSeek等数十款主流模型与多模态能力。产品分为个人版与团队版两大序列,个人版三档39元/月起适配独立开发者,团队版按席位订阅提供企业级数据安全与多账号管理能力,搭配夜间五折、满减券等多重优惠,帮助用户低成本搭建全链路AI工作流。
|
5月前
|
人工智能 Linux API
突发!速推剪映小助手下架,依赖第三方的工作流全崩了!
突发!速推剪映小助手下架,依赖第三方的工作流全崩了!
|
7月前
|
存储 人工智能 前端开发
使用Spring AI Alibaba构建智能体Agent
本文详解使用Spring AI Alibaba框架,结合DashScope和React Agent,通过两个实战案例(基础测试+生产级应用),教你快速构建Java AI智能体
3152 7
|
5月前
|
人工智能 编解码 监控
【开源剪映小助手】视频生成接口
Capcut Mate视频生成接口提供云端异步渲染服务,支持提交任务(/gen_video)与实时查询状态(/gen_video_status),具备进度跟踪、多格式输出、错误恢复及API密钥验证等功能,适用于各类AI视频创作场景。(239字)
|
6月前
|
监控 前端开发 中间件
【开源剪映小助手】调试与故障排除
本指南面向capcut-mate开发者,系统梳理Python后端(FastAPI)、Electron桌面端与React前端的调试方法,涵盖日志分析、IPC通信、异常处理、性能优化及常见故障排查,助力高效定位与解决运行时问题。(239字)
313 10
|
6月前
|
编解码 缓存 API
【开源剪映小助手】草稿管理接口
本文档详解剪映草稿管理三大核心API:创建、保存及获取草稿文件列表,涵盖请求参数、响应格式、错误码、URL规则与最佳实践,助力开发者快速集成稳定高效的草稿系统。(239字)
|
6月前
|
Linux 测试技术 开发者
【开源剪映小助手】开发者指南
capcut-mate 是开源剪映自动化工具,基于 FastAPI + Electron 构建,支持跨平台草稿管理、媒体处理与视频导出。采用分层架构、条件依赖与优雅降级机制,确保 Windows/Linux 兼容性与一致开发体验。(239字)
|
6月前
|
存储 缓存 前端开发
【开源剪映小助手】代码结构说明
本项目为CapCut Mate(剪映助手)后端与桌面客户端一体化方案,采用“FastAPI(Python)+ Electron+React”混合架构。后端分层清晰(Router→Service→Utils),前端通过预加载脚本与IPC安全调用原生能力,支持草稿管理、媒体处理与视频导出,兼顾性能、可维护性与跨平台兼容性。(239字)

热门文章

最新文章