



制作动态视频,会用到多个子工作流:
主工作流:文生图 + 串联图生视频 + 生成剪映草稿
子工作流1:批量提交图生视频任务 + 循环查询任务
子工作流2:通过taskidList批量查询任务状态 + 输出视频地址
一、搭建子工作流2: search_video
我们先来搭建子工作流2:通过taskidList批量查询任务状态
子工作流2:入参task_id_list 和 api_key

代码节点之前是用于生成video_url失败的情况下,这个做一个特殊的占位标识,可以在主流程中用静态图片等替代,比如失败后将video_url固定复制一个字符串,外层工作流进行代码判断做特殊处理,这里没有用到, 只是预留

结束节点输出视频地址:

二、搭建子工作流1:img_to_video
批量提交循环中,代码_3做了一个1s的等待,避免频率过高导致提交失败:

-
async function main({ params }: Args): Promise<Output> {
await sleep(1000); // 等待1秒// 构建输出对象const ret = {"status": 0};return ret;}function sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));}
在当前工作流中,调用我们上面创建的子工作流2:search_video,用于批量查询任务状态

循环查询任务状态,这里按次数 + 等待30s, 阿里通义-turbo一般3-5分钟可生成,循环次数够用,这里没有使用无限循环,防止进入死循环


async function main({ params }: Args): Promise<Output> {
await sleep(30000); // 等待30秒let video_urls = params.video_urls;const nonEmptyUrls = video_urls.filter(item => item != null && item.trim() !== "");const length = Array.isArray(params.taskid_list) ? params.taskid_list.length : 0;// 构建输出对象const ret = {"video_urls": nonEmptyUrls,"ori_length": length};return ret;}function sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));}
由于我们循环批量查询了很多次任务状态,但只有最后一次才全部成功,才会有全部的视频地址,所以增加代码_2节点获取最后一次批量查询到的视频地址集合;

-
async function main({ params }: Args): Promise<Output> {var urls = params.urls;var final_list = []var list = urls[urls.length-1].video_urls;for(let i=0;i<list.length;i++){final_list.push(list[i]);}// 构建输出对象const ret = {"final_list":final_list};
return ret;}
输出视频地址:

到此,我们已经把 批量图生视频的 创建和查询工作流搭建完成
接下来就和之前分享的火柴人流程类似了,在主流程中把批量图生视频的子流程串起来就可以了。
三、搭建主流程


开始节点,支持自定义绘画提示词,视频长度和背景音乐:

增加 代码节点 计算图片数量
默认一张图片生成5s视频,最多支持20s,就是最大4张图片,视频时长支持5/10/15/20 三种,对应图片数量也就是1/2/3/4张 四种情况:

// 在这里,您可以通过 ‘params’ 获取节点中的输入变量,并通过 'ret' 输出结果// 'params' 和 'ret' 已经被正确地注入到环境中// 下面是一个示例,获取节点输入中参数名为‘input’的值:// const input = params.input;// 下面是一个示例,输出一个包含多种数据类型的 'ret' 对象:// const ret = { "name": ‘小明’, "hobbies": [“看书”, “旅游”] };
async function main({ params }: Args): Promise<Output> {var times = params.times;var times_data = times/5;if(times_data>4){times_data=4;}// 构建输出对象const ret = {"times": times_data};return ret;}
直接按代码的次数循环,生成指定数量的首帧图片:


增加代码_2组长 图生视频需要的数据格式:

-
// 在这里,您可以通过 ‘params’ 获取节点中的输入变量,并通过 'ret' 输出结果// 'params' 和 'ret' 已经被正确地注入到环境中// 下面是一个示例,获取节点输入中参数名为‘input’的值:// const input = params.input;// 下面是一个示例,输出一个包含多种数据类型的 'ret' 对象:// const ret = { "name": ‘小明’, "hobbies": [“看书”, “旅游”] };
async function main({ params }: Args): Promise<Output> {var prompt = params.prompt;var imgList = params.imgList;var data =[];for(var img of imgList){data.push({img_url:img,prompt:prompt});}// 构建输出对象const ret = {"img_list": data};return ret;}
最后,通过代码节点组装 背景音乐 和视频素材,生成剪映草稿:

-
// 在这里,您可以通过 ‘params’ 获取节点中的输入变量,并通过 'ret' 输出结果// 'params' 和 'ret' 已经被正确地注入到环境中// 下面是一个示例,获取节点输入中参数名为‘input’的值:// const input = params.input;// 下面是一个示例,输出一个包含多种数据类型的 'ret' 对象:// const ret = { "name": ‘小明’, "hobbies": [“看书”, “旅游”] };async function main({ params }: Args): Promise<Output> {const { video_url_list} = params;var bg_audio_url = params.bg_audio_url;
// 处理音频数据let audioStartTime = 0;let maxDuration = 0;const videoTimelines = [];const video_urls = [];// 处理图片数据const imageData = [];let imageStartTime = 0;// 特效 [{"effect_title":"金粉闪闪","end":5000000,"start":0}]const eff_list =[];const img_timelines = [];const video_timelines =[];for (let i = 0; i < video_url_list.length; i++) {const duration = 5000000;video_timelines.push({start: imageStartTime,end: imageStartTime + duration});imageStartTime += duration;maxDuration = maxDuration + duration;}// 添加背景音乐const bg_audio_list = [];const bg_audio_timelines = [];//var audio_url = "https://p9-bot-workflow-sign.byteimg.com/tos-cn-i-mdko3gqilj/d15a8f419716466f8c6976ded535332e.mp3~tplv-mdko3gqilj-image.image?rk3s=81d4c505&x-expires=1775488748&x-signature=r%2FLegsQ9uDw2FzTYk68fMGFMKOQ%3D&x-wf-file_name=%E7%BE%BD%E8%82%BF+-+Windy+Hill+%28%E9%A3%8E%E4%B9%8B%E8%B0%B7%29.mp3";// 默认动漫var audio_url ="https://p9-bot-workflow-sign.byteimg.com/tos-cn-i-mdko3gqilj/5f75fc94355e45178365b66a7fcfce90.mp3~tplv-mdko3gqilj-image.image?rk3s=81d4c505&x-expires=1775521513&x-signature=1wzdU%2BAgwe2c5m9LNDPPrui1Wts%3D&x-wf-file_name=%E6%B2%BB%E6%84%88%E7%B3%BB%E5%8A%A8%E6%BC%AB.mp3";if(bg_audio_url && bg_audio_url != '默认'){audio_url = bg_audio_url;}bg_audio_list.push(audio_url);bg_audio_timelines.push({start: 0,end: maxDuration});// 构建输出对象const result = {bg_audio_list: bg_audio_list,bg_autdo_timelines: bg_audio_timelines,video_timelines: video_timelines,video_urls : video_url_list};return result;}
视频下载
-
下载剪映小助手(视频需要用小助手下载),下载地址:https://ts.fyshark.com/#/login?user_id=10299

-
将草稿链接复制到剪映小助手,点击创建草稿

将下载的文件夹复制到剪映草稿文件夹,也可以直接配置下载路径为剪映草稿路径:

打开剪映,查看和导出视频:(需要安装剪映:https://www.capcut.cn/)

本篇文章来源于微信公众号: CodeL
文章评论