
Byted Vod Process Tools
- 11 installs
- 411 repo stars
- Updated August 4, 2026
- bytedance/agentkit-samples
vod-process-tools is a Claude skill that uploads media and submits async Volcengine VOD jobs for video and audio editing, enhancement and AI analysis.
About
vod-process-tools wraps Volcengine VOD audio and video processing. It uploads local or URL media, then submits async VOD jobs for tasks like stitching, trimming, speed change, image-to-video, audio extraction and mixing, denoising, quality enhancement, AI super-resolution, frame interpolation, ASR, OCR, subtitle removal and embedding, scene slicing, matting, highlight extraction, video translation and drama recap. It polls task status and returns generated output links. A developer supplies Volcengine keys and a VOD space name and runs per-task Python scripts.
- Submits async Volcengine VOD jobs for editing, enhancement and AI analysis
- Covers super-resolution, ASR, OCR, subtitle and video-translation tasks
- Uploads media, polls task status and returns output links
Byted Vod Process Tools by the numbers
- 11 all-time installs (skills.sh)
- Ranked #1,049 of 1,335 Generative Media skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
byted-vod-process-tools capabilities & compatibility
Requires Volcengine Access Key, Secret Key and a VOD space name; async VOD jobs incur cloud costs.
- Capabilities
- video processing · super resolution · speech to text · ocr extraction · video translation · subtitle editing
- Use cases
- video generation · transcription · translation
- Pricing
- Bring your own API key
What byted-vod-process-tools says it does
The skill submits async VOD jobs, polls task status, and returns generated output links.
python <SKILL_DIR>/scripts/upload_media.py "<local_file_path_or_http_url>" [space_name]
npx skills add https://github.com/bytedance/agentkit-samples --skill byted-vod-process-toolsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 11 |
|---|---|
| repo stars | ★ 411 |
| Last updated | August 4, 2026 |
| Repository | bytedance/agentkit-samples ↗ |
What it does
Upload media and run async Volcengine VOD jobs for editing, enhancement and AI media analysis.
Who is it for?
Programmatic video and audio processing and AI media analysis via Volcengine VOD.
Skip if: Pure text generation, real-time streaming or source-free generative video creation.
When should I use this skill?
You need VOD-based media processing like stitching, super-resolution, ASR, OCR or translation.
What you get
Async VOD job output links for the processed or analyzed media.
By the numbers
- Over 25 media-processing task types in the decision tree
Files
Volcengine VOD Tools
---
前置条件
- Python:确认
python --version≥ 3.6 - 环境变量(必需,也可通过工作目录下的
.env文件配置,脚本会自动加载): VOLCENGINE_ACCESS_KEY— 火山引擎 Access KeyVOLCENGINE_SECRET_KEY— 火山引擎 Secret KeyVOD_SPACE_NAME— VOD 空间名称- 依赖:脚本依赖
python-dotenv
---
参数传入方式
所有脚本支持两种 JSON 参数传入方式:
1. 内联 JSON(适合简单参数):python script.py '{"key":"value"}' 2. 文件引用(推荐,避免 shell 转义问题):python script.py @params.json
@ 前缀表示从文件读取 JSON 内容,文件路径相对于当前工作目录。
---
结果交付规则
- 提交异步任务成功后会返回异步任务id,字段为
VCCreativeId或TaskId,在给用户交付最终产物时,必须包含异步任务id - 在展示最终产物链接时,禁止随意修改链接内容
- 优先将产物链接提供给用户
---
工作流程
1) 识别输入视频类型(必要时先上传拿 vid://...)
后续所有处理脚本优先使用 VOD 侧资源引用:
- Vid:
vid://vxxxx(或部分脚本接受裸vxxxx并自动补vid://) - DirectUrl / FileName:
directurl://<vod_file_name>(媒体类任务用DirectUrl时会要求FileName + SpaceName)
当用户提供的是以下输入之一,需要先执行上传逻辑,拿到 Vid 后再继续:
- 本地文件路径:如
/path/to/a.mp4 http/https链接:如https://example.com/a.mp4(会走 URL 拉取上传,并轮询上传结果)
统一用 scripts/upload_media.py:
python <SKILL_DIR>/scripts/upload_media.py "<local_file_path_or_http_url>" [space_name]脚本输出中 Source 字段即 vid://...,可直接作为后续处理输入。
安全限制:本地文件上传仅允许 workspace/、userdata/ 和 /tmp 目录下的文件。
2) 识别用户意图 → 选择对应处理脚本
根据用户需求,按以下决策树选择脚本:
| 用户意图 | 脚本 |
|---|---|
| 多个视频/音频合成一个(顺序拼接) | stitching |
| 截取视频/音频的某个时间片段 | clipping |
| 加速/慢放/变速 | speedup |
| 镜像/上下翻转/左右翻转 | flip |
| 多张图片串联生成视频 | image_to_video |
| 替换/叠加视频的背景音乐 | compile |
| 只要视频里的音频轨 | extract_audio |
| 多条音频同时叠加播放(混音) | mix_audios |
| 分离人声和伴奏/背景音 | voice_separation |
| 去除环境噪音/电流杂音/风噪 | noise_reduction |
| 模糊/低画质视频修复(压缩伪影/噪点/划痕) | quality_enhance |
| 低分辨率视频提升(如 720P→1080P) | super_resolution |
| 低帧率视频插帧提升流畅度(如 30fps→60fps) | interlacing |
| 语音识别/ASR/提取视频中的文字对白 | asr_speech_to_text |
| OCR 文字提取/识别视频中的屏幕文字 | ocr_text_extract |
| 擦除视频硬字幕 | subtitle_removal |
| 给视频添加/嵌入字幕(烧录字幕) | add_subtitle |
| 视频场景分割/智能切片 | intelligent_slicing |
| 人像抠图/人像分割 | portrait_matting |
| 绿幕抠像/绿屏抠像 | green_screen |
| AI 漫剧转绘(漫画风/3D卡通风格) | comic_style |
| 短剧高光剪辑/精彩片段提取 | highlight |
| AI 视频翻译(字幕/语音/面容翻译) | video_translation |
| 查询翻译项目状态/重启翻译轮询 | poll_translation |
| 查询翻译项目列表 | list_translation |
| AI 解说视频生成(短剧解说/二创) | drama_recap |
| AI 剧本还原(视频转结构化剧本) | drama_script |
| 查询媒资信息(Vid 详情+播放地址) | get_media_info |
3) 构造参数并执行
视频编辑类
| 脚本 | 用途 | 详细参数 |
|---|---|---|
stitching.py '<json>' | 视频/音频拼接 | references/01-stitching.md |
clipping.py '<json>' | 视频/音频裁剪 | references/02-clipping.md |
flip.py '<json>' | 视频翻转 | references/03-flip.md |
speedup.py video '<json>' | 视频变速 | references/04-speedup.md |
speedup.py audio '<json>' | 音频变速 | references/04-speedup.md |
image_to_video.py '<json>' | 图片转视频 | references/05-image-to-video.md |
compile.py '<json>' | 音视频合成 | references/06-compile.md |
extract_audio.py '<json>' | 提取音轨 | references/07-extract-audio.md |
mix_audios.py '<json>' | 混音 | references/08-mix-audios.md |
媒体处理类
| 脚本 | 用途 | 详细参数 |
|---|---|---|
voice_separation.py '<json>' | 人声分离 | references/10-voice-separation.md |
noise_reduction.py '<json>' | 音频降噪 | references/11-noise-reduction.md |
quality_enhance.py '<json>' | 综合画质修复 | references/12-quality-enhance.md |
super_resolution.py '<json>' | AI 超分辨率 | references/13-super-resolution.md |
interlacing.py '<json>' | 智能补帧 | references/14-interlacing.md |
AI 内容分析类
| 脚本 | 用途 | 详细参数 |
|---|---|---|
asr_speech_to_text.py '<json>' | 语音识别 ASR | references/15-asr-speech-to-text.md |
ocr_text_extract.py '<json>' | OCR 文字提取 | references/16-ocr-text-extract.md |
subtitle_removal.py '<json>' | 硬字幕擦除 | references/17-subtitle-removal.md |
add_subtitle.py '<json>' | 添加嵌入字幕 | references/18-add-subtitle.md |
intelligent_slicing.py '<json>' | 智能场景分割 | references/19-intelligent-slicing.md |
portrait_matting.py '<json>' | 人像抠图 | references/20-portrait-matting.md |
green_screen.py '<json>' | 绿幕抠像 | references/21-green-screen.md |
highlight.py '<json>' | 短剧高光剪辑 | references/23-highlight.md |
get_media_info.py '<json>' | 媒资信息查询 | references/27-get-media-info.md |
AI 内容生成类
| 脚本 | 用途 | 详细参数 |
|---|---|---|
comic_style.py '<json>' | AI 漫剧转绘 | references/22-comic-style.md |
video_translation.py '<json>' | AI 视频翻译 | references/24-video-translation.md |
drama_recap.py '<json>' | AI 解说视频生成 | references/25-drama-recap.md |
drama_script.py '<json>' | AI 剧本还原 | references/26-drama-script.md |
重启轮询
| 脚本 | 用途 |
|---|---|
poll_vcreative.py <task_id> | 重启编辑类任务轮询 |
poll_media.py <task_type> <RunId> | 重启媒体处理类任务轮询 |
poll_translation.py <ProjectId> | 重启翻译任务轮询 |
超时响应中的 resume_hint.command 字段包含可直接复制执行的重启命令。
---
示例
# 本地文件先上传拿到 vid(后续脚本统一用 vid://... 作为输入)
python <SKILL_DIR>/scripts/upload_media.py "/path/to/local.mp4" my_space
# 拼接两个视频,加转场
python <SKILL_DIR>/scripts/stitching.py \
'{"type":"video","videos":["vid://v0001","vid://v0002"],"transitions":["1182359"]}'
# 使用 @file.json 传参(推荐,避免转义问题)
python <SKILL_DIR>/scripts/stitching.py @params.json
# 人声分离(注意 type 首字母大写)
python <SKILL_DIR>/scripts/voice_separation.py '{"type":"Vid","video":"v0310abc"}'
# 超分到 1080P
python <SKILL_DIR>/scripts/super_resolution.py '{"type":"Vid","video":"v0310xyz","Res":"1080p"}'
# ASR 语音识别
python <SKILL_DIR>/scripts/asr_speech_to_text.py '{"type":"Vid","video":"v0310abc"}'
# 短剧高光剪辑
python <SKILL_DIR>/scripts/highlight.py '{"Vids":["v023xxx","v024xxx"]}'
# AI 视频翻译(中文→英文)
python <SKILL_DIR>/scripts/video_translation.py '{"Vid":"v0d225gxxx","SourceLanguage":"zh","TargetLanguage":"en"}'
# AI 漫剧转绘(漫画风 720p)
python <SKILL_DIR>/scripts/comic_style.py '{"Vid":"v0d012xxxx","Style":"漫画风","Resolution":"720p"}'
# AI 解说视频(自动生成解说词)
python <SKILL_DIR>/scripts/drama_recap.py '{"Vids":["v023xxx"],"AutoGenerateRecapText":true}'
# AI 剧本还原
python <SKILL_DIR>/scripts/drama_script.py '{"Vids":["v023xxx","v024xxx"]}'
# 查询媒资信息
python <SKILL_DIR>/scripts/get_media_info.py '{"vids":"v001,v002"}'
# 超时后重启编辑类轮询
python <SKILL_DIR>/scripts/poll_vcreative.py <异步智剪任务ID> my_space
# 超时后重启媒体类轮询
python <SKILL_DIR>/scripts/poll_media.py videSuperResolution run_yyy my_space
# 超时后重启翻译轮询
python <SKILL_DIR>/scripts/poll_translation.py <ProjectId> my_space---
错误输出
所有错误统一格式:{"error": "说明"}
超时输出(含重启指令):
{
"error": "轮询超时(360 次 × 5s),任务仍在处理中",
"resume_hint": {
"description": "任务尚未完成,可用以下命令重启轮询",
"command": "python <SKILL_DIR>/scripts/poll_media.py videSuperResolution run_yyy my_space"
}
}约束
- 调用脚本前必须查看脚本详细参数说明
---
计费说明
仅当用户主动咨询费用或计费规则时,再参考 references/00-billing-instructions.md 中的计费说明,向用户简要说明 byted-vod-process-tools 所依赖的 VOD 资源的计费构成,避免在普通剪辑/处理对话中主动展开计费细节。
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
费用说明
byted-vod-process-tools 作为 Agent-Skill 不收取额外费用。但在通过该 Skill 驱动音视频加工处理的过程中,会调用火山引擎视频点播后端的各项资源。在使用过程中,产生的费用主要由以下三部分组成:
视频/音频拼接 stitching
将多段视频或音频按顺序拼接为一个文件,视频支持转场特效。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | video 或 audio |
videos | list[string] | 视频时必填 | 视频列表,每项格式见下方「文件引用格式」 |
audios | list[string] | 音频时必填 | 音频列表 |
transitions | list[string] | 可选 | 转场效果 ID 列表(仅 video 支持,audio 忽略) |
文件引用格式
vid://v0310xxx— VOD 空间 Viddirecturl://test.mp4— VOD 存储 FileNamehttps://example.com/a.mp4— 公网 URL(直接传字符串)
转场数量少于视频段数 -1 时,自动循环复用。
可用转场效果
| 效果名 | ID |
|---|---|
| 交替出场 | 1182359 |
| 旋转放大 | 1182360 |
| 泛开 | 1182358 |
| 六角形 | 1182365 |
| 故障转换 | 1182367 |
| 飞眼 | 1182368 |
| 梦幻放大 | 1182369 |
| 开门展现 | 1182370 |
| 立方转换 | 1182373 |
| 透镜变换 | 1182374 |
| 晚霞转场 | 1182375 |
| 圆形交替 | 1182378 |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.mp4",
"resolution": "1920x1080",
"duration": 12.5
}
}失败时返回 "Status": "failed_run";轮询超时返回 error + resume_hint。
示例
# 拼接两段视频,加「交替出场」转场
python <SKILL_DIR>/scripts/stitching.py \
'{"type":"video","videos":["vid://v0001","vid://v0002"],"transitions":["1182359"]}'
# 拼接音频(不支持转场)
python <SKILL_DIR>/scripts/stitching.py \
'{"type":"audio","audios":["vid://v0003","vid://v0004"]}'视频/音频裁剪 clipping
按时间段裁剪视频或音频片段。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | video 或 audio |
source | string | ✅ | 源文件,格式:vid://xxx / directurl://xxx / 公网 URL |
start_time | float | ✅ | 裁剪开始时间(秒),支持 2 位小数,默认 0 |
end_time | float | ✅ | 裁剪结束时间(秒),必须 > start_time |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.mp4",
"duration": 20.0
}
}示例
# 裁剪视频 10s~30s 片段
python <SKILL_DIR>/scripts/clipping.py \
'{"type":"video","source":"vid://v0001","start_time":10,"end_time":30}'
# 裁剪音频
python <SKILL_DIR>/scripts/clipping.py \
'{"type":"audio","source":"vid://v0002","start_time":5.5,"end_time":60}'视频翻转 flip
对视频做上下(flip_x)或左右(flip_y)镜像翻转,支持同时开启两个方向。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | vid / directurl / http |
source | string | ✅ | 视频文件标识 |
flip_x | bool | 可选 | true = 上下翻转,默认 false |
flip_y | bool | 可选 | true = 左右翻转,默认 false |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.mp4"
}
}示例
# 左右翻转(镜像)
python <SKILL_DIR>/scripts/flip.py \
'{"type":"vid","source":"v0001","flip_y":true}'
# 同时上下+左右翻转(旋转 180°)
python <SKILL_DIR>/scripts/flip.py \
'{"type":"vid","source":"v0001","flip_x":true,"flip_y":true}'视频变速 / 音频变速 speedup
调整视频或音频的播放速度倍数。
用法
python <SKILL_DIR>/scripts/speedup.py <video|audio> '<json_args>'第一个参数指定媒体类型(video 或 audio),决定使用哪个工作流。
参数(json_args)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | vid / directurl / http |
source | string | ✅ | 文件标识 |
speed | float | 可选 | 速度倍数,范围 0.1~4,默认 1.0 |
speed 参考值
| speed | 效果 |
|---|---|
| 0.25 | 四分之一慢放 |
| 0.5 | 慢放 |
| 1.0 | 原速(默认) |
| 2.0 | 两倍速 |
| 4.0 | 最高四倍速 |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.mp4"
}
}示例
# 视频两倍速
python <SKILL_DIR>/scripts/speedup.py video \
'{"type":"vid","source":"v0001","speed":2.0}'
# 音频 0.5 倍慢放
python <SKILL_DIR>/scripts/speedup.py audio \
'{"type":"vid","source":"v0002","speed":0.5}'图片转视频 image_to_video
将多张图片串联生成视频,支持每张图片设置独立时长、动画效果和转场。
参数
顶层参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
images | list[dict] | ✅ | 图片列表,见下方子字段说明 |
transitions | list[string] | 可选 | 转场效果 ID 列表(与图片数 -1 对应,不足时循环复用) |
images 子字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | vid / directurl / http |
source | string | ✅ | 图片文件标识 |
duration | float | 可选 | 该图片展示时长(秒),默认 3,支持 2 位小数 |
animation_type | string | 可选 | 动画类型:move_up / move_down / move_left / move_right / zoom_in / zoom_out |
animation_in | float | 可选 | 动画开始时间(秒),默认从图片开始 |
animation_out | float | 可选 | 动画结束时间(秒),默认随图片结束 |
可用转场效果
参见 01-stitching.md 中的转场效果列表。
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.mp4"
}
}示例
# 3 张图片转视频,第 2 张放大动画,图片间加「泛开」转场
python <SKILL_DIR>/scripts/image_to_video.py \
'{"images":[
{"type":"http","source":"https://example.com/1.jpg","duration":3},
{"type":"http","source":"https://example.com/2.jpg","duration":4,"animation_type":"zoom_in"},
{"type":"http","source":"https://example.com/3.jpg","duration":3}
],"transitions":["1182358"]}'音视频合成 compile
将独立视频轨和音频轨合并为单一文件,可替换或叠加视频原声。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
video | dict | ✅ | 视频信息:{"type":"vid","source":"v0001"} |
audio | dict | ✅ | 音频信息:{"type":"vid","source":"v0002"} |
is_audio_reserve | bool | 可选 | 是否保留原视频原声,默认 true |
is_video_audio_sync | bool | 可选 | 是否对齐音视频时长,默认 false(不对齐则以较长流为准) |
sync_mode | string | 可选 | 对齐基准(仅 sync=true 时生效):video(默认)/ audio |
sync_method | string | 可选 | 对齐方式(仅 sync=true 时生效):trim(裁剪,默认)/ speed(变速) |
video / audio 子字段
| 字段 | 说明 |
|---|---|
type | vid / directurl / http |
source | 文件标识 |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.mp4"
}
}示例
# 替换视频背景音(不保留原声)
python <SKILL_DIR>/scripts/compile.py \
'{"video":{"type":"vid","source":"v0001"},
"audio":{"type":"vid","source":"v0002"},
"is_audio_reserve":false}'
# 叠加背景音,并以视频时长为准裁剪音频
python <SKILL_DIR>/scripts/compile.py \
'{"video":{"type":"vid","source":"v0001"},
"audio":{"type":"http","source":"https://example.com/bgm.mp3"},
"is_video_audio_sync":true,"sync_mode":"video","sync_method":"trim"}'提取音轨 extract_audio
从视频中分离并导出独立音频文件。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | vid / directurl / http |
source | string | ✅ | 视频文件标识 |
format | string | 可选 | 输出音频格式:m4a(默认)/ mp3 |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.m4a"
}
}示例
# 提取音轨为 mp3
python <SKILL_DIR>/scripts/extract_audio.py \
'{"type":"vid","source":"v0001","format":"mp3"}'混音 mix_audios
将多轨音频混合叠加为一个文件(同时播放,非拼接)。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
audios | list[dict] | ✅ | 音频列表,至少 1 项,每项含 type + source |
audios 子字段
| 字段 | 说明 |
|---|---|
type | vid / directurl / http |
source | 音频文件标识 |
与stitching的区别:mix_audios是多轨叠加(同时响),stitching是顺序拼接(先后响)。
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.m4a"
}
}示例
# 将人声和背景音乐混合
python <SKILL_DIR>/scripts/mix_audios.py \
'{"audios":[
{"type":"vid","source":"v0001"},
{"type":"http","source":"https://example.com/bgm.mp3"}
]}'画中画/水印叠加 add_sub_video
在主视频上叠加子视频或动态水印,支持自定义位置、尺寸和出现时间段。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
video | dict | ✅ | 主视频:{"type":"vid","source":"v0001"} |
sub_video | dict | ✅ | 子视频/水印:{"type":"vid","source":"v0002"} |
sub_options | dict | 可选 | 叠加选项,见下方子字段 |
sub_options 子字段
| 字段 | 类型 | 说明 |
|---|---|---|
height | string | 水印高度,支持百分比(如 "30%")或像素(如 "100") |
width | string | 水印宽度,支持百分比或像素 |
pos_x | string | 水印 X 轴位置(像素,以视频左上角为原点) |
pos_y | string | 水印 Y 轴位置(像素,以视频左上角为原点) |
start_time | float | 水印出现时间(秒) |
end_time | float | 水印消失时间(秒) |
注意:若end_time超过原视频时长,输出视频将以end_time为准,超出部分以黑屏延续。
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.mp4"
}
}示例
# 在视频右下角叠加 logo(宽20%,从第5秒到第15秒)
python <SKILL_DIR>/scripts/add_sub_video.py \
'{"video":{"type":"vid","source":"v0001"},
"sub_video":{"type":"http","source":"https://example.com/logo.mp4"},
"sub_options":{"width":"20%","pos_x":"80%","pos_y":"80%","start_time":5,"end_time":15}}'
# 全程画中画(左上角,固定大小300px宽)
python <SKILL_DIR>/scripts/add_sub_video.py \
'{"video":{"type":"vid","source":"v0001"},
"sub_video":{"type":"vid","source":"v0002"},
"sub_options":{"width":"300","pos_x":"20","pos_y":"20"}}'人声分离 voice_separation
将视频或音频中的人声与背景音乐精确分离,输出两个独立音频文件。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | Vid(视频ID)或 DirectUrl(VOD存储FileName) |
video | string | ✅ | 视频/音频的 Vid 或 FileName |
注意:type首字母大写(Vid/DirectUrl),与编辑类工具不同。
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"SpaceName": "my_space",
"AudioUrls": [
{"DirectUrl": "voice.m4a", "Vid": "", "Type": "voice", "Url": "https://cdn.example.com/voice.m4a"},
{"DirectUrl": "bg.m4a", "Vid": "", "Type": "background", "Url": "https://cdn.example.com/bg.m4a"}
],
"VideoUrls": [],
"Texts": []
}| AudioUrls[].Type | 含义 |
|---|---|
voice | 提取的人声音频 |
background | 提取的背景音乐 |
轮询超时时返回 error + resume_hint,可用其中的 command 重启轮询:
python <SKILL_DIR>/scripts/poll_media.py 'voiceSeparation' '<RunId>' [space_name]示例
# 提交任务并等待结果(一步完成)
python <SKILL_DIR>/scripts/voice_separation.py \
'{"type":"Vid","video":"v0310abc"}'音频降噪 noise_reduction
智能消除环境噪音、电流杂音、风噪等,提升人声清晰度。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | Vid(视频ID)或 DirectUrl(VOD存储FileName) |
audio | string | ✅ | 音频的 Vid 或 FileName |
注意:type首字母大写(Vid/DirectUrl)。
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"SpaceName": "my_space",
"VideoUrls": [
{"FileId": "xxx", "DirectUrl": "output.m4a", "Url": "https://cdn.example.com/output.m4a"}
],
"AudioUrls": [],
"Texts": []
}audioNoiseReduction属于 enhance 类任务,产物在VideoUrls(文件格式为音频,命名沿用 API 字段)。
轮询超时时返回 error + resume_hint,可用其中的 command 重启轮询:
python <SKILL_DIR>/scripts/poll_media.py 'audioNoiseReduction' '<RunId>' [space_name]示例
# 提交降噪任务并等待结果(一步完成)
python <SKILL_DIR>/scripts/noise_reduction.py \
'{"type":"Vid","audio":"v0310abc"}'综合画质修复 quality_enhance
AI 综合修复视频质量:消除压缩伪影、噪点、划痕,提升整体清晰度与色彩表现。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | Vid(视频ID)或 DirectUrl(VOD存储FileName) |
video | string | ✅ | 视频的 Vid 或 FileName |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"SpaceName": "my_space",
"VideoUrls": [
{"FileId": "xxx", "DirectUrl": "output.mp4", "Url": "https://cdn.example.com/output.mp4"}
],
"AudioUrls": [],
"Texts": []
}轮询超时时返回 error + resume_hint,可用其中的 command 重启轮询:
python <SKILL_DIR>/scripts/poll_media.py 'enhanceVideo' '<RunId>' [space_name]示例
# 提交画质修复任务并等待结果(一步完成)
python <SKILL_DIR>/scripts/quality_enhance.py \
'{"type":"Vid","video":"v0310abc"}'AI 超分辨率 super_resolution
AI 智能提升视频分辨率(如 720P → 1080P),同步锐化画面细节。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | Vid 或 DirectUrl |
video | string | ✅ | 视频 Vid 或 FileName |
Res | string | 二选一 | 目标分辨率预设(见下表) |
ResLimit | int | 二选一 | 目标长边/短边最大像素值,范围 [64, 2160] |
`Res` 和 `ResLimit` 不能同时指定,否则返回错误。
Res 可选值
| 值 | 含义 |
|---|---|
240p | 240P |
360p | 360P |
480p | 480P |
540p | 540P |
720p | 720P(HD) |
1080p | 1080P(Full HD) |
2k | 2K |
4k | 4K |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"SpaceName": "my_space",
"VideoUrls": [
{"FileId": "xxx", "DirectUrl": "output.mp4", "Url": "https://cdn.example.com/output.mp4"}
],
"AudioUrls": [],
"Texts": []
}task_type 为videSuperResolution(注意官方拼写:vide非video)。
轮询超时时返回 error + resume_hint,可用其中的 command 重启轮询:
python <SKILL_DIR>/scripts/poll_media.py 'videSuperResolution' '<RunId>' [space_name]示例
# 超分至 1080P
python <SKILL_DIR>/scripts/super_resolution.py \
'{"type":"Vid","video":"v0310abc","Res":"1080p"}'
# 限制长边不超过 1920px
python <SKILL_DIR>/scripts/super_resolution.py \
'{"type":"Vid","video":"v0310abc","ResLimit":1920}'智能补帧 interlacing
用运动补偿算法将低帧率视频(如 24fps/30fps)插帧至高帧率(如 60fps),使运动场景更流畅。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | Vid 或 DirectUrl |
video | string | ✅ | 视频 Vid 或 FileName |
Fps | float | ✅ | 目标帧率(fps),范围 (0, 120] |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"SpaceName": "my_space",
"VideoUrls": [
{"FileId": "xxx", "DirectUrl": "output.mp4", "Url": "https://cdn.example.com/output.mp4"}
],
"AudioUrls": [],
"Texts": []
}轮询超时时返回 error + resume_hint,可用其中的 command 重启轮询:
python <SKILL_DIR>/scripts/poll_media.py 'videoInterlacing' '<RunId>' [space_name]示例
# 将 30fps 视频补帧至 60fps
python <SKILL_DIR>/scripts/interlacing.py \
'{"type":"Vid","video":"v0310abc","Fps":60}'语音转字幕 (ASR) asr_speech_to_text
使用 ASR 技术将视频中的语音内容转换为带时间戳的字幕信息。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | 输入类型:Vid 或 DirectUrl |
video | string | ✅ | 当 type 为 Vid 时为视频 ID;当 type 为 DirectUrl 时为 FileName |
language | string | 可选 | 识别提示语言,不传则自动探测。支持取值见下方 |
language 可选值
| 取值 | 语言 |
|---|---|
cmn-Hans-CN | 简体中文 |
cmn-Hant-CN | 繁体中文 |
eng-US | 英语 |
jpn-JP | 日语 |
kor-KR | 韩语 |
rus-RU | 俄语 |
fra-FR | 法语 |
por-PT | 葡萄牙语 |
spa-ES | 西班牙语 |
vie-VN | 越南语 |
mya-MM | 缅甸语 |
nld-NL | 荷兰语 |
deu-DE | 德语 |
ind-ID | 印尼语 |
ita-IT | 意大利语 |
pol-PL | 波兰语 |
tha-TH | 泰语 |
tur-TR | 土耳其语 |
ara-SA | 阿拉伯语 |
msa-MY | 马来语 |
ron-RO | 罗马尼亚语 |
fil-PH | 菲律宾语 |
hin-IN | 印地语 |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"Texts": [
{
"Start": 0.5,
"End": 3.2,
"Text": "大家好,欢迎收看",
"Speaker": "speaker_0"
}
]
}示例
# 对视频进行中文语音识别
python <SKILL_DIR>/scripts/asr_speech_to_text.py \
'{"type":"Vid","video":"v0310abc","language":"cmn-Hans-CN"}'
# 自动检测语言
python <SKILL_DIR>/scripts/asr_speech_to_text.py \
'{"type":"Vid","video":"v0310abc"}'
# DirectUrl 模式
python <SKILL_DIR>/scripts/asr_speech_to_text.py \
'{"type":"DirectUrl","video":"path/to/file.mp4"}'画面文字提取 (OCR) ocr_text_extract
使用 OCR 技术智能提取视频画面中嵌入的文字信息。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | 输入类型:Vid 或 DirectUrl |
video | string | ✅ | 当 type 为 Vid 时为视频 ID;当 type 为 DirectUrl 时为 FileName |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"Texts": [
{
"Start": 1.0,
"End": 5.5,
"Text": "画面中的文字内容"
}
]
}示例
# 提取视频画面中的文字
python <SKILL_DIR>/scripts/ocr_text_extract.py \
'{"type":"Vid","video":"v0310abc"}'
# DirectUrl 模式
python <SKILL_DIR>/scripts/ocr_text_extract.py \
'{"type":"DirectUrl","video":"path/to/file.mp4"}'硬字幕擦除 subtitle_removal
智能检测并无缝擦除视频画面中已有的硬字幕,保留原始背景。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | 输入类型:Vid 或 DirectUrl |
video | string | ✅ | 当 type 为 Vid 时为视频 ID;当 type 为 DirectUrl 时为 FileName |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"VideoUrls": [
{
"FileId": "xxx",
"DirectUrl": "path/to/output.mp4",
"Url": "https://cdn.example.com/output.mp4"
}
]
}示例
# 擦除视频中的硬字幕
python <SKILL_DIR>/scripts/subtitle_removal.py \
'{"type":"Vid","video":"v0310abc"}'
# DirectUrl 模式
python <SKILL_DIR>/scripts/subtitle_removal.py \
'{"type":"DirectUrl","video":"path/to/file.mp4"}'添加内嵌字幕 add_subtitle
将外部字幕文件(如 SRT 格式)或字幕文本列表烧录到视频画面中,生成带有内嵌字幕的新视频。支持自定义字体、字幕样式和字幕位置。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
video | dict | ✅ | 视频信息,见下方子字段 |
subtitle_url | string | 二选一 | 字幕文件 URL / FileName,支持 SRT、VTT、ASS 等格式。优先级高于 text_list |
text_list | list | 二选一 | 字幕文本列表,见下方子字段 |
subtitle_config | dict | 可选 | 字幕样式配置,见下方子字段 |
video 子字段
| 字段 | 类型 | 说明 |
|---|---|---|
type | string | vid / directurl / http |
source | string | 视频文件信息 |
text_list 子字段
| 字段 | 类型 | 说明 |
|---|---|---|
text | string | 字幕文本 |
start_time | float | 文本开始时间(秒) |
end_time | float | 文本结束时间(秒) |
subtitle_config 子字段
| 字段 | 类型 | 说明 |
|---|---|---|
font_size | int | 字体大小(像素),默认 200 |
font_type | string | 字体 ID,默认 SY_Black(思源黑体) |
font_color | string | 字体颜色,RGBA 格式,默认 #FFFFFFFF(白色) |
background_color | string | 背景颜色,RGBA 格式,默认 #00000000(透明) |
background_border_width | number | 背景边框宽度(像素) |
border_color | string | 描边颜色,RGBA 格式,默认 #00000000 |
border_width | int | 描边宽度(像素),默认 0 |
font_pos_config | dict | 位置配置:width、height、pos_x、pos_y(支持百分比或像素) |
可用字体 ID
| 字体名称 | 字体 ID |
|---|---|
| 思源黑体 | SY_Black |
| 阿里巴巴普惠体 | ALi_PuHui |
| 庞门正道标题体 | PM_ZhengDao |
| 站酷高端黑 | 1187221 |
| 站酷酷黑体 | 1187219 |
| 站酷快乐体 | 1187217 |
| 站酷文艺体 | 1187213 |
| 站酷小薇 LOGO 体 | 1187211 |
| 站酷仓耳渔阳体 | 1187223 |
| 站酷意大利体 | 1187225(不支持中文) |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "success",
"OutputJson": {
"vid": "v0310xxx",
"url": "https://cdn.example.com/output.mp4",
"duration": 60.0
}
}示例
# 通过字幕文件添加字幕
python <SKILL_DIR>/scripts/add_subtitle.py \
'{"video":{"type":"vid","source":"v0001"},"subtitle_url":"directurl://subtitles.srt"}'
# 通过文本列表添加字幕
python <SKILL_DIR>/scripts/add_subtitle.py \
'{"video":{"type":"vid","source":"v0001"},"text_list":[{"text":"你好世界","start_time":0,"end_time":3},{"text":"欢迎观看","start_time":3,"end_time":6}]}'
# 自定义字幕样式
python <SKILL_DIR>/scripts/add_subtitle.py @params.json智能场景切分 intelligent_slicing
基于画面转场和镜头变化,智能将长视频切分为多个逻辑相关的短片段。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | 输入类型:Vid 或 DirectUrl |
video | string | ✅ | 当 type 为 Vid 时为视频 ID;当 type 为 DirectUrl 时为 FileName |
min_duration | float | 可选 | 最小片段时长(秒),默认 2.0 |
threshold | float | 可选 | 场景切分灵敏度阈值,默认 15.0(值越小切分越多) |
返回值
任务自动轮询至终态,成功时返回片段列表(含各片段的起止时间和产物信息):
{
"Status": "Success",
"VideoUrls": [
{
"DirectUrl": "path/to/segment_001.mp4",
"Url": "https://cdn.example.com/segment_001.mp4"
}
]
}示例
# 对视频进行智能场景切分
python <SKILL_DIR>/scripts/intelligent_slicing.py \
'{"type":"Vid","video":"v0310abc"}'
# 自定义切分参数
python <SKILL_DIR>/scripts/intelligent_slicing.py \
'{"type":"Vid","video":"v0310abc","min_duration":5.0,"threshold":10.0}'人像抠图 portrait_matting
自动识别视频中的主要人像并进行高精度抠图,生成带有透明通道的视频素材。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | 输入类型:Vid 或 DirectUrl |
video | string | ✅ | 当 type 为 Vid 时为视频 ID;当 type 为 DirectUrl 时为 FileName |
output_format | string | 可选 | 输出视频封装格式,默认 WEBM,支持 MOV / WEBM |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"VideoUrls": [
{
"FileId": "xxx",
"DirectUrl": "path/to/output.webm",
"Url": "https://cdn.example.com/output.webm"
}
]
}示例
# 人像抠图,输出 WEBM 格式
python <SKILL_DIR>/scripts/portrait_matting.py \
'{"type":"Vid","video":"v0310abc"}'
# 人像抠图,输出 MOV 格式
python <SKILL_DIR>/scripts/portrait_matting.py \
'{"type":"Vid","video":"v0310abc","output_format":"MOV"}'绿幕抠图 green_screen
对绿幕背景视频进行专业级抠图,常用于后期制作与特效合成。
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | ✅ | 输入类型:Vid 或 DirectUrl |
video | string | ✅ | 当 type 为 Vid 时为视频 ID;当 type 为 DirectUrl 时为 FileName |
output_format | string | 可选 | 输出视频封装格式,默认 WEBM,支持 MOV / WEBM |
返回值
任务自动轮询至终态,成功时返回:
{
"Status": "Success",
"VideoUrls": [
{
"FileId": "xxx",
"DirectUrl": "path/to/output.webm",
"Url": "https://cdn.example.com/output.webm"
}
]
}示例
# 绿幕抠图,输出 WEBM 格式
python <SKILL_DIR>/scripts/green_screen.py \
'{"type":"Vid","video":"v0310abc"}'
# 绿幕抠图,输出 MOV 格式
python <SKILL_DIR>/scripts/green_screen.py \
'{"type":"Vid","video":"v0310abc","output_format":"MOV"}'AI 漫剧转绘(Comic Style Transfer)
将短剧/视频转绘为漫画风格或 3D 卡通风格的视频,保留原始音频和剧情。
---
限制
| 项目 | 限制 |
|---|---|
| 视频时长 | ≤ 5 分钟 |
| 音频轨道 | 必须包含音频轨道 |
| 并发数 | 同一账号同一时间仅支持 1 个任务 |
| 处理耗时 | 约 10 分钟 / 1 分钟视频 |
| 内容安全 | 视频需通过内容安全审核 |
---
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
Vid | String | 是 | 视频 ID(上传后获得) |
Resolution | String | 是 | 输出分辨率:480p / 720p / 1080p |
Style | String | 否 | 转绘风格,默认 漫画风。可选:漫画风 / 3D卡通风格 |
---
完整工作流
Step 1 — 获取视频 ID(Vid)
按 SKILL.md「公共前置步骤:媒资上传」完成上传后获取 Vid。如果用户已有 Vid 则跳过。
Step 2 — 提交转绘任务
将参数写入 JSON 文件后执行:
cat > workspace/comic_params.json << 'EOF'
{
"Vid": "<vid>",
"Resolution": "720p",
"Style": "漫画风"
}
EOF
python <SKILL_DIR>/scripts/comic_style.py @workspace/comic_params.json成功输出示例:
{
"Status": "success",
"OutputJson": {
"vid": "v0d012xxxx",
"url": "https://xxx.volcvod.com/xxx.mp4",
"resolution": "720p",
"duration": 120.5,
"filename": "output.mp4"
}
}将 url 返回给用户即可播放/下载转绘后的视频。
Step 3 — 恢复轮询(仅超时时使用)
如果 Step 2 因轮询超时返回 resume_hint,使用以下命令恢复:
python <SKILL_DIR>/scripts/comic_style.py --poll <VCreativeId> [space_name]也可使用通用轮询脚本:
python <SKILL_DIR>/scripts/poll_vcreative.py <VCreativeId> [space_name]---
错误处理
| 错误信息 | 原因 | 处理方式 |
|---|---|---|
| 缺少必填参数 Vid | 未提供视频 ID | 让用户提供 Vid 或先上传视频 |
| 缺少必填参数 Resolution | 未提供输出分辨率 | 让用户选择 480p / 720p / 1080p |
| Style 不合法 | 风格名称不在可选值内 | 提示可选:漫画风 / 3D卡通风格 |
| 视频时长超过限制 | 视频超过 5 分钟 | 建议用户裁剪视频后重试 |
| 提交任务失败 | API 返回错误 | 检查账号权限和并发限制 |
| 轮询超时 | 处理时间较长 | 使用 --poll 恢复轮询 |
---
计费
参考 billing-instructions.md。
短剧高光剪辑(Highlight)
基于大模型的多模态高光提取算法,智能地从短剧正片视频中提取出最精彩的高光片段。可生成单集摘要、剧集集锦、剧集宣传片等不同形式的视频素材,用于广告投放、短剧宣传等各种场景。
---
工作流程
步骤 1:确认视频 ID
用户需提供一个或多个视频 ID(Vid)。如果用户只有本地文件或 URL,按 SKILL.md「公共前置步骤:媒资上传」完成上传后获取 Vid。
步骤 2:提交高光剪辑任务
python <SKILL_DIR>/scripts/highlight.py '<json_args>' [space_name]
python <SKILL_DIR>/scripts/highlight.py @params.json [space_name]脚本提交任务后会自动轮询直到终态(成功/失败),无需额外操作。
步骤 3(可选):恢复轮询
如果任务超时,可使用输出中的 resume_hint.command 恢复:
python <SKILL_DIR>/scripts/poll_media.py highlight <RunId> [space_name]---
限制
- 输入视频至少 1 个,支持多个视频同时提交(如多集短剧),最多不超过30个
- 当前仅支持 Miniseries(短剧)模型
---
参数说明(highlight.py)
| 参数 | 类型 | 必选 | 默认值 | 说明 |
|---|---|---|---|---|
Vids | Array\<String\> | 是 | - | 视频 ID 列表,至少 1 个 |
Model | String | 否 | "Miniseries" | 模型类型(当前仅支持短剧) |
Mode | String | 否 | "StorylineCuts" | 剪辑模式(剧情高光剪辑) |
WithStoryboard | Boolean | 否 | true | 是否生成分镜脚本 |
WithOpeningHook | Boolean | 否 | true | 是否生成开头钩子片段 |
模型(Model)
| 值 | 说明 |
|---|---|
Miniseries | 短剧模型(默认) |
模式(Mode)
| 值 | 说明 |
|---|---|
StorylineCuts | 剧情高光剪辑(默认),按故事线提取高光片段 |
---
示例
单个视频
{
"Vids": ["v02399g10002d6tab1iljht5kim11hp0"]
}多集视频(批量提交)
{
"Vids": [
"v02399g10002d6tab1iljht5kim11hp0",
"v02399g10002qpj9aljht4nmunv9ng",
"v02399g10002qpj9aljhta75lgba20"
]
}完整配置
{
"Vids": [
"v02399g10002d6tab1iljht5kim11hp0",
"v02399g10002qpj9aljht4nmunv9ng"
],
"Model": "Miniseries",
"Mode": "StorylineCuts",
"WithStoryboard": true,
"WithOpeningHook": true
}命令行示例
# 单个视频高光剪辑
python <SKILL_DIR>/scripts/highlight.py '{"Vids":["v02399g10002d6tab1iljht5kim11hp0"]}'
# 多集视频
python <SKILL_DIR>/scripts/highlight.py '{"Vids":["v023xxx","v024xxx","v025xxx"]}' my_space
# 使用文件传参
python <SKILL_DIR>/scripts/highlight.py @params.json my_space
# 恢复超时任务的轮询
python <SKILL_DIR>/scripts/poll_media.py highlight 'lb:5c320217a2b335641293cb39beeb' my_space---
输出
成功时返回:
{
"Status": "Success",
"Code": "",
"SpaceName": "test-doc",
"VideoUrls": [],
"AudioUrls": [],
"Texts": []
}说明:高光剪辑任务的产物通常需要通过视频点播控制台或后续剪辑 API 获取具体的高光片段视频。任务成功表示高光提取已完成。
超时时的恢复指引:
{
"error": "轮询超时(360 次 × 5s),任务仍在处理中",
"resume_hint": {
"description": "任务尚未完成,可用以下命令重启轮询",
"command": "python <SKILL_DIR>/scripts/poll_media.py 'highlight' 'lb:xxx' my_space"
}
}AI 视频翻译(声影智译)
将视频从一种语言翻译为另一种语言,支持文本翻译、语音翻译和面容翻译。
---
工作流程
步骤 1:确认视频 ID
用户需提供视频 ID(Vid)。如果用户只有本地文件或 URL,按 SKILL.md「公共前置步骤:媒资上传」完成上传后获取 Vid。
步骤 2:确认源语言和目标语言(⚠️ 必选,无默认值)
`SourceLanguage` 和 `TargetLanguage` 是必选参数,没有默认值。
如果用户没有明确提供,必须先向用户确认后再调用脚本,不可自行假设或填入默认值。
确认时可向用户展示支持的语言列表:
源语言(SourceLanguage)仅支持:
| 代码 | 语言 |
|---|---|
zh | 中文 |
en | 英文 |
目标语言(TargetLanguage)支持:
| 代码 | 语言 | 代码 | 语言 |
|---|---|---|---|
zh | 中文 | en | 英文 |
ja | 日语 | ko | 韩语 |
de | 德语 | fr | 法语 |
ru | 俄语 | es | 西班牙语 |
pt | 葡萄牙语 | it | 意大利语 |
id | 印尼语 | vi | 越南语 |
th | 泰语 | ar | 阿拉伯语 |
tr | 土耳其语 |
步骤 3:询问翻译内容类型(文本/语音/面容,可多类型自由组合)(⚠️ 必须执行)
每次翻译任务都需要先询问用户要翻译哪些内容类型,并将结果映射到 TranslationTypeList。
可选类型:
| 类型 | TranslationTypeList 中包含的项 | 说明 |
|---|---|---|
| 文本翻译 | SubtitleTranslation | 仅文本翻译 |
| 语音翻译 | VoiceTranslation | 文本 + 语音翻译 |
| 面容翻译 | FacialTranslation | 文本 + 语音 + 面容翻译 |
允许多类型组合(例如:文本 + 语音、文本 + 语音 + 面容等)。
注:在当前实现中,只要选择了 VoiceTranslation 或 FacialTranslation,SubtitleTranslation 将会一并开启。
说明:脚本参数中的 TranslationTypeList 支持以下常见组合:>
- ["SubtitleTranslation"]:仅文本翻译- ["SubtitleTranslation","VoiceTranslation"]:文本 + 语音翻译- ["SubtitleTranslation","VoiceTranslation","FacialTranslation"]:文本 + 语音 + 面容翻译(默认)用户明确选择后,将 TranslationTypeList 设置为对应的组合。
步骤 4:确认是否擦除原字幕(⚠️ 必须询问)
每次翻译任务都必须询问用户是否需要擦除原视频中的字幕,不得跳过此步骤或自行假设。
询问时必须附带以下收费提示:
是否需要擦除原视频中的字幕?
>
⚠️ 字幕擦除为收费功能,按实际输出视频时长计费,具体价格请参考 视频 AI 应用计费。
>
- 是:擦除原字幕(IsEraseSource: true)- 否:保留原字幕(IsEraseSource: false,默认)用户明确回复后,将 IsEraseSource 设置为对应值。
步骤 5:提交翻译任务
python <SKILL_DIR>/scripts/video_translation.py '<json_args>' [space_name]
python <SKILL_DIR>/scripts/video_translation.py @params.json [space_name]脚本提交任务后会自动轮询直到终态(成功/失败/暂停),无需额外操作。
步骤 6(可选):管理翻译任务
翻译任务可能耗时较长,以下场景可使用对应脚本:
| 场景 | 命令 |
|---|---|
| 查看翻译任务列表 | python <SKILL_DIR>/scripts/list_translation.py [space_name] ['<options_json>'] |
| 查看指定项目详情 / 重启轮询 | python <SKILL_DIR>/scripts/poll_translation.py <ProjectId> [space_name] |
| 超时后恢复 | 直接复制输出中 resume_hint.command 的命令执行 |
---
限制
- 视频时长:不超过 10 分钟(600 秒),超限将被自动拒绝
- `SourceLanguage` 和 `TargetLanguage`:必选,无默认值,必须由用户明确指定
- `TranslationTypeList`:必须询问用户翻译类型组合(文本/语音/面容,可多选)
- `IsEraseSource`:必须每次询问用户确认,并提示字幕擦除为收费功能
---
参数说明(video_translation.py)
| 参数 | 类型 | 必选 | 默认值 | 说明 |
|---|---|---|---|---|
Vid | String | 是 | - | 视频 ID |
SourceLanguage | String | 是 | - | 源语言,必须由用户明确指定 |
TargetLanguage | String | 是 | - | 目标语言,必须由用户明确指定 |
SpaceName | String | 否 | 环境变量/命令行 | 点播空间名 |
TranslationTypeList | Array | 询问 | 全部三种 | 翻译类型组合(见下表) |
RecognitionType | String | 否 | "OCR" | 字幕识别方式(见下表) |
IsVision | Boolean | 否 | false | 是否开启视频理解 |
IsHardSubtitle | Boolean | 否 | true | 是否硬字幕 |
FontSize | Integer | 否 | 30 | 硬字幕字体大小(1-80) |
IsEraseSource | Boolean | 询问 | false | 是否擦除原字幕,必须询问用户确认(收费功能) |
MarginL | Double | 否 | 0.1 | 左边距比例(0-1) |
MarginR | Double | 否 | 0.09 | 右边距比例(0-1) |
MarginV | Double | 否 | 0.12 | 底部边距比例(0-1) |
ShowLines | Integer | 否 | 0 | 最多显示行数,0 不限 |
TermbaseConfig | Object | 否 | - | 术语库配置 |
ProcessConfig | Object | 否 | - | 流程控制配置(如暂停阶段) |
VoiceCloneConfig | Object | 否 | - | 声音克隆配置 |
翻译类型组合(TranslationTypeList)
| 组合 | 说明 |
|---|---|
["SubtitleTranslation"] | 仅文本翻译 |
["SubtitleTranslation","VoiceTranslation"] | 文本 + 语音翻译 |
["SubtitleTranslation","VoiceTranslation","FacialTranslation"] | 文本 + 语音 + 面容翻译(默认) |
字幕识别方式(RecognitionType)
| 值 | 说明 |
|---|---|
OCR | 从视频画面识别字幕(默认) |
ASR | 从音轨识别字幕 |
SourceSubtitleFile | 使用用户提供的源语言字幕文件 |
SourceAndTargetSubtitleFile | 使用用户提供的源/目标语言字幕文件 |
BilingualSubtitleFile | 使用用户提供的双语字幕文件 |
---
参数说明(list_translation.py)
python <SKILL_DIR>/scripts/list_translation.py [space_name] ['<options_json>']| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
PageNumber | Integer | 1 | 页码 |
PageSize | Integer | 10 | 每页数量 |
StatusFilter | String | - | 状态过滤(逗号分隔),如 "InProcessing,ProcessSucceed" |
ProjectIdOrTitleFilter | String | - | 按项目 ID 或名称过滤 |
翻译项目状态
| 状态 | 说明 |
|---|---|
InProcessing | 处理中 |
ProcessSuspended | 处理暂停(等待人工干预) |
ProcessSucceed | 处理完成 |
ProcessFailed | 处理失败 |
InExporting | 导出中 |
ExportSucceed | 导出完成 |
ExportFailed | 导出失败 |
---
示例
最简调用(必须包含 Vid + 源语言 + 目标语言)
{
"Vid": "v0d225g10002d6tab1iljhtf5buiu8v0",
"SourceLanguage": "zh",
"TargetLanguage": "es"
}指定翻译类型 + 擦除原字幕
{
"Vid": "v0d225g10002d6tab1iljhtf5buiu8v0",
"SourceLanguage": "zh",
"TargetLanguage": "ja",
"TranslationTypeList": ["SubtitleTranslation", "VoiceTranslation"],
"IsEraseSource": true
}完整配置
{
"SpaceName": "my_space",
"Vid": "v0d225g10002d6tab1iljhtf5buiu8v0",
"SourceLanguage": "zh",
"TargetLanguage": "es",
"TranslationTypeList": [
"SubtitleTranslation",
"VoiceTranslation",
"FacialTranslation"
],
"RecognitionType": "OCR",
"IsVision": false,
"IsHardSubtitle": true,
"FontSize": 30,
"IsEraseSource": false,
"MarginL": 0.1,
"MarginR": 0.09,
"MarginV": 0.12,
"ShowLines": 0
}命令行完整示例
# 提交翻译任务
python <SKILL_DIR>/scripts/video_translation.py '{"Vid":"v0d225g10002d6tab1iljhtf5buiu8v0","SourceLanguage":"zh","TargetLanguage":"es"}'
# 使用文件传参
python <SKILL_DIR>/scripts/video_translation.py @params.json my_space
# 查看所有翻译任务
python <SKILL_DIR>/scripts/list_translation.py my_space
# 过滤已完成的任务
python <SKILL_DIR>/scripts/list_translation.py my_space '{"StatusFilter":"ProcessSucceed"}'
# 查看项目详情 / 恢复轮询
python <SKILL_DIR>/scripts/poll_translation.py 684038d6b71c9005b266fefe my_space---
输出
成功时返回:
{
"Status": "ProcessSucceed",
"ProjectId": "684038d6b71c9005b266fefe",
"ProjectVersion": "01c4fa5da48a588a46f81e282b100",
"InputVideo": {
"Title": "example.mp4",
"Vid": "v0d225g10002d6tab1iljhtf5buiu8v0",
"Url": "https://...",
"Duration": 120.5
},
"OutputVideo": {
"Vid": "v0299fg4d103gsqljht10tatbreg",
"Url": "https://...",
"FileName": "video.mp4",
"Duration": 120.5
}
}语言缺失时的错误:
{"error": "必须提供 SourceLanguage(源语言)。支持的源语言: en(英文), zh(中文)。请让用户明确指定源语言后重试。"}超时时的恢复指引:
{
"error": "轮询超时(360 次 × 5s),翻译任务仍在处理中",
"ProjectId": "684038d6b71c9005b266fefe",
"resume_hint": {
"description": "任务尚未完成,可用以下命令重启轮询",
"command": "python <SKILL_DIR>/scripts/poll_translation.py '684038d6b71c9005b266fefe' my_space"
}
}AI 解说视频生成(Drama Recap)
基于大模型视频理解,根据原视频智能生成带有 AI 配音和解说字幕的"二创"解说视频。支持自定义解说词或 AI 自动生成,可配置音色、语速、解说风格、字幕样式以及短剧三要素模板。
---
工作流程
步骤 1:确认视频 ID
用户需提供一个或多个视频 ID(Vid)。如果用户只有本地文件或 URL,按 SKILL.md「公共前置步骤:媒资上传」完成上传后获取 Vid。
也支持传入已完成的剧本还原任务 ID(DramaScriptTaskId),此时无需再提供 Vids。
步骤 2:确认解说词来源(⚠️ 二选一)
| 模式 | 参数设置 | 说明 |
|---|---|---|
| 用户提供解说词 | RecapText = "解说文案" | 默认模式,必须提供 RecapText |
| AI 自动生成 | AutoGenerateRecapText = true | AI 根据视频内容自动创作,不可同时设置 RecapText |
如果用户没有明确提供解说词且未要求 AI 自动生成,需向用户确认选择哪种模式。
步骤 3:提交解说视频生成任务
python <SKILL_DIR>/scripts/drama_recap.py '<json_args>' [space_name]
python <SKILL_DIR>/scripts/drama_recap.py @params.json [space_name]脚本提交任务后会自动轮询直到终态(成功/失败/超时),无需额外操作。
步骤 4(可选):恢复轮询
如果任务超时,可使用输出中的 resume_hint.command 恢复:
python <SKILL_DIR>/scripts/drama_recap.py --poll <TaskId> [space_name]---
限制
- 所有视频总时长不超过 90 分钟(约 45 集短剧)
- 视频分辨率需保持一致
- 视频必须包含硬字幕(内嵌字幕)
- 不支持 HLS / M3U8 格式
- 不支持挂载在对象存储桶中的视频
- 需白名单开通,使用前需联系火山引擎技术支持
---
参数说明(drama_recap.py)
视频输入(二选一)
| 参数 | 类型 | 必选 | 说明 |
|---|---|---|---|
Vids | Array\<String\> | 与 DramaScriptTaskId 二选一 | 视频 ID 列表 |
DramaScriptTaskId | String | 与 Vids 二选一 | 已完成的剧本还原任务 ID |
解说词
| 参数 | 类型 | 必选 | 默认值 | 说明 |
|---|---|---|---|---|
RecapText | String | 条件必选 | - | 自定义解说词(AutoGenerateRecapText=false 时必填) |
AutoGenerateRecapText | Boolean | 否 | false | 是否 AI 自动生成解说词 |
RecapStyle | String | 否 | - | AI 解说风格关键词,如"搞笑""悬疑",≤500 字符 |
RecapTextSpeed | Double | 否 | 1.0 | 解说语速 [0.5, 2.0],推荐 1.2 |
RecapTextLength | Integer | 否 | - | AI 生成解说词长度(字符数),≤5000 |
PauseTime | Integer | 否 | 120 | 句间停顿(毫秒)[1, 1000] |
AllowRepeatMatch | Boolean | 否 | false | 是否允许匹配重复画面 |
音色
| 参数 | 类型 | 必选 | 默认值 | 说明 |
|---|---|---|---|---|
VoiceType | String | 否 | "Yunxi" | 音色名称(见下方预置音色列表) |
AppId | String | 否 | - | 豆包语音 App ID(使用高级音色时) |
预置音色:Yunxi(默认)、Yunjian、Yunfeng、Yunyi、Yunjie、Yunze、Yunye、Xiaoxiao、Xiaochen、Xiaohan、Xiaomo
其他
| 参数 | 类型 | 必选 | 默认值 | 说明 |
|---|---|---|---|---|
IsEraseSubtitle | Boolean | 否 | false | 是否擦除原视频字幕 |
BatchGenerateCount | Integer | 否 | 1 | 批量生成数量,最大 100 |
FontConfig | Object | 否 | - | 字幕样式配置(字体、位置、颜色等) |
MiniseriesEdit | Object | 否 | - | 短剧三要素配置(见下方) |
短剧三要素(MiniseriesEdit)
仅适用于竖屏短剧,一键添加剧名、角标、提示语。
| 参数 | 类型 | 说明 |
|---|---|---|
Template | String | 模板名称:热门短剧1 \~ 热门短剧5 |
Title | String | 短剧名称(≤15 字) |
Hint | String | 提示语(≤20 字),如"影视效果 请勿模仿" |
字幕样式(FontConfig)
| 参数 | 类型 | 说明 |
|---|---|---|
NoSubtitle | Boolean | 是否不添加字幕,默认 false |
FontSize | Integer | 字体大小(pixel) |
FontColor | String | 字体颜色(RGBA),如 "#FFCC66FF" |
BorderColor | String | 描边颜色(RGBA) |
BorderWidth | Integer | 描边宽度(pixel) |
BackgroundColor | String | 字幕背景色(RGBA) |
PosX / PosY | Integer | 字幕区域左上角坐标 |
Width / Height | Integer | 字幕区域尺寸 |
Alpha | Double | 透明度 [0,1] |
AlignType | Integer | 对齐方式(0=左, 1=居中, 2=右) |
Typesetting | Integer | 排列方向(0=横排, 1=竖排) |
---
示例
最简调用(用户提供解说词)
{
"Vids": ["v02b69g10000example"],
"RecapText": "这是一部关于都市爱情的短剧,讲述了两位年轻人相遇相知相爱的故事。"
}AI 自动生成解说词
{
"Vids": ["v02b69g10000example1", "v02b69g10000example2"],
"AutoGenerateRecapText": true,
"RecapStyle": "搞笑",
"RecapTextSpeed": 1.2,
"RecapTextLength": 800
}基于已有剧本还原结果
{
"DramaScriptTaskId": "v02bbbg1006xxx",
"AutoGenerateRecapText": true,
"RecapStyle": "悬疑"
}完整配置
{
"Vids": ["v02b69g10000example"],
"RecapText": "自定义解说词文本...",
"VoiceType": "Xiaoxiao",
"IsEraseSubtitle": true,
"RecapTextSpeed": 1.3,
"PauseTime": 200,
"BatchGenerateCount": 3,
"FontConfig": {
"FontSize": 60,
"FontColor": "#FFFFFFFF",
"BorderColor": "#000000FF",
"BorderWidth": 2
},
"MiniseriesEdit": {
"Template": "热门短剧1",
"Title": "《都市爱情》",
"Hint": "影视效果 请勿模仿"
}
}命令行示例
# 用户提供解说词
python <SKILL_DIR>/scripts/drama_recap.py '{"Vids":["v02b69g10000example"],"RecapText":"解说文案..."}'
# AI 自动生成
python <SKILL_DIR>/scripts/drama_recap.py '{"Vids":["v023xxx"],"AutoGenerateRecapText":true,"RecapStyle":"搞笑"}' my_space
# 使用文件传参
python <SKILL_DIR>/scripts/drama_recap.py @params.json my_space
# 恢复超时任务的轮询
python <SKILL_DIR>/scripts/drama_recap.py --poll 'v02bbbg1006xxx' my_space---
输出
成功时(单个视频):
{
"Status": "success",
"TaskId": "v02bbbg10064d3kbdminbj659kvikr10",
"SpaceName": "my_space",
"Vid": "v02b69g10000example"
}成功时(批量生成):
{
"Status": "success",
"TaskId": "v02bbbg10064d3kbdminbj659kvikr10",
"SpaceName": "my_space",
"MultipleResult": {
"TotalCount": 3,
"SuccessItems": [
{"Vid": "v02b69g10000out1", "Index": 1},
{"Vid": "v02b69g10000out2", "Index": 2}
],
"FailedItems": [
{"Index": 3, "BizCode": 500130}
]
}
}超时时的恢复指引:
{
"error": "轮询超时(360 次 × 5s),任务仍在处理中",
"TaskId": "v02bbbg1006xxx",
"resume_hint": {
"description": "任务尚未完成,可用以下命令重启轮询",
"command": "python <SKILL_DIR>/scripts/drama_recap.py --poll 'v02bbbg1006xxx' my_space"
}
}AI 剧本还原(Drama Script Restoration)
基于大模型视频理解,将剧情类视频转化为结构化剧本文本。精准识别并提取视频中的场景、人物(角色)、对话、情节等核心元素,为内容创作者和数据分析师提供高价值的文本素材。
---
工作流程
步骤 1:确认视频 ID
用户需提供一个或多个视频 ID(Vid)。如果用户只有本地文件或 URL,按 SKILL.md「公共前置步骤:媒资上传」完成上传后获取 Vid。
步骤 2:提交剧本还原任务
python <SKILL_DIR>/scripts/drama_script.py '<json_args>' [space_name]
python <SKILL_DIR>/scripts/drama_script.py @params.json [space_name]脚本提交任务后会自动轮询直到终态(成功/失败/超时),无需额外操作。
步骤 3(可选):恢复轮询
如果任务超时,可使用输出中的 resume_hint.command 恢复:
python <SKILL_DIR>/scripts/drama_script.py --poll <TaskId> [space_name]步骤 4:交付结果
任务成功后,返回的 ResultUrl 是一个 .json.gz 压缩文件的下载链接(有效期 24 小时),包含完整的结构化剧本信息(场景、人物、对话、情节等)。
⚠️ 结果交付规则:直接将 ResultUrl 下载链接提供给用户即可,不需要下载或解压这个 JSON 文件。向用户展示时说明:
剧本还原完成,以下是结构化剧本的下载链接(.json.gz 格式,有效期 24 小时):>
下载链接:<ResultUrl>>
下载后使用 gzip 解压即可获得结构化剧本 JSON 文件。
---
限制
- 所有视频总时长不超过 300 分钟
- 视频分辨率需保持一致(不可混合不同分辨率的视频)
- 视频必须包含硬字幕(内嵌字幕),纯画面无字幕视频不支持
- 不支持 HLS / M3U8 格式的视频
- ResultUrl 有效期 24 小时,过期需重新提交任务
---
参数说明(drama_script.py)
| 参数 | 类型 | 必选 | 默认值 | 说明 |
|---|---|---|---|---|
Vids | Array\<String\> | 是 | - | 视频 ID 列表,至少 1 个 |
ClientToken | String | 否 | 自动生成 UUID | 幂等 token,相同 token 不会重复创建任务 |
---
示例
单个视频
{
"Vids": ["v02399g10002d6tab1iljht5kim11hp0"]
}多个视频(同一部剧的多集)
{
"Vids": [
"v02399g10002d6tab1iljht5kim11hp0",
"v02399g10002qpj9aljht4nmunv9ng",
"v02399g10002qpj9aljhta75lgba20"
]
}指定幂等 token
{
"Vids": ["v02399g10002d6tab1iljht5kim11hp0"],
"ClientToken": "my-unique-request-id-001"
}命令行示例
# 单个视频剧本还原
python <SKILL_DIR>/scripts/drama_script.py '{"Vids":["v02399g10002d6tab1iljht5kim11hp0"]}'
# 多个视频
python <SKILL_DIR>/scripts/drama_script.py '{"Vids":["v023xxx","v024xxx","v025xxx"]}' my_space
# 使用文件传参
python <SKILL_DIR>/scripts/drama_script.py @params.json my_space
# 恢复超时任务的轮询
python <SKILL_DIR>/scripts/drama_script.py --poll 'task_abc123' my_space---
输出
成功时返回:
{
"Status": "success",
"TaskId": "task_abc123",
"SpaceName": "my_space",
"ResultUrl": "https://example.com/result.json.gz",
"note": "ResultUrl 是一个 .json.gz 压缩文件的下载链接(有效期 24 小时)。直接将此链接提供给用户,不需要下载或解压。"
}⚠️ 重要:收到ResultUrl后,直接将链接交付给用户。禁止执行curl、wget等命令下载该文件,也禁止执行gunzip、zcat等命令解压该文件。
失败时返回:
{
"Status": "failed",
"TaskId": "task_abc123",
"SpaceName": "my_space",
"detail": { "Status": "failed" },
"note": "任务失败,请检查输入视频是否满足限制条件后重新提交。"
}超时时的恢复指引:
{
"error": "轮询超时(360 次 × 5s),任务仍在处理中",
"TaskId": "task_abc123",
"resume_hint": {
"description": "任务尚未完成,可用以下命令重启轮询",
"command": "python <SKILL_DIR>/scripts/drama_script.py --poll 'task_abc123' my_space"
}
}27 - 获取媒资信息
功能
通过 Vid(视频 ID)获取媒资信息,包含基础信息、片源信息及播放地址。支持批量查询,超过 20 个 Vid 时自动分批请求。
脚本
python <SKILL_DIR>/scripts/get_media_info.py '{"vids":"v001,v002,v003"}'
python <SKILL_DIR>/scripts/get_media_info.py @params.json参数
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
vids | string 或 array | 是 | Vid 列表。字符串时用逗号分隔;数组时直接传入。无数量上限,超过 20 个自动分批请求 |
返回示例
{
"MediaInfoList": [
{
"Vid": "v02b69g10000xxxxx",
"Title": "示例视频",
"SpaceName": "my_space",
"PublishStatus": "Published",
"CreateTime": "2025-12-28T08:57:58Z",
"Source": {
"Format": "MP4",
"Duration": 120.5,
"Width": 1920,
"Height": 1080,
"Size": 52428800,
"Codec": "h264",
"Fps": 30.0,
"FileName": "088ecee226xxx.mp4"
},
"PlayUrl": "https://cdn.example.com/xxx/video.mp4?auth=xxx"
}
],
"NotExistVids": ["v_not_found"]
}说明
- 底层调用
GetMediaInfos接口,单次最多查询 20 个 Vid。当传入 Vid 超过 20 个时,脚本自动分批发送请求并合并结果。 - 播放地址获取优先使用 CDN 域名 + URL 鉴权,若视频未发布会自动执行发布操作后获取 Origin 地址。
NotExistVids字段仅在存在无效 Vid 时返回。
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
add_subtitle.py — 添加内嵌字幕
用法:
python <SKILL_DIR>/scripts/add_subtitle.py '<json_args>'
python <SKILL_DIR>/scripts/add_subtitle.py @params.json
json_args 字段见 references/18-add-subtitle.md
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import init_and_parse, fmt_src, out, bail
def main():
client, sp, args = init_and_parse()
# ── 视频参数 ──
video = args.get("video")
if not video:
bail("add_subtitle: video 不能为空")
vt = video.get("type", "vid")
vs = video.get("source", "")
formatted_video = fmt_src(vt, vs) if vt in ("vid", "directurl") else vs
# ── 字幕来源(二选一,subtitle_url 优先) ──
subtitle_url = args.get("subtitle_url")
text_list = args.get("text_list")
if not subtitle_url and not text_list:
bail("add_subtitle: 必须指定 subtitle_url 或 text_list 中的一个")
param_obj = {
"space_name": sp,
"video": formatted_video,
}
if subtitle_url:
param_obj["subtitle_url"] = subtitle_url
elif text_list:
param_obj["text_list"] = text_list
# ── 字幕样式配置(可选) ──
subtitle_config = args.get("subtitle_config")
if subtitle_config:
param_obj["subtitle_config"] = subtitle_config
out(client.submit_vcreative("loki://168214785", param_obj, sp))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
asr_speech_to_text.py — 语音转字幕 (ASR)
用法:
python <SKILL_DIR>/scripts/asr_speech_to_text.py '<json_args>'
python <SKILL_DIR>/scripts/asr_speech_to_text.py @params.json
json_args 字段见 references/15-asr-speech-to-text.md
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import init_and_parse, build_media_input, out, bail
def main():
client, sp, args = init_and_parse()
t = args.get("type", "Vid")
video = args.get("video")
if not video:
bail("asr_speech_to_text: video 不能为空")
asr_config = {"WithSpeakerInfo": True}
language = args.get("language")
if language:
asr_config["Language"] = language
params = {
"Input": build_media_input(t, video, sp),
"Operation": {
"Type": "Task",
"Task": {
"Type": "Asr",
"Asr": asr_config,
},
},
}
out(client.submit_media(params, "asr", sp))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
clipping.py — 视频/音频裁剪
用法:
python <SKILL_DIR>/scripts/clipping.py '<json_args>'
python <SKILL_DIR>/scripts/clipping.py @params.json
json_args 字段见 references/02-clipping.md
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import init_and_parse, fmt_src, out, bail
def main():
client, sp, args = init_and_parse()
t = args.get("type", "video")
source = args.get("source")
if not source:
bail("clipping: source 不能为空")
start = float(args.get("start_time", 0))
end = float(args.get("end_time", start + 1))
if end <= start:
bail("clipping: end_time 必须大于 start_time")
param_obj = {
"space_name": sp,
"source": fmt_src(t, source),
"start_time": start,
"end_time": end,
}
wf = "loki://158666752" if t == "audio" else "loki://154419276"
out(client.submit_vcreative(wf, param_obj, sp))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
comic_style.py — AI 漫剧转绘(Comic Style Transfer)
使用 AsyncVCreativeTask(Scene=videostyletrans)提交转绘任务,
通过 GetVCreativeTaskResult 轮询到终态。
用法:
# 直接执行(提交 + 自动轮询)
python <SKILL_DIR>/scripts/comic_style.py @params.json
# 恢复轮询已提交的任务
python <SKILL_DIR>/scripts/comic_style.py --poll <VCreativeId> [space_name]
params.json 示例:
{
"Vid": "v0d012xxxx",
"Style": "漫画风",
"Resolution": "720p"
}
参数说明:
Vid (必填) 视频 ID,也可传入 vid://xxx 格式
Style (选填) 转绘风格,默认 "漫画风"。可选:"漫画风" | "3D卡通风格"
Resolution (必填) 输出分辨率:"480p" | "720p" | "1080p"
"""
import sys
import os
import json
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import (
init_and_parse,
get_space_name,
out,
bail,
log,
)
from api_manage import ApiManage
from vod_api_constants import (
VOD_ACTION_SUBMIT_ASYNC_AI_CLIP,
VOD_FIELD_AI_CLIP_TASK_ID,
)
# ── 限制 ────────────────────────────────────────────
MAX_DURATION_SEC = 300 # 视频时长 ≤ 5 分钟
VALID_STYLES = {"漫画风", "3D卡通风格"}
VALID_RESOLUTIONS = {"480p", "720p", "1080p"}
def get_duration(api: ApiManage, vid: str, space_name: str) -> float:
"""通过 GetMediaInfos 获取视频时长(秒)。"""
raw = api.get_media_infos(vid, space_name)
result = raw.get("Result", raw)
info_list = result.get("MediaInfoList", [])
if not info_list:
bail(f"未找到 Vid={vid} 的媒资信息,请确认 Vid 及空间名称")
basic = info_list[0].get("BasicInfo", {})
duration = basic.get("Duration", 0)
return float(duration)
def submit_comic_style(
api: ApiManage, vid: str, style: str, resolution: str, space_name: str
) -> dict:
"""提交 AsyncVCreativeTask (Scene=videostyletrans) 并自动轮询。"""
# 构建 vid:// 格式输入
vid_input = vid if vid.startswith("vid://") else f"vid://{vid}"
param_obj = {
"input": vid_input,
"style": style,
"resolution": resolution,
}
payload = {
"Uploader": space_name,
"Scene": "videostyletrans",
# ParamObj 需要是对象而不是字符串
"ParamObj": param_obj,
}
log(f"提交漫剧转绘任务:Vid={vid}, Style={style}, Resolution={resolution}")
# 直接调用底层 _post 接口,因为 comic_style 使用 Scene 而非 WorkflowId
try:
resp = api._post(VOD_ACTION_SUBMIT_ASYNC_AI_CLIP, payload)
except Exception as e:
bail(f"提交任务失败:{e}")
if isinstance(resp, str):
resp = json.loads(resp)
result = resp.get("Result", {})
base_resp = result.get("BaseResp", {}) or {}
sc = base_resp.get("StatusCode", 0)
if sc != 0:
bail(f"提交任务失败:StatusCode={sc} msg={base_resp.get('StatusMessage', '')}")
vcreative_id = result.get(VOD_FIELD_AI_CLIP_TASK_ID, "") or result.get(
"VCreativeId", ""
)
if not vcreative_id:
bail(f"提交任务未返回 VCreativeId,原始响应:{json.dumps(resp)}")
log(f"任务已提交,VCreativeId={vcreative_id},开始轮询...")
return api.poll_vcreative(vcreative_id, space_name)
def main():
# ── 恢复轮询模式 ───────────────────────────────
if len(sys.argv) >= 3 and sys.argv[1] == "--poll":
vcreative_id = sys.argv[2]
api = ApiManage()
space_name = get_space_name(argv_pos=3)
result = api.poll_vcreative(vcreative_id, space_name)
out(result)
return
# ── 正常提交模式 ───────────────────────────────
api, space_name, params = init_and_parse(argv_pos=1)
vid = params.get("Vid", "").strip()
if not vid:
bail("缺少必填参数 Vid(视频 ID)")
# 去掉 vid:// 前缀用于校验
raw_vid = vid.replace("vid://", "") if vid.startswith("vid://") else vid
resolution = params.get("Resolution", "").strip()
if not resolution:
bail(f"缺少必填参数 Resolution,可选值:{', '.join(sorted(VALID_RESOLUTIONS))}")
if resolution not in VALID_RESOLUTIONS:
bail(
f"Resolution 不合法:{resolution},可选值:{', '.join(sorted(VALID_RESOLUTIONS))}"
)
style = params.get("Style", "漫画风").strip()
if style not in VALID_STYLES:
bail(f"Style 不合法:{style},可选值:{', '.join(sorted(VALID_STYLES))}")
# ── 时长校验 ─────────────────────────────────
log("检查视频时长...")
duration = get_duration(api, raw_vid, space_name)
log(f"视频时长:{duration:.1f}s")
if duration > MAX_DURATION_SEC:
bail(f"视频时长 {duration:.0f}s 超过限制(最大 {MAX_DURATION_SEC}s / 5 分钟)")
# ── 提交 ─────────────────────────────────────
result = submit_comic_style(api, raw_vid, style, resolution, space_name)
out(result)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
compile.py — 音视频合成(替换/叠加背景音)
用法:
python <SKILL_DIR>/scripts/compile.py '<json_args>'
python <SKILL_DIR>/scripts/compile.py @params.json
json_args 字段见 references/06-compile.md
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import init_and_parse, fmt_src, out, bail
def main():
client, sp, args = init_and_parse()
video = args.get("video")
if not video:
bail("compile: video 不能为空")
audio = args.get("audio")
if not audio:
bail("compile: audio 不能为空")
vt, vs = video.get("type", "vid"), video.get("source", "")
at, as_ = audio.get("type", "vid"), audio.get("source", "")
param_obj = {
"space_name": sp,
"video": fmt_src(vt, vs) if vt in ("vid", "directurl") else vs,
"audio": fmt_src(at, as_) if at in ("vid", "directurl") else as_,
"is_audio_reserve": bool(args.get("is_audio_reserve", True)),
"is_video_audio_sync": bool(args.get("is_video_audio_sync", False)),
}
if param_obj["is_video_audio_sync"]:
param_obj["sync_mode"] = args.get("sync_mode", "video")
param_obj["sync_method"] = args.get("sync_method", "trim")
out(client.submit_vcreative("loki://167984726", param_obj, sp))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
drama_recap.py — 提交解说视频生成任务(CreateDramaRecapTask / QueryDramaRecapTask)
基于大模型视频理解,根据原视频生成不同风格的 AI 解说视频,支持自定义解说词或 AI 自动生成,
支持多种音色、字幕样式和短剧三要素模板。
用法:
python <SKILL_DIR>/scripts/drama_recap.py '<json_args>' [space_name]
python <SKILL_DIR>/scripts/drama_recap.py @params.json [space_name]
python <SKILL_DIR>/scripts/drama_recap.py --poll <TaskId> [space_name]
JSON 参数说明:
视频输入(二选一):
Vids — 视频 ID 列表(至少 1 个)
DramaScriptTaskId — 已完成的剧本还原任务 ID(与 Vids 互斥)
解说词(根据模式必选或可选):
RecapText — 自定义解说词文本(AutoGenerateRecapText=false 时必选)
可选:
AutoGenerateRecapText — 是否 AI 自动生成解说词,默认 false
RecapStyle — AI 解说风格关键词(如"搞笑"、"悬疑"),≤500 字符
RecapTextSpeed — 解说语速 [0.5, 2.0],默认 1.0,推荐 1.2
RecapTextLength — AI 生成解说词长度(字符数),≤5000
PauseTime — 句间停顿(毫秒)[1, 1000],默认 120
AllowRepeatMatch — 是否允许匹配重复画面,默认 false
IsEraseSubtitle — 是否擦除原字幕,默认 false
BatchGenerateCount — 批量生成数量,默认 1,最大 100
VoiceType — 音色名称(默认 Yunxi),预置: Yunxi/Yunjian/Yunfeng/Yunyi/Yunjie/Yunze/Yunye/Xiaoxiao/Xiaochen/Xiaohan/Xiaomo
AppId — 豆包语音 App ID(使用高级音色时需要)
FontConfig — 字幕样式配置(详见 reference 文档)
MiniseriesEdit — 短剧三要素配置(Template/Title/Hint)
输出:
成功: {"Status":"success","TaskId":"...","Vid":"...","MultipleResult":{...}}
失败: {"error":"..."}
超时: {"error":"轮询超时...","resume_hint":{"command":"python .../drama_recap.py --poll <TaskId> <space>"}}
"""
import sys
import os
import json
import time
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import (
init_and_parse,
get_space_name,
log,
bail,
out,
)
from api_manage import ApiManage
# ══════════════════════════════════════════════════════
# 预置音色列表
# ══════════════════════════════════════════════════════
PRESET_VOICES = {
"Yunxi",
"Yunjian",
"Yunfeng",
"Yunyi",
"Yunjie",
"Yunze",
"Yunye",
"Xiaoxiao",
"Xiaochen",
"Xiaohan",
"Xiaomo",
}
# 短剧三要素模板
SUPPORTED_TEMPLATES = {
"热门短剧1",
"热门短剧2",
"热门短剧3",
"热门短剧4",
"热门短剧5",
}
# ══════════════════════════════════════════════════════
# 轮询逻辑
# ══════════════════════════════════════════════════════
def poll_drama_recap(api, space_name, task_id, max_rounds=360, interval=5):
"""
轮询 QueryDramaRecapTask 直到终态。
终态: success / failed / timeout
"""
log(f"开始轮询解说视频任务: TaskId={task_id}")
for i in range(1, max_rounds + 1):
try:
raw = api.query_drama_recap_task(
{
"SpaceName": space_name,
"TaskId": task_id,
}
)
resp = json.loads(raw) if isinstance(raw, str) else raw
result = resp.get("Result", {})
status = result.get("Status", "")
if i % 12 == 1: # 每分钟打一次日志
log(f"轮询第 {i}/{max_rounds} 次, Status={status}")
if status == "success":
log("解说视频生成成功")
output = {
"Status": "success",
"TaskId": task_id,
"SpaceName": space_name,
}
# 单个视频时有 Vid
if result.get("Vid"):
output["Vid"] = result["Vid"]
# 批量时有 MultipleResult
if result.get("MultipleResult"):
output["MultipleResult"] = result["MultipleResult"]
return output
if status in ("failed", "timeout"):
log(f"任务终态: {status}")
return {
"Status": status,
"TaskId": task_id,
"SpaceName": space_name,
"detail": result,
"note": f"任务{status},请检查输入视频和参数后重试。",
}
# running — 继续等待
except Exception as e:
if i % 12 == 1:
log(f"轮询异常: {e}")
time.sleep(interval)
# 超时
return {
"error": f"轮询超时({max_rounds} 次 × {interval}s),任务仍在处理中",
"TaskId": task_id,
"resume_hint": {
"description": "任务尚未完成,可用以下命令重启轮询",
"command": f"python <SKILL_DIR>/scripts/drama_recap.py --poll '{task_id}' {space_name}",
},
}
# ══════════════════════════════════════════════════════
# 主流程
# ══════════════════════════════════════════════════════
def main():
# ── 检查恢复轮询模式 ──
if len(sys.argv) >= 3 and sys.argv[1] == "--poll":
task_id = sys.argv[2]
space_name = get_space_name(argv_pos=3)
api = ApiManage()
result = poll_drama_recap(api, space_name, task_id)
out(result)
return
api, space_name, args = init_and_parse(argv_pos=1)
# ── 解析视频输入(Vids 和 DramaScriptTaskId 二选一)──
vids = args.get("Vids") or args.get("vids") or []
if isinstance(vids, str):
vids = [vids]
drama_script_task_id = (
args.get("DramaScriptTaskId") or args.get("dramaScriptTaskId") or ""
)
if vids and drama_script_task_id:
bail("Vids 和 DramaScriptTaskId 互斥,只能提供其中一个")
if not vids and not drama_script_task_id:
bail("必须提供 Vids(视频 ID 列表)或 DramaScriptTaskId(剧本还原任务 ID)之一")
# ── 解析解说词相关 ──
auto_generate = args.get("AutoGenerateRecapText", False)
recap_text = args.get("RecapText") or args.get("recapText") or ""
if not auto_generate and not recap_text:
bail(
"当 AutoGenerateRecapText 为 false(默认)时,必须提供 RecapText(解说词文本)。\n"
"或设置 AutoGenerateRecapText=true 让 AI 自动生成解说词。"
)
if auto_generate and recap_text:
bail("AutoGenerateRecapText=true 时不可同时设置 RecapText,请二选一")
# ── 构造请求体 ──
body = {"SpaceName": space_name}
if vids:
body["Vids"] = [v for v in vids if v]
if not body["Vids"]:
bail("Vids 列表中没有有效的视频 ID")
else:
body["DramaScriptTaskId"] = drama_script_task_id
if recap_text:
body["RecapText"] = recap_text
# IsEraseSubtitle
if "IsEraseSubtitle" in args:
body["IsEraseSubtitle"] = args["IsEraseSubtitle"]
# BatchGenerateCount
batch_count = args.get("BatchGenerateCount", 1)
if batch_count != 1:
body["BatchGenerateCount"] = batch_count
# ── SpeakerConfig ──
voice_type = args.get("VoiceType") or args.get("voiceType") or ""
app_id = args.get("AppId") or args.get("appId") or ""
if voice_type or app_id:
speaker = {}
if voice_type:
speaker["VoiceType"] = voice_type
if app_id:
speaker["AppId"] = app_id
speaker["Cluster"] = "volcano_tts"
body["SpeakerConfig"] = speaker
# ── FontConfig (pass-through) ──
font_config = args.get("FontConfig") or args.get("fontConfig")
if font_config and isinstance(font_config, dict):
body["FontConfig"] = font_config
# ── DramaRecapConfig ──
recap_config = {}
if auto_generate:
recap_config["AutoGenerateRecapText"] = True
recap_style = args.get("RecapStyle") or args.get("recapStyle") or ""
if recap_style:
recap_config["RecapStyle"] = recap_style
recap_speed = args.get("RecapTextSpeed") or args.get("recapTextSpeed")
if recap_speed is not None:
recap_config["RecapTextSpeed"] = float(recap_speed)
recap_length = args.get("RecapTextLength") or args.get("recapTextLength")
if recap_length is not None:
recap_config["RecapTextLength"] = int(recap_length)
pause_time = args.get("PauseTime") or args.get("pauseTime")
if pause_time is not None:
recap_config["PauseTime"] = int(pause_time)
allow_repeat = args.get("AllowRepeatMatch")
if allow_repeat is not None:
recap_config["AllowRepeatMatch"] = allow_repeat
if recap_config:
body["DramaRecapConfig"] = recap_config
# ── MiniseriesEdit (短剧三要素) ──
mini_edit = args.get("MiniseriesEdit") or args.get("miniseriesEdit")
if mini_edit and isinstance(mini_edit, dict):
tmpl = mini_edit.get("Template", "")
if tmpl and tmpl not in SUPPORTED_TEMPLATES:
bail(
f"不支持的短剧三要素模板: {tmpl}。支持: {', '.join(sorted(SUPPORTED_TEMPLATES))}"
)
body["MiniseriesEdit"] = mini_edit
input_desc = (
f"{len(vids)} 个视频" if vids else f"DramaScriptTaskId={drama_script_task_id}"
)
log(
f"提交解说视频生成任务: {input_desc}, AutoGenerate={auto_generate}, BatchCount={batch_count}"
)
# ── 提交任务 ──
try:
raw = api.create_drama_recap_task(body)
resp = json.loads(raw) if isinstance(raw, str) else raw
except Exception as e:
bail(f"CreateDramaRecapTask 调用失败: {e}")
resp_meta = resp.get("ResponseMetadata", {})
if resp_meta.get("Error"):
bail(
f"CreateDramaRecapTask 返回错误: {json.dumps(resp_meta['Error'], ensure_ascii=False)}"
)
result = resp.get("Result", {})
task_id = result.get("TaskId", "")
if not task_id:
bail(
f"CreateDramaRecapTask 未返回 TaskId: {json.dumps(resp, ensure_ascii=False)}"
)
drama_script_tid = result.get("DramaScriptTaskId", "")
log(
f"任务已提交: TaskId={task_id}"
+ (f", DramaScriptTaskId={drama_script_tid}" if drama_script_tid else "")
)
# ── 轮询 ──
poll_result = poll_drama_recap(api, space_name, task_id)
out(poll_result)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
drama_script.py — 提交 AI 剧本还原任务(CreateDramaScriptTask / QueryDramaScriptTask)
基于大模型视频理解,将剧情类视频转化为结构化剧本文本。精准识别并提取视频中的
场景、人物(角色)、对话、情节等核心元素,为内容创作者和数据分析师提供高价值文本素材。
用法:
python <SKILL_DIR>/scripts/drama_script.py '<json_args>' [space_name]
python <SKILL_DIR>/scripts/drama_script.py @params.json [space_name]
JSON 参数说明:
必选:
Vids — 视频 ID 列表(至少 1 个),如 ["v023xxx", "v024xxx"]
可选:
ClientToken — 幂等 token(不传则自动生成 UUID)
输出:
成功: {"Status":"success","TaskId":"...","ResultUrl":"..."}
失败: {"error":"..."}
超时: {"error":"轮询超时...","resume_hint":{"command":"python .../drama_script.py --poll <TaskId> <space>"}}
恢复轮询模式:
python <SKILL_DIR>/scripts/drama_script.py --poll <TaskId> [space_name]
"""
import sys
import os
import json
import time
import uuid
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import (
init_and_parse,
get_space_name,
log,
bail,
out,
POLL_INTERVAL,
POLL_MAX,
)
from api_manage import ApiManage
# ══════════════════════════════════════════════════════
# 剧本还原任务轮询
# ══════════════════════════════════════════════════════
def poll_drama_script(api, task_id: str, space_name: str) -> dict:
"""
轮询 QueryDramaScriptTask,终态:success / failed / timeout。
状态机:
running → 继续等待
success → 终态成功,返回 ResultUrl
failed → 终态失败
timeout → 终态超时(服务端超时,非客户端轮询超时)
"""
TERMINAL_SUCCESS = {"success"}
TERMINAL_FAIL = {"failed", "timeout"}
for i in range(1, POLL_MAX + 1):
log(f"轮询剧本还原任务 [{i}/{POLL_MAX}] TaskId={task_id}")
try:
raw = api.query_drama_script_task(
{
"SpaceName": space_name,
"TaskId": task_id,
}
)
if isinstance(raw, str):
raw = json.loads(raw)
except Exception as e:
log(f" 查询失败: {e},等待 {POLL_INTERVAL}s 后重试...")
time.sleep(POLL_INTERVAL)
continue
result = raw.get("Result", raw)
status = result.get("Status", "")
if status in TERMINAL_SUCCESS:
result_url = result.get("ResultUrl", "")
return {
"Status": "success",
"TaskId": task_id,
"SpaceName": space_name,
"ResultUrl": result_url,
"note": (
"ResultUrl 是一个 .json.gz 压缩文件的下载链接(有效期 24 小时)。"
"直接将此链接提供给用户,不需要下载或解压。"
),
}
if status in TERMINAL_FAIL:
return {
"Status": status,
"TaskId": task_id,
"SpaceName": space_name,
"detail": result,
"note": "任务失败,请检查输入视频是否满足限制条件后重新提交。"
if status == "failed"
else "任务服务端超时,请稍后重新提交。",
}
# running 或其他中间状态
log(f" 状态={status!r},等待 {POLL_INTERVAL}s ...")
time.sleep(POLL_INTERVAL)
# 客户端轮询超时
return {
"error": f"轮询超时({POLL_MAX} 次 × {POLL_INTERVAL}s),任务仍在处理中",
"TaskId": task_id,
"resume_hint": {
"description": "任务尚未完成,可用以下命令重启轮询",
"command": f"python <SKILL_DIR>/scripts/drama_script.py --poll '{task_id}' {space_name}",
},
}
# ══════════════════════════════════════════════════════
# 主流程
# ══════════════════════════════════════════════════════
def main():
# 检查是否为恢复轮询模式
if len(sys.argv) > 1 and sys.argv[1] == "--poll":
if len(sys.argv) < 3:
bail("恢复轮询用法: python drama_script.py --poll <TaskId> [space_name]")
task_id = sys.argv[2]
api = ApiManage()
sp = get_space_name(argv_pos=3)
log(f"恢复轮询剧本还原任务:TaskId={task_id}, SpaceName={sp}")
result = poll_drama_script(api, task_id, sp)
out(result)
return
api, space_name, args = init_and_parse(argv_pos=1)
# ── 解析 Vids ──
vids = args.get("Vids") or args.get("vids") or []
# 兼容单个 vid 字符串
if isinstance(vids, str):
vids = [vids]
if not vids:
bail("必须提供 Vids 参数(视频 ID 列表),至少包含 1 个视频 ID")
# 过滤空值
vids = [v for v in vids if v]
if not vids:
bail("Vids 列表中没有有效的视频 ID")
# ── 幂等 token ──
client_token = args.get("ClientToken") or str(uuid.uuid4())
# ── 构造请求体 ──
body = {
"SpaceName": space_name,
"Vids": vids,
"ClientToken": client_token,
}
log(f"提交剧本还原任务: {len(vids)} 个视频, SpaceName={space_name}")
# ── 提交任务 ──
try:
raw = api.create_drama_script_task(body)
if isinstance(raw, str):
raw = json.loads(raw)
except Exception as e:
bail(f"提交剧本还原任务失败: {e}")
result = raw.get("Result", raw)
task_id = result.get("TaskId", "")
if not task_id:
bail(f"提交任务未返回 TaskId,原始响应:{json.dumps(raw, ensure_ascii=False)}")
log(f"任务已提交,TaskId={task_id},开始轮询...")
# ── 轮询直到终态 ──
poll_result = poll_drama_script(api, task_id, space_name)
out(poll_result)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
extract_audio.py — 从视频中提取音轨
用法:
python <SKILL_DIR>/scripts/extract_audio.py '<json_args>'
python <SKILL_DIR>/scripts/extract_audio.py @params.json
json_args 字段见 references/07-extract-audio.md
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import init_and_parse, fmt_src, out, bail
def main():
client, sp, args = init_and_parse()
t = args.get("type", "vid")
source = args.get("source")
if not source:
bail("extract_audio: source 不能为空")
fmt = args.get("format", "m4a")
if fmt not in ("mp3", "m4a"):
bail("extract_audio: format 必须为 mp3 或 m4a")
param_obj = {
"space_name": sp,
"source": fmt_src(t, source),
"format": fmt,
}
out(client.submit_vcreative("loki://167986559", param_obj, sp))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
flip.py — 视频翻转(上下/左右)
用法:
python <SKILL_DIR>/scripts/flip.py '<json_args>'
python <SKILL_DIR>/scripts/flip.py @params.json
json_args 字段见 references/03-flip.md
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import init_and_parse, fmt_src, out, bail
def main():
client, sp, args = init_and_parse()
t = args.get("type", "vid")
source = args.get("source")
if not source:
bail("flip: source 不能为空")
param_obj = {
"space_name": sp,
"source": fmt_src(t, source),
"flip_x": bool(args.get("flip_x", False)),
"flip_y": bool(args.get("flip_y", False)),
}
out(client.submit_vcreative("loki://165221855", param_obj, sp))
if __name__ == "__main__":
main()
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
get_media_info.py — 获取媒资信息(含播放地址)
用法:
python get_media_info.py '{"vids":"v001,v002"}'
python get_media_info.py @params.json
参数:
vids (str, 必需): 逗号分隔的 Vid 列表
返回:
每个 Vid 的基础信息、片源信息及播放链接
"""
import sys
import os
import json
sys.path.insert(0, os.path.dirname(__file__))
from vod_common import init_and_parse, log, out
from api_manage import ApiManage
# GetMediaInfos 接口单次最多 20 个 Vid
BATCH_LIMIT = 20
def _fetch_batch(api: ApiManage, vids_str: str, space_name: str) -> dict:
"""单次请求最多 20 个 vid。"""
raw = api.get_media_infos(vids_str, space_name)
if isinstance(raw, str):
raw = json.loads(raw)
return raw.get("Result", raw)
def run(api: ApiManage, args: dict, space_name: str):
vids_raw = args.get("vids") or args.get("Vids") or ""
if not vids_raw:
return {"error": "缺少必需参数 vids(逗号分隔的 Vid 列表)"}
# 统一为列表
if isinstance(vids_raw, list):
vid_list = [v.strip() for v in vids_raw if v.strip()]
else:
vid_list = [v.strip() for v in str(vids_raw).split(",") if v.strip()]
if not vid_list:
return {"error": "vids 为空"}
all_media = []
not_exist = []
# 分批请求,每批最多 BATCH_LIMIT 个
for i in range(0, len(vid_list), BATCH_LIMIT):
batch = vid_list[i : i + BATCH_LIMIT]
batch_str = ",".join(batch)
log(f"查询媒资信息 [{i + 1}~{i + len(batch)}/{len(vid_list)}]: {batch_str}")
result = _fetch_batch(api, batch_str, space_name)
media_list = result.get("MediaInfoList") or []
batch_not_exist = result.get("NotExistVids") or []
not_exist.extend(batch_not_exist)
for item in media_list:
basic = item.get("BasicInfo", {})
source = item.get("SourceInfo", {})
vid = basic.get("Vid", "")
# 获取播放地址
play_url = ""
if vid:
try:
info = api.get_play_video_info(vid, space_name)
play_url = info.get("PlayURL", "")
except Exception as e:
log(f"获取播放地址失败 ({vid}): {e}")
# 降级:通过 FileName 获取
fname = source.get("FileName", "")
if fname:
try:
play_url = api.get_play_url("directurl", fname, space_name)
except Exception:
pass
all_media.append(
{
"Vid": vid,
"Title": basic.get("Title", ""),
"SpaceName": basic.get("SpaceName", ""),
"PublishStatus": basic.get("PublishStatus", ""),
"CreateTime": basic.get("CreateTime", ""),
"Source": {
"Format": source.get("Format", ""),
"Duration": source.get("Duration"),
"Width": source.get("Width"),
"Height": source.get("Height"),
"Size": source.get("Size"),
"Codec": source.get("Codec", ""),
"Fps": source.get("Fps"),
"FileName": source.get("FileName", ""),
},
"PlayUrl": play_url,
}
)
output = {"MediaInfoList": all_media}
if not_exist:
output["NotExistVids"] = not_exist
return output
def main():
api, space_name, args = init_and_parse()
result = run(api, args, space_name)
out(result)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
green_screen.py — 绿幕抠图
用法:
python <SKILL_DIR>/scripts/green_screen.py '<json_args>'
python <SKILL_DIR>/scripts/green_screen.py @params.json
json_args 字段见 references/21-green-screen.md
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import init_and_parse, build_media_input, out, bail
def main():
client, sp, args = init_and_parse()
t = args.get("type", "Vid")
video = args.get("video")
if not video:
bail("green_screen: video 不能为空")
fmt = args.get("output_format", "WEBM").upper()
if fmt not in ("MOV", "WEBM"):
bail(f"green_screen: output_format 必须为 MOV 或 WEBM,得到:{fmt}")
params = {
"Input": build_media_input(t, video, sp),
"Operation": {
"Type": "Task",
"Task": {
"Type": "VideoMatting",
"VideoMatting": {
"Model": "GreenScreen",
"VideoOption": {"Format": fmt},
"NewVid": True,
},
},
},
}
out(client.submit_media(params, "greenScreen", sp))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
highlight.py — 提交短剧高光剪辑任务(StartExecution - Highlight)
基于大模型多模态高光提取算法,从短剧正片视频中智能提取最精彩的高光片段,
可生成单集摘要、剧集集锦、剧集宣传片等视频素材。
用法:
python <SKILL_DIR>/scripts/highlight.py '<json_args>' [space_name]
python <SKILL_DIR>/scripts/highlight.py @params.json [space_name]
JSON 参数说明:
必选:
Vids — 视频 ID 列表(至少 1 个),如 ["v023xxx", "v024xxx"]
可选:
Model — 模型,默认 "Miniseries"(短剧)
Mode — 模式,默认 "StorylineCuts"(剧情高光剪辑)
WithStoryboard — 是否生成分镜脚本,默认 true
WithOpeningHook— 是否生成开头钩子片段,默认 true
输出:
成功: {"Status":"Success","RunId":"...","Meta":{...},"MultiInputs":[...]}
失败: {"error":"..."}
超时: {"error":"轮询超时...","resume_hint":{"command":"python .../poll_media.py highlight <RunId> <space>"}}
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import (
init_and_parse,
log,
bail,
out,
)
# ══════════════════════════════════════════════════════
# 默认配置
# ══════════════════════════════════════════════════════
DEFAULT_MODEL = "Miniseries"
DEFAULT_MODE = "StorylineCuts"
DEFAULT_WITH_STORYBOARD = True
DEFAULT_WITH_OPENING_HOOK = True
# 支持的模型
SUPPORTED_MODELS = {"Miniseries"}
# 支持的模式
SUPPORTED_MODES = {"StorylineCuts"}
# ══════════════════════════════════════════════════════
# 主流程
# ══════════════════════════════════════════════════════
def main():
api, space_name, args = init_and_parse(argv_pos=1)
# ── 解析 Vids ──
vids = args.get("Vids") or args.get("vids") or []
# 兼容单个 vid 字符串
if isinstance(vids, str):
vids = [vids]
if not vids:
bail("必须提供 Vids 参数(视频 ID 列表),至少包含 1 个视频 ID")
# ── 解析可选参数 ──
model = args.get("Model", DEFAULT_MODEL)
mode = args.get("Mode", DEFAULT_MODE)
with_storyboard = args.get("WithStoryboard", DEFAULT_WITH_STORYBOARD)
with_opening_hook = args.get("WithOpeningHook", DEFAULT_WITH_OPENING_HOOK)
if model not in SUPPORTED_MODELS:
bail(
f"不支持的 Model: {model}。当前支持: {', '.join(sorted(SUPPORTED_MODELS))}"
)
if mode not in SUPPORTED_MODES:
bail(f"不支持的 Mode: {mode}。当前支持: {', '.join(sorted(SUPPORTED_MODES))}")
duration = api.sum_media_info_list_duration_seconds(",".join(vids), space_name)
if duration is None:
bail("未找到媒资列表,请确认 Vids 及空间名称")
# 如果 duration 大于 300,则 max_duration 为 180,否则 max_duration 为 60
if duration > 300:
max_duration = 180
else:
max_duration = 60
# ── 构造 MultiInputs ──
multi_inputs = []
for vid in vids:
if not vid:
continue
multi_inputs.append(
{
"Type": "Vid",
"Vid": vid,
}
)
if not multi_inputs:
bail("Vids 列表中没有有效的视频 ID")
# ── 构造请求体 ──
params = {
"SpaceName": space_name,
"MultiInputs": multi_inputs,
"Operation": {
"Type": "Task",
"Task": {
"Type": "Highlight",
"Highlight": {
"Model": model,
"Mode": mode,
"Edit": {
"Mode": "HighlightClips",
},
"HighlightCuts": {
"WithStoryboard": with_storyboard,
"MaxDuration": max_duration,
},
"OpeningHook": {
"WithOpeningHook": with_opening_hook,
},
},
},
},
}
log(f"提交高光剪辑任务: {len(multi_inputs)} 个视频, Model={model}, Mode={mode}")
# ── 提交并轮询 ──
result = api.submit_media(params, "highlight", space_name)
out(result)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
image_to_video.py — 图片转视频
用法:
python <SKILL_DIR>/scripts/image_to_video.py '<json_args>'
python <SKILL_DIR>/scripts/image_to_video.py @params.json
json_args 字段见 references/05-image-to-video.md
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from vod_common import init_and_parse, fmt_src, out, bail
def main():
client, sp, args = init_and_parse()
images = args.get("images")
if not images:
bail("image_to_video: images 不能为空")
formatted = []
for img in images:
it = img.get("type", "vid")
isrc = img.get("source", "")
item = {
"type": it,
"source": fmt_src(it, isrc) if it in ("vid", "directurl") else isrc,
}
for k in ("duration", "animation_type", "animation_in", "animation_out"):
if k in img:
item[k] = img[k]
formatted.append(item)
param_obj = {
"space_name": sp,
"images": formatted,
"transitions": args.get("transitions") or [],
}
out(client.submit_vcreative("loki://167979998", param_obj, sp))
if __name__ == "__main__":
main()
Related skills
FAQ
What credentials does it need?
It needs VOLCENGINE_ACCESS_KEY, VOLCENGINE_SECRET_KEY and VOD_SPACE_NAME, configurable via a .env file.
What is it not for?
It is not for pure text generation, real-time streaming or source-free generative video creation.