节前福利!火柴人心理视频升级版,Coze工作流实例!

大家好,跟着老黄学AI!

最近有小伙伴问高级版的火柴人案例,今天,它来了!

按照惯例,我们先上效果图:

视频主体拆解

1.顶上有左标题,右标题,左标题还有个图标。这些元素我们可以选择作为用户输入,用户没输入,就默认

2.火柴人图片布局为左中右,按照字幕的时间线,轮流出现,而且顶部还有图片的描述。

3.第一期我们用的都是黑白纯色,这次的高级版有彩色的元素在里面。

4.口播的字幕有中英对照

流程设计

1.根据输入的文案或者大模型产生的文案,用大模型进行分镜描述,批量产出图片。

2.处理音频,动画效果、中英翻译字幕、生成背景图

3.小助手插件生成草稿

核心节点拆解

(1)开始节点,为什么开始节点要特意讲解,因为如果我们想这个工作流越灵活,那么给用户自定义使用的输入,就要越多。

(2)大模型_文案生成

参考提示词:

# 角色
心理学知识分享博主,作为心理学知识分享博主,善于通过理论解读和案例分析,帮助读者理解心理现象背后的原理,用通俗易懂的方式呈现心理学的智慧。
你是一个专门制作以火柴人形式呈现心理知识相关视频内容的专家。


## 技能  创作心理学科普文案
-目标:依据用户提供的心理主题方向,创作具有启发性和实用性的的心理科普文章
-文章结构:采用总分结构,开篇引出主题,分段阐述心理学理论与实际应用,结合案例进行说明,结尾总结要点并提供行动建议。
-案例生动呈现:选取贴近生活的案例,从情境描述、心理分析、应对策略等维度展开多角度剖析。
-语言风格:保持专业性和通俗性平衡,关键理论突出解释,专业术语配合括号解释,段落间逻辑清晰。
-论证方式:采用经典心理学理论框架,注重理论与实践结合,避免过度 简化或夸大。
同样的话不要 反复说,不要重复
输出格式:采用合理长短句结构,不需要有数字分段,直接输出文章内容,标题和1个核心关键词。
- 字数300字以内

(3)大模型_分镜描述:

参考提示词:

# 角色
你是一位专业且富有创意的视频分镜描述专家,专注于火柴人风格的心理学视频分镜创作,能够将心理学科普文章转化为生动、形象且符合极简风格要求的视频分镜描述。

## 技能
### 技能 1: 创作视频分镜描述
1. 仔细研读用户提供的心理学科普文章内容,全面理解其中的心理学知识、情节以及人物情绪等关键要素。
2. 按照要求创作心理学视频分镜描述,确保:
    - 字幕文案分段:每个段落均由一句话构成,语句简洁明了,表达清晰流畅,同时具备节奏感。
    - 分镜描述:画面呈现极简风格,清晰直观。画面描述要精准、细致地体现情节细节以及人物情绪等方面。每个人物的描述中都要加上火柴人形象。
    - 字幕文案必须严格按照用户给的文案拆分,不能禁止严禁修改提供的内容
    - 至少8个分镜, 不超过50个分镜
### 技能 2: 生成分镜图像提示词
依据分镜描述,生成对应的[分镜图像提示词],需严格遵循以下要求:
{{llm_prompt}}

(4)背景图_设置:

(5)大模型_中英翻译

参考提示词:

# 角色
你是一位专业的翻译专家,专长于将中文文本精准且流畅地翻译成英文。

## 技能
### 技能 1: 翻译中文内容
1. 当接收到中文内容后,将其准确翻译成英文,要确保译文完整保留原文的意义、语气以及风格, 中文内容在json数组中,需要将数组中的每句中文单独翻译。
2. 在翻译过程中,充分留意中文的语境和文化内涵,让英文表达既忠实于原文,又契合英语习惯。

## 输出要求
1. 翻译后的英文文本务必符合英语语法规范,表达清晰、语句流畅,具备良好的可读性。
2. 准确传达原文的所有信息,杜绝随意添加或删减内容。
3. 若遇到中文习语或具有文化特色的内容,采用符合英语表达习惯的译法,保证信息完整且传达效果良好。

## 注意事项
1. 对于多义词或模糊表达,保证译文明确、连贯且前后一致。
2. 若直译可能产生歧义,则采用意译方法,同时保证原意不变。

(6)动画效果与视频参数组成

(7)调用小助手数据生成器与小助手插件,这个不展开说了,大家可以看看我上一篇文章,有详细介绍。

(8)代码节点

参考代码:

// 在这里,您可以通过 ‘params’  获取节点中的输入变量,并通过 'ret' 输出结果
// 'params' 和 'ret' 已经被正确地注入到环境中
// 下面是一个示例,获取节点输入中参数名为‘input’的值:
// const input = params.input; 
// 下面是一个示例,输出一个包含多种数据类型的 'ret' 对象:
// const ret = { "name": ‘小明’, "hobbies": [“看书”, “旅游”] };
async function main({ params }: Args): Promise<Output> {
    const { image_list, list, audio_list, duration_list, bg_image } = params;

    // 处理音频数据
    const audioData = [];
    let audioStartTime = 0;
    const videoTimelines = [];
    let maxDuration = 0;

    for (let i = 0; i < audio_list.length && i < duration_list.length; i++) {
        const duration = duration_list[i];
        audioData.push({
            audio_url: audio_list[i],
            duration,
            start: audioStartTime,
            end: audioStartTime + duration,
            audio_effect: "教学"
        });
        videoTimelines.push({
            start: audioStartTime,
            end: audioStartTime + duration
        });
        audioStartTime += duration;
        maxDuration = audioStartTime;
    }

    // 处理图片数据
    const imageData = [];
   
    // const imgData = processImageSequence(image_list, duration_list);
    
    // 使用示例
    const scheduler = new AnimationScheduler();

    // 配置为顺序模式
    // configure({
    //     mode: ANIMATION_MODES.SEQUENTIAL,
    //     animationPreset: 'SEQUENCE'
    // });
    
    // // 示例1:创建对称动画布局
    // configure({
    //     mode: ANIMATION_MODES.SYMMETRIC,
    //     animationPreset: 'SYMMETRIC',
    //     symmetricPairing: 'LR', // 左右对称配对
    //     trackWeights: { left: 2, middle: 1, right: 2 } // 增加左右轨道权重
    // });

  
    // 示例3:完全随机模式配置
    // configure({
    //     mode: ANIMATION_MODES.RANDOM,
    //     animationPreset: 'RANDOM',
    //     overlapTolerance: 0.6,      // 允许更多重叠
    //     groupSyncThreshold: 3       // 每5个元素形成一组
    // });

    // // 示例4:自定义顺序模式
    // configure({
    //     mode: ANIMATION_MODES.SEQUENTIAL,
    //     sequentialOrder: ['middle', 'left', 'right'], // 自定义播放顺序
    //     trackWeights: { left: 1, middle: 3, right: 1 } // 中间轨道权重最高
    // });
    const type = params.type;
    if(type == "中心聚焦模式"){
        // 示例2:配置中心聚焦模式
        // configure({
        //     mode: ANIMATION_MODES.CENTER_FOCUS,
        //     animationPreset: 'FOCUS',
        //     durationSettings: {
        //         baseExtension: 800000,  // 扩展800ms
        //         minDuration: 1500000    // 最小1500ms
        //     }
        // });
    }else if(type=="随机模式"){
        // 示例3:完全随机模式配置
        // configure({
        //     mode: ANIMATION_MODES.RANDOM,
        //     animationPreset: 'RANDOM',
        //     overlapTolerance: 0.6,      // 允许更多重叠
        //     groupSyncThreshold: 3       // 每5个元素形成一组
        // });
    } else if(type=="左中右布局模式"){
        // 示例1:创建对称动画布局
        //configure({
        //     mode: ANIMATION_MODES.SYMMETRIC,
        //     animationPreset: 'SYMMETRIC',
        //   symmetricPairing: 'LMR', // 左中右配对
        //   trackWeights: { left: 2, middle: 1, right: 2 } // 增加左右轨道权重
         //});
    } else{
        // 默认顺序模式
    }


    // 处理图片序列
    const imgData = scheduler.process(image_list,duration_list);

   
    // 处理背景图片
    const bgImageData = [
        {
            image_url: bg_image,
            width: 1920,
            height: 1080,
            start: 0,
            end: maxDuration + 600000
        }
    ];

    // 处理字幕数据
    const captions = list.map(item => item.cap);
    const subtitleDurations = duration_list;

    const processedSubtitles = [];
    const processedSubtitleDurations = [];

    for (let i = 0; i < captions.length; i++) {
        const text = captions[i];
        const totalDuration = subtitleDurations[i];

        const subtitles = text.split(/[,。!,!?]/).filter(part => part.trim() !== '');
        const subtitleCount = subtitles.length;

        if (subtitleCount > 0) {
            const perSubtitleDuration = totalDuration / subtitleCount;
            for (let j = 0; j < subtitleCount; j++) {
                processedSubtitles.push(subtitles[j]);
                processedSubtitleDurations.push(perSubtitleDuration);
            }
        } else {
            processedSubtitles.push(text);
            processedSubtitleDurations.push(totalDuration);
        }
    }

    // 处理字幕时间线
    const textTimelines = [];
    let textStartTime = 0;

    for (const duration of processedSubtitleDurations) {
        const endTime = textStartTime + duration;
        textTimelines.push({
            start: textStartTime,
            end: endTime
        });
        textStartTime = endTime;
    }

    
    // 构建输出对象
    const result = {
        audio_list: JSON.stringify(audioData),
        image_list: JSON.stringify(imageData),
        timelines: videoTimelines,
        text_timelines: textTimelines,
        text_cap: processedSubtitles,
        max_time: maxDuration,
        bg_image: JSON.stringify(bgImageData),
        imageDataLeft:JSON.stringify(imgData.left),
        imageDataRight:JSON.stringify(imgData.right),
        imageDataMiddle:JSON.stringify(imgData.middle),
        imgData: imgData
    };

    return result;
}



/*
 * 入场动画预设池
 * 说明:定义不同布局模式下的可用动画类型组合
 * 结构:模式名 -> 轨道位置 -> 可选的动画类型数组
 */
const ANIMATION_PRESETS = {
    // 顺序模式预设:左中右轨道使用不同动画组合
    SEQUENCE: {
        left: ["向右滑动", "放大"],       // 左轨道可选动画
        middle: ["向上滑动", "放大"],     // 中间轨道可选动画
        right: ["向左滑动", "向左转入"]    // 右轨道可选动画
    },
    // 中心聚焦模式预设:中间轨道优先配置
    FOCUS: {
        middle: ["放大", "向上滑动"],     // 中间轨道使用更突出的动画
        left: ["向右滑动", "放大"],
        right: ["向左滑动", "向左转入"]
    },
    // 对称模式预设:左右轨道使用对称动画组合
    SYMMETRIC: {
        left: ["向右滑动", "放大"],
        right: ["向左滑动", "向左转入"],
        middle: ["向上滑动", "放大"],
    },
    // 随机模式预设:所有位置共享动画池
    RANDOM: {
        all: ["向右滑动", "放大", "向下滑动","向左转入"] // 全轨道共用动画池
    }
};

/*
 * 动画模式枚举
 * 说明:定义不同的动画调度策略模式
 */
const ANIMATION_MODES = {
    SEQUENTIAL: 'sequential',    // 顺序模式:按指定顺序播放
    CENTER_FOCUS: 'center',      // 中心聚焦模式:中间元素优先
    SYMMETRIC: 'symmetric',      // 对称模式:左右对称播放
    RANDOM: 'random'             // 随机模式:完全随机选择
};

/*
 * 全局配置参数
 * 示例用法:
 * configure({
 *   mode: ANIMATION_MODES.SYMMETRIC,
 *   animationPreset: 'SYMMETRIC',
 *   trackWeights: { left: 2, middle: 1, right: 2 }
 * })
 */
const CONFIG = {
    mode: ANIMATION_MODES.SEQUENTIAL, // 动画调度模式(默认顺序模式)
    animationPreset: 'SEQUENCE',       // 使用的动画预设名称
    trackWeights: { left: 1, middle: 1, right: 1 }, // 轨道选择权重(中间轨道权重更高)
    overlapTolerance: 1,            // 重叠容忍度(0-1,值越大允许更多重叠)
    groupSyncThreshold: 3,            // 组同步阈值(元素数量达到阈值后同步)
    sequentialOrder: ['left', 'middle', 'right'], // 顺序模式的播放顺序
    symmetricPairing: 'LR',           // 对称模式配对方式(LR: 左右对称 / LMR: 包含中间)
    durationSettings: {               // 时长相关配置
        unit: 1,                      // 时间单位系数(示例:1表示1ms)
        baseExtension: 500000,        // 基础时长扩展(500ms)
        minDuration: 1000000,         // 最小持续时间(1000ms)
        groupRatio: 1.8               // 组时长比例系数
    }
};

// 核心处理器
class AnimationScheduler {
    constructor() {
        this.tracks = { left: [], middle: [], right: [] };
        this.timeWindows = [];
        this.groups = [];
        this.currentGroup = null;
    }

    process(imageList, durationList) {
        imageList.forEach((img, idx) => {
            this._processImage(img, idx, durationList);
        });
        this._postProcess();
        return this._formatOutput();
    }

    _processImage(image, index, durations) {
        const start = this._getStartTime(index, durations);
        const originalDuration = durations[index] * CONFIG.durationSettings.unit;
        
        this._createGroupIfNeeded(index);
        
        const track = this._selectTrack(start, originalDuration);
        const { endTime, groupEnd } = this._calculateTiming(start, originalDuration);
        
        const animation = this._selectAnimation(track);
        const item = this._createItem(image, track, start, endTime, animation);
        
        this._updateState(item, groupEnd);
    }

    _createGroupIfNeeded(index) {
        let shouldCreate = false;
        
        // 顺序模式专用分组逻辑
        if (CONFIG.mode === ANIMATION_MODES.SEQUENTIAL) {
            const groupSize = CONFIG.sequentialOrder.length;
            shouldCreate = (index % groupSize === 0) || (this.groups.length === 0);
        } 
        // 其他模式原有逻辑
        else {
            shouldCreate = 
                index % 3 === 0 || 
                (CONFIG.mode === ANIMATION_MODES.SYMMETRIC && index % 2 === 0) ||
                this.groups.length === 0;
        }

        if (shouldCreate) {
            this.currentGroup = {
                items: [],
                animationType: this._getGroupAnimationType(),
                endTime: 0
            };
            this.groups.push(this.currentGroup);
        }
    }


    _getGroupAnimationType() {
        const preset = ANIMATION_PRESETS[CONFIG.animationPreset];
        switch(CONFIG.mode) {
            case ANIMATION_MODES.SEQUENTIAL:
                return {
                    left: this._randomPick(preset.left),
                    middle: this._randomPick(preset.middle),
                    right: this._randomPick(preset.right)
                };
            case ANIMATION_MODES.CENTER_FOCUS:
                return {
                    middle: this._randomPick(preset.middle),
                    left: this._randomPick(preset.left),
                    right: this._randomPick(preset.right)
                };
            case ANIMATION_MODES.SYMMETRIC:
                return CONFIG.symmetricPairing === 'LR' ? {
                    left: this._randomPick(preset.left),
                    right: this._randomPick(preset.right)
                } : {
                    left: this._randomPick(preset.left),
                    middle: this._randomPick(preset.middle),
                    right: this._randomPick(preset.right)
                };
            case ANIMATION_MODES.RANDOM:
                return { all: this._randomPick(preset.all) };
            default:
                throw new Error('未知动画模式');
        }
    }

    _selectTrack(start, duration) {
        // 新增顺序模式专用处理逻辑
        if (CONFIG.mode === ANIMATION_MODES.SEQUENTIAL) {
            const groupSize = CONFIG.sequentialOrder.length;
            const positionInGroup = this.currentGroup.items.length % groupSize;
            const targetTrack = CONFIG.sequentialOrder[positionInGroup];
            
            // 强制等待机制:如果当前轨道冲突,延迟到下一个可用时间点
            const lastInTrack = [...this.tracks[targetTrack]].pop();
            if (lastInTrack && lastInTrack.end > start) {
                start = lastInTrack.end + 100000; // 增加100ms间隔
            }
            
            return targetTrack;
        }

        // 保留其他模式的原有逻辑
        const candidates = Object.keys(this.tracks).map(track => ({
            track,
            score: this._calculateTrackScore(track, start, start + duration)
        }));
        return candidates.sort((a, b) => b.score - a.score)[0].track;
    }
    _fallbackToOriginalLogic(start, duration) {
        const candidates = Object.keys(this.tracks).map(track => ({
            track,
            score: this._calculateTrackScore(track, start, start + duration)
        }));
        return candidates.sort((a, b) => b.score - a.score)[0].track;
    }

    _calculateTrackScore(track, start, end) {
        const overlapCount = this.tracks[track]
            .filter(item => item.end > start && item.start < end)
            .length;
        
        const recentUsage = this.tracks[track]
            .filter(item => item.end > start - 500000)
            .length;
        
        const weights = {
            availability: overlapCount === 0 ? 400 : 0,
            overlap: -overlapCount * 150,
            recent: -recentUsage * 50,
            configWeight: CONFIG.trackWeights[track] * 200,
            random: Math.random() * 100
        };
        
        return Object.values(weights).reduce((sum, val) => sum + val, 0);
    }

    _calculateTiming(start, originalDuration) {
        const baseEnd = start + originalDuration;
        let endTime = baseEnd + CONFIG.durationSettings.baseExtension;
        
        // 顺序模式强制组同步
        if (CONFIG.mode === ANIMATION_MODES.SEQUENTIAL) {
            // 始终保证最小持续时间
            const minEnd = start + CONFIG.durationSettings.minDuration;
            endTime = Math.max(endTime, minEnd);

            // 动态扩展组持续时间
            if (this.currentGroup.items.length > 0) {
                // 取当前元素需要的结束时间和组现有结束时间的较大者
                endTime = Math.max(endTime, this.currentGroup.endTime);
            }
            
            // 更新组结束时间为当前最大值
            this.currentGroup.endTime = Math.max(this.currentGroup.endTime || 0, endTime);
            endTime = this.currentGroup.endTime;
        } else {
            // 保留原有逻辑
            if (this.currentGroup.items.length > 0) {
                const lastItem = this.currentGroup.items[this.currentGroup.items.length - 1];
                endTime = Math.max(endTime, lastItem.end);
            }
            
            endTime = Math.max(
                endTime,
                start + CONFIG.durationSettings.minDuration
            );
        }
        
        return {
            endTime,
            groupEnd: CONFIG.mode === ANIMATION_MODES.SYMMETRIC ? endTime : null
        };
    }

    _createItem(image, track, start, end, animation) {
        return {
            image_url: image,
            in_animation: animation,
            start: this._adjustTiming(start, track),
            end: this._adjustTiming(end, track),
            width: 1920,
            height: 1080,
            track
        };
    }

    _adjustTiming(time, track) {
        if (CONFIG.mode === ANIMATION_MODES.SYMMETRIC) {
            return track === 'right' ? time + 100000 : time;
        }
        return time;
    }

    _selectAnimation(track) {
        if (CONFIG.mode === ANIMATION_MODES.RANDOM) {
            return this.currentGroup.animationType.all;
        }
        return this.currentGroup.animationType[track];
    }

    _updateState(item, groupEnd) {
        this.tracks[item.track].push(item);
        this.currentGroup.items.push(item);
        
        // 强制同步组内所有元素的结束时间
        this.currentGroup.items.forEach(i => i.end = this.currentGroup.endTime);
        
        this.currentGroup.endTime = Math.max(
            this.currentGroup.endTime, 
            groupEnd || item.end
        );
    }

    _postProcess() {
        this._adjustTrackOverlaps();
        this._balanceDurations();
    }

    _adjustTrackOverlaps() {
        Object.values(this.tracks).forEach(track => {
            track.sort((a, b) => a.start - b.start);
            for (let i = 1; i < track.length; i++) {
                const prev = track[i - 1];
                const curr = track[i];
                if (prev.end > curr.start) {
                    const adjust = (prev.end - curr.start) * CONFIG.overlapTolerance;
                    prev.end -= adjust;
                    curr.start = prev.end;
                }
            }
        });
    }

    _balanceDurations() {
        if (CONFIG.mode === ANIMATION_MODES.CENTER_FOCUS) {
            this.tracks.middle.forEach(item => {
                item.end += 300000; // 延长中间元素
            });
        }
    }

    _getStartTime(index, durations) {
        return index === 0 ? 0 : durations
            .slice(0, index)
            .reduce((sum, dur) => sum + dur * CONFIG.durationSettings.unit, 0);
    }

    _formatOutput() {
        return Object.entries(this.tracks).reduce((acc, [track, items]) => {
            acc[track] = items.map(item => ({
                image_url: item.image_url,
                in_animation: item.in_animation,
                start: item.start,
                end: item.end,
                width: item.width,
                height: item.height
            }));
            return acc;
        }, { left: [], middle: [], right: [] });
    }

    _randomPick(arr) {
        return arr[Math.floor(Math.random() * arr.length)];
    }
}


/*
 * 配置接口函数
 * 用法示例:动态修改配置参数
 * configure({
 *   mode: ANIMATION_MODES.RANDOM,
 *   overlapTolerance: 0.5,
 *   durationSettings: {
 *     minDuration: 2000000 // 设置最小持续时间为2000ms
 *   }
 * })
 */
function configure(options) {
    Object.assign(CONFIG, options);
}

// --------------------------
// 主要配置参数使用示例说明:
// --------------------------

// // 示例1:创建对称动画布局
// configure({
//     mode: ANIMATION_MODES.SYMMETRIC,
//     animationPreset: 'SYMMETRIC',
//     symmetricPairing: 'LR', // 左右对称配对
//     trackWeights: { left: 2, middle: 1, right: 2 } // 增加左右轨道权重
// });

// // 示例2:配置中心聚焦模式
// configure({
//     mode: ANIMATION_MODES.CENTER_FOCUS,
//     animationPreset: 'FOCUS',
//     durationSettings: {
//         baseExtension: 800000,  // 扩展800ms
//         minDuration: 1500000    // 最小1500ms
//     }
// });

// // 示例3:完全随机模式配置
// configure({
//     mode: ANIMATION_MODES.RANDOM,
//     animationPreset: 'RANDOM',
//     overlapTolerance: 0.6,      // 允许更多重叠
//     groupSyncThreshold: 5       // 每5个元素形成一组
// });

// // 示例4:自定义顺序模式
// configure({
//     mode: ANIMATION_MODES.SEQUENTIAL,
//     sequentialOrder: ['middle', 'left', 'right'], // 自定义播放顺序
//     trackWeights: { left: 1, middle: 3, right: 1 } // 中间轨道权重最高
// });

// // 使用示例
// const scheduler = new AnimationScheduler();

// // 配置为中心聚焦模式
// configure({
//     mode: ANIMATION_MODES.CENTER_FOCUS,
//     animationPreset: 'FOCUS'
// });

// // 处理图片序列
// const result = scheduler.process(
//     ['img1.jpg', 'img2.jpg', 'img3.jpg'],
//     [1000, 1500, 1200]
// );

以上就是本期的所有内容!

想要完整工作流、完整代码、提示词的,请关注我的同名小绿书领取

我在Coze商店里面上架了该类视频的两种工作流。目前是免费使用的,大家可以去体验。这里是Coze应用体验链接:https://www.coze.cn/s/4-UQdusJPU0/

<think>好的,我现在要回答用户关于如何使用Coze工具或库进行视频工作流提取的问题。首先,我需要仔细阅读用户提供的引用内容,特别是引用[1]、[3]、[4],因为这些部分提到了Coze工作流的相关应用。 用户的问题主要集中在视频处理,尤其是从视频中提取工作流信息。根据引用[1],VideoTextExtractorWorkflow可以处理多种平台的短视频链接,提取文案内容。这说明Coze有现成的工作流来处理视频转文本的任务。接下来,引用[3]提到使用url2PodcastTwoPerson_demo工作流自动生成播客,这可能涉及视频或音频内容的处理。引用[4]则讨论了如何结合Cursor和Coze工作流开发插件,可能涉及网页内容提取,但用户的问题是关于视频的,所以重点还是在引用[1]和[3]。 用户可能需要的步骤包括访问Coze工作流库,选择合适的工作流(如VideoTextExtractorWorkflow),配置输入参数(视频链接),然后执行工作流获取文本输出。需要确保用户提供的视频链接属于支持的平台,如抖音、快手等。此外,可能需要权限或API密钥,但引用中没有提到,可能需要进一步确认。 还要注意用户提到的“工作流信息”可能指视频中的结构化数据或步骤说明,而不仅仅是文案。如果现有工作流仅提取文案,可能需要定制或调整。但根据现有引用,VideoTextExtractorWorkflow是主要的解决方案,所以应优先推荐。同时,提醒用户参考提供的教程链接(引用[2]和[4])以获取详细步骤,尤其是视频教程可能更直观。 最后,生成相关问题时要围绕Coze的其他工作流应用、处理不同格式的视频、性能优化等,确保问题与用户需求相关,帮助扩展他们的理解。</think>### 如何使用Coze工具进行视频工作流提取 #### 步骤说明 1. **确认视频来源平台** Coze的`VideoTextExtractorWorkflow`支持主流社交平台的短视频链接(如抖音、快手、小红书等)[^1]。确保您的视频链接属于支持的平台。 2. **调用工作流** 在Coze的工作空间中选择资源库,找到对应的工作流(例如`VideoTextExtractorWorkflow`或类似名称的预设流程),点击打开并配置输入参数[^3]。 3. **输入视频链接** 将需要提取文案的视频链接作为输入参数传递给工作流。例如: ```python # 示例代码(需根据实际API调整) workflow_input = {"video_url": "https://example.com/douyin/12345"} ``` 4. **执行工作流** 运行工作流后,系统会自动解析视频内容,提取文本信息。输出结果通常为JSON格式,包含视频标题、字幕、语音转文字等文本内容。 5. **处理输出结果** 根据需求对提取的文本进行后续处理(如关键词提取、摘要生成等)。 #### 技术实现要点 - **依赖Coze API**:需通过Coze提供的接口或SDK调用工作流,确保权限配置正确[^4]。 - **支持格式**:目前主要针对短视频链接,若需处理本地视频文件,可能需要先上传至支持的平台或转换为链接形式。 #### 示例场景 若用户提供抖音视频链接`https://www.douyin.com/12345`,调用工作流后返回: ```json { "title": "如何学习Python", "subtitles": ["第一段:基础语法", "第二段:实战项目"], "speech_text": "大家好,今天讲解Python入门技巧..." } ``` ### 相关问题 1. Coze工作流支持哪些视频平台的内容提取? 2. 如何将本地视频文件通过Coze转换为文本信息? 3. Coze提取视频文案的准确率如何优化? 4. 能否用Coze工作流实现视频内容的多语言翻译?[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老黄学AI

你的鼓励是我创作的最好动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值