自动化混剪视频

本教程以扣子为例

单个混剪

开始接收的变量 a

  • bgm_url:背景音乐链接
  • Copywriting_list:混剪视频链接数组
  • video_duration_list:混剪视频信息数组
  • video_list:台词数组

流程图 a

graph TB
开始 --> 制作人物语音+字幕
subgraph 制作人物语音+字幕
    direction LR
        利用台词数组制作音频 --> 利用音频时长制作字幕 --> 语音合成
    end
制作人物语音+字幕 --> 制作混剪视频
subgraph 制作混剪视频
    direction LR
        利用代码随机打乱视频组+保证视频长度 --> 合成视频 --> 剪切多余视频
    end
制作混剪视频 --> 将混剪视频和音频合成
subgraph 配置字幕
    direction LR
         获取视频信息 --> 根据视频高度配置字幕位置
    end
将混剪视频和音频合成 --> 配置字幕 --> 添加字幕
添加字幕 --> bgm调整
subgraph bgm调整
    direction LR
         bgm剪辑 --> bgm声音调整
    end
bgm调整 --> 添加bgm --> 结束

插件 a

代码

字幕构建

变量

  • speech_info_list:视频信息列表 {text:台词;duration:时长}
async function main({ params }: Args): Promise<Output> {
  // 确保 speech_info_list 存在且是一个数组,否则返回空列表以避免错误。
  if (!params.speech_info_list || !Array.isArray(params.speech_info_list)) {
    return { text_list: [] };
  }

  const text_list = [];
  let cumulative_time = 0; // 初始化累积时间,第一个片段的 start_time 将是 0。

  // 遍历输入的 speech_info_list 数组
  for (const item of params.speech_info_list) {
    const start_time = cumulative_time;

    // 将字符串格式的 duration 转换为浮点数进行计算
    const duration = parseFloat(item.duration);

    const end_time = start_time + duration;

    // 构建符合目标格式的新对象并添加到结果数组中
    text_list.push({
      start_time: start_time,
      text: item.text,
      end_time: end_time,
    });

    // 更新累积时间,为下一个片段的开始时间做准备,并加上 0.1 秒的间隔。
    cumulative_time = end_time + 0.1;
  }

  // 返回最终构建的、包含 text_list 的对象
  return { text_list };
}

混剪视频打乱

变量

  • video_time_list:视频时间列表
  • original_video_list:视频列表
  • speech_time:音频总时长
interface Args {
  params: {
    original_video_list: string[], // 视频链接列表
    video_time_list: number[], // 视频时长列表 (单位:秒)
    speech_time: number, // 音频总时长 (单位:秒)
  };
}

// 将视频链接和时长组合在一起,方便处理
interface VideoInfo {
  url: string;
  duration: number;
}

async function main({ params }: Args): Promise<Output> {
  const { original_video_list, video_time_list, speech_time } = params;

  // --- 1. 输入验证 (Edge Case Handling) ---
  // 如果视频列表为空,直接返回空结果,避免无限循环
  if (!original_video_list || original_video_list.length === 0) {
    console.error("错误:输入的视频列表为空。");
    return { video_list: [] };
  }
  // 确保视频列表和时长列表长度一致
  if (original_video_list.length !== video_time_list.length) {
    throw new Error("视频列表和时长列表的长度不匹配。");
  }

  // --- 2. 数据准备 ---
  // 将视频链接和时长合并成一个对象数组,方便后续操作
  const allVideos: VideoInfo[] = original_video_list.map((url, index) => ({
    url: url,
    duration: video_time_list[index],
  }));

  // --- 3. 核心抽取逻辑 ---
  let selectedVideoUrls: string[] = [];
  let currentTotalDuration = 0;

  // 创建一个可变的视频池,用于“抽一个少一个”的操作
  let availableVideos = [...allVideos];

  // 循环条件:当累积时长小于或等于目标音频时长时,继续抽取
  while (currentTotalDuration <= speech_time) {
    // 如果可抽取的视频池空了(所有视频都抽过一轮了)
    if (availableVideos.length === 0) {
      // 重置视频池,开始新一轮抽取
      availableVideos = [...allVideos];
    }

    // 从当前视频池中随机选择一个视频
    const randomIndex = Math.floor(Math.random() * availableVideos.length);

    // 这就实现了“抽一个少一个”的效果。
    const [chosenVideo] = availableVideos.splice(randomIndex, 1);

    // 更新结果
    selectedVideoUrls.push(chosenVideo.url);
    currentTotalDuration += chosenVideo.duration;
  }

  // --- 4. 返回结果 ---
  return {
    video_list: selectedVideoUrls,
  };
}

多个混剪

开始接收的变量 b

  • title:视频核心内容
  • videos:视频列表
  • round:循环次数

流程图 b

graph TB
开始 --> 将视频静音+获得时长 --> 循环制作混剪视频
开始 --> 利用大模型得到背景音乐关键词 --> 查找背景音乐 --> 循环制作混剪视频


subgraph 循环制作混剪视频
    direction LR
        获得当前时间戳 --> 利用当前时间戳+用户输入主题+prompt获得文案 --> 随机选择bgm --> 生成单个混剪脚本工作流
    end
循环制作混剪视频 --> 结束

大模型 prompt

bgm

# 任务

你是一个 BGM 关键词生成器。根据主题 `{{title}}`,生成一组最适合在抖音、剪映中搜索的 BGM 关键词。

# 要求

- 直接输出结果,不要任何解释。
- 关键词之间用空格隔开。
- 只输出一组最佳组合。

文案

# 角色

你是一位顶级的短视频脚本专家,同时也是一个专业的 AI 字幕切分引擎。

# 核心任务

你的任务是根据我提供的视频主题 `{{title}}`,并结合下面的随机种子,在内部构思一篇完整的口语化视频口播稿,然后**直接输出**经过快节奏、超短句切分处理后的最终字幕文案。

**本次创作的随机种子是:`{{random_seed}}`。请将此种子作为你创意的来源,确保内容独一无二。**

# 工作流程与规则

1.  **构思脚本 (内部环节)**:根据 `{{title}}` 和随机种子,在你的“脑中”创作一段完整、流畅、吸引人的口播稿。**不要输出这一步的完整稿件**
2.  **切分并输出 (最终交付)**:将你构思好的脚本,严格遵循以下规则进行处理,并作为最终结果输出:
    - **字数限制**: 每行严格在 **8 个字以内**
    - **移除标点**: 必须 **移除所有标点符号**
    - **忠于原文**: 输出的文字必须完全来自于你构思的脚本,**不可修改、增删任何文字**
    - **格式**: 每行一句,直接输出纯文本。

插件 b