还原到1.0.0

This commit is contained in:
Hommy
2025-10-27 23:07:46 +08:00
parent e5b2871144
commit c756d578f2
216 changed files with 29936 additions and 32839 deletions
-14
View File
@@ -1,14 +0,0 @@
[flake8]
extend-ignore = E301, E302, E303, E305, E306, E701, F403, F405
exclude =
.git,
__pycache__,
ignored,
build,
pyJianYingDraft/metadata/animation_meta.py,
pyJianYingDraft/metadata/audio_effect_meta.py,
pyJianYingDraft/metadata/filter_meta.py,
pyJianYingDraft/metadata/video_effect_meta.py,
pyJianYingDraft/metadata/transition_meta.py,
pyJianYingDraft\metadata\font_meta.py
max-line-length = 140
+3 -60
View File
@@ -1,60 +1,3 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
*.egg-info/
dist/
build/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg
MANIFEST
# Virtual environments
venv/
venv-capcut/
ENV/
env/
.venv/
# uv
.uv/
uv.lock
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
# Project specific
output/
draft_*/
dfd_*/
*.zip
# Logs
*.log
# Environment variables
.env
.env.local
# Cache
.cache/
*.cache
*.pyc
.venv
./dist
-1
View File
@@ -1 +0,0 @@
3.11
+32
View File
@@ -0,0 +1,32 @@
FROM python:3.11-slim
# 使用pip安装uv
RUN pip install --no-cache-dir uv
# 验证uv安装
RUN uv --version
# 设置工作目录
WORKDIR /app
# 创建非root用户并提前配置缓存目录
RUN mkdir -p /root/.cache/uv
# 从CI构建的dist目录复制所有文件
COPY dist/ .
# 安装依赖(仍使用root用户确保权限)
RUN uv sync
# 暴露应用端口
EXPOSE 60000
# 设置环境变量,指定uv缓存目录和用户主目录
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH="/app/.venv/bin:$PATH" \
HOME="/root" \
UV_CACHE_DIR="/root/.cache/uv"
# 启动命令
CMD ["uv", "run", "main.py", "--workers", "4"]
-360
View File
@@ -1,360 +0,0 @@
# 通过CapCutAPI连接AI生成的一切 [在线体验](https://www.capcutapi.top)
<div align="center">
```
👏👏👏👏 庆祝github 800星,送出价值8000点不记名云渲染券:040346B5-8D8F-459E-8EE7-332C0B827117
```
</div>
## 项目概览
**CapCutAPI** 是一款强大的云端 剪辑 API,它赋予您对 AI 生成素材(包括图片、音频、视频和文字)的精确控制权。
它提供了精确的编辑能力来拼接原始的 AI 输出,例如给视频变速或将图片镜像反转。这种能力有效地解决了 AI 生成的结果缺乏精确控制,难以复制的问题,让您能够轻松地将创意想法转化为精致的视频。
所有这些功能均旨在对标剪映软件的功能,确保您在云端也能获得熟悉且高效的剪辑体验。
### 核心优势
1. 通过API的方式,提供对标剪映/CapCut的剪辑能力。
2. 可以在网页实时预览剪辑结果,无需下载,极大方便工作流开发。
3. 可以下载剪辑结果,并导入到剪映/CapCut中二次编辑。
4. 可以利用API将剪辑结果生成视频,实现全云端操作。
## 效果展示
<div align="center">
**MCP,创建属于自己的剪辑Agent**
[![AI Cut](https://img.youtube.com/vi/fBqy6WFC78E/hqdefault.jpg)](https://www.youtube.com/watch?v=fBqy6WFC78E)
**通过CapCutAPI,将AI生成的图片,视频组合起来**
[![Airbnb](https://img.youtube.com/vi/1zmQWt13Dx0/hqdefault.jpg)](https://www.youtube.com/watch?v=1zmQWt13Dx0)
[![Horse](https://img.youtube.com/vi/IF1RDFGOtEU/hqdefault.jpg)](https://www.youtube.com/watch?v=IF1RDFGOtEU)
[![Song](https://img.youtube.com/vi/rGNLE_slAJ8/hqdefault.jpg)](https://www.youtube.com/watch?v=rGNLE_slAJ8)
</div>
## 核心功能
| 功能模块 | API | MCP 协议 | 描述 |
|---------|----------|----------|------|
| **草稿管理** | ✅ | ✅ | 创建、保存剪映/CapCut草稿文件 |
| **视频处理** | ✅ | ✅ | 多格式视频导入、剪辑、转场、特效 |
| **音频编辑** | ✅ | ✅ | 音频轨道、音量控制、音效处理 |
| **图像处理** | ✅ | ✅ | 图片导入、动画、蒙版、滤镜 |
| **文本编辑** | ✅ | ✅ | 多样式文本、阴影、背景、动画 |
| **字幕系统** | ✅ | ✅ | SRT 字幕导入、样式设置、时间同步 |
| **特效引擎** | ✅ | ✅ | 视觉特效、滤镜、转场动画 |
| **贴纸系统** | ✅ | ✅ | 贴纸素材、位置控制、动画效果 |
| **关键帧** | ✅ | ✅ | 属性动画、时间轴控制、缓动函数 |
| **媒体分析** | ✅ | ✅ | 视频时长获取、格式检测 |
## 快速开始
### 1. 系统要求
- Python 3.10+
- 剪映 或 CapCut 国际版
- FFmpeg
### 2. 安装部署
#### 使用 uv (推荐)
```bash
# 1. 克隆项目
git clone https://github.com/sun-guannan/CapCutAPI.git
cd CapCutAPI
# 2. 安装 uv (如果尚未安装)
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# 3. 安装依赖
uv sync # 安装基础依赖
uv sync --extra mcp # 安装包含 MCP 协议支持的依赖
# 4. 配置文件 (可选)
cp config.json.example config.json
# 根据需要编辑 config.json
```
#### 使用传统方式
```bash
# 1. 克隆项目
git clone https://github.com/sun-guannan/CapCutAPI.git
cd CapCutAPI
# 2. 创建虚拟环境 (推荐)
python -m venv venv-capcut
source venv-capcut/bin/activate # Linux/macOS
# 或 venv-capcut\Scripts\activate # Windows
# 3. 安装依赖
pip install -r requirements.txt # HTTP API 基础依赖
pip install -r requirements-mcp.txt # MCP 协议支持 (可选)
# 4. 配置文件
cp config.json.example config.json
# 根据需要编辑 config.json
```
### 3. 启动服务
#### 使用 uv
```bash
uv run capcut_server.py # 启动HTTP API服务器, 默认端口: 9001
uv run mcp_server.py # 启动 MCP 协议服务,支持 stdio 通信
```
#### 使用传统方式
```bash
python capcut_server.py # 启动HTTP API服务器, 默认端口: 9001
python mcp_server.py # 启动 MCP 协议服务,支持 stdio 通信
```
## MCP 集成指南
[MCP 文档](./MCP_文档_中文.md) • [MCP English Guide](./MCP_Documentation_English.md)
### 1. 客户端配置
创建或更新 `mcp_config.json` 配置文件:
#### 使用 uv
```json
{
"mcpServers": {
"capcut-api": {
"command": "uv",
"args": ["run", "mcp_server.py"],
"cwd": "/path/to/capcut-mate",
"env": {
"PYTHONPATH": "/path/to/capcut-mate",
"DEBUG": "0"
}
}
}
}
```
#### 使用传统 Python
```json
{
"mcpServers": {
"capcut-api": {
"command": "python3",
"args": ["mcp_server.py"],
"cwd": "/path/to/capcut-mate",
"env": {
"PYTHONPATH": "/path/to/capcut-mate",
"DEBUG": "0"
}
}
}
}
```
### 2. 连接测试
```bash
# 测试 MCP 连接
python test_mcp_client.py
# 预期输出
✅ MCP 服务器启动成功
✅ 获取到 11 个可用工具
✅ 草稿创建测试通过
```
## 使用示例
### 1. API 示例
添加视频素材
```python
import requests
# 添加背景视频
response = requests.post("http://localhost:9001/add_video", json={
"video_url": "https://example.com/background.mp4",
"start": 0,
"end": 10
"volume": 0.8,
"transition": "fade_in"
})
print(f"视频添加结果: {response.json()}")
```
创建样式文本
```python
import requests
# 添加标题文字
response = requests.post("http://localhost:9001/add_text", json={
"text": "欢迎使用 CapCutAPI",
"start": 0,
"end": 5,
"font": "思源黑体",
"font_color": "#FFD700",
"font_size": 48,
"shadow_enabled": True,
"background_color": "#000000"
})
print(f"文本添加结果: {response.json()}")
```
可以在`example.py`文件中获取更多示例。
### 2. MCP 协议示例
完整工作流程
```python
# 1. 创建新项目
draft = mcp_client.call_tool("create_draft", {
"width": 1080,
"height": 1920
})
draft_id = draft["result"]["draft_id"]
# 2. 添加背景视频
mcp_client.call_tool("add_video", {
"video_url": "https://example.com/bg.mp4",
"draft_id": draft_id,
"start": 0,
"end": 10,
"volume": 0.6
})
# 3. 添加标题文字
mcp_client.call_tool("add_text", {
"text": "AI 驱动的视频制作",
"draft_id": draft_id,
"start": 1,
"end": 6,
"font_size": 56,
"shadow_enabled": True,
"background_color": "#1E1E1E"
})
# 4. 添加关键帧动画
mcp_client.call_tool("add_video_keyframe", {
"draft_id": draft_id,
"track_name": "main",
"property_types": ["scale_x", "scale_y", "alpha"],
"times": [0, 2, 4],
"values": ["1.0", "1.2", "0.8"]
})
# 5. 保存项目
result = mcp_client.call_tool("save_draft", {
"draft_id": draft_id
})
print(f"项目已保存: {result['result']['draft_url']}")
```
高级文本效果
```python
# 多样式彩色文本
mcp_client.call_tool("add_text", {
"text": "彩色文字效果展示",
"draft_id": draft_id,
"start": 2,
"end": 8,
"font_size": 42,
"shadow_enabled": True,
"shadow_color": "#FFFFFF",
"background_alpha": 0.8,
"background_round_radius": 20,
"text_styles": [
{"start": 0, "end": 2, "font_color": "#FF6B6B"},
{"start": 2, "end": 4, "font_color": "#4ECDC4"},
{"start": 4, "end": 6, "font_color": "#45B7D1"}
]
})
```
### 3. 下载草稿
调用 `save_draft` 会在`capcut_server.py`当前目录下生成一个 `dfd_` 开头的文件夹,将其复制到剪映/CapCut 草稿目录,即可在应用中看到生成的草稿。
## 模版
我们汇总了一些模版,放在`pattern`文件夹下。
## 社区与支持
我们欢迎各种形式的贡献!我们的迭代规则:
- 禁止直接向main提交pr
- 可以向dev分支提交pr
- 每周一从dev合并到main分支,并发版
## 进群交流
![交流群](https://github.com/user-attachments/assets/44a4d7b0-2478-40ef-9fab-8f6d6da68afd)
- 反馈问题
- 功能建议
- 最新消息
### 🤝 合作机会
- **出海视频制作**: 想要利用这个API批量制作出海视频吗?我提供免费的咨询服务,帮助你利用这个API制作。相应的,我要将制作的工作流模板放到这个项目中的template目录中**开源**出来。
- **加入我们**: 我们的目标是提供稳定可靠的视频剪辑工具,方便融合AI生成的图片/视频/语音。如果你有兴趣,可以先从将工程里的中文翻译成英文开始!提交pr,我会看到。更深入的,还有MCP剪辑Agent, web剪辑端,云渲染这三个模块代码还没有开源出来。
- **联系方式**:
- 微信:gogoshine-com
## 📈 Star History
<div align="center">
[![Star History Chart](https://api.star-history.com/svg?repos=sun-guannan/CapCutAPI&type=Date)](https://www.star-history.com/#sun-guannan/CapCutAPI&Date)
![GitHub repo size](https://img.shields.io/github/repo-size/sun-guannan/CapCutAPI?style=flat-square)
![GitHub code size](https://img.shields.io/github/languages/code-size/sun-guannan/CapCutAPI?style=flat-square)
![GitHub issues](https://img.shields.io/github/issues/sun-guannan/CapCutAPI?style=flat-square)
![GitHub pull requests](https://img.shields.io/github/issues-pr/sun-guannan/CapCutAPI?style=flat-square)
![GitHub last commit](https://img.shields.io/github/last-commit/sun-guannan/CapCutAPI?style=flat-square)
</div>
*Made with ❤️ by the CapCutAPI Community*
</div>
## 商业合作
- 微信:
![微信](./assets/wechat.png)
- 邮箱:taohongmin51@gmail.com
+39 -328
View File
@@ -1,348 +1,59 @@
# CapCut Mate API
# Connect AI generates via CapCutAPI [Try it online](https://www.capcutapi.top)
## 项目简介
CapCut Mate API 是一个基于 FastAPI 构建的剪映小助手
## Project Overview
**CapCutAPI** is a powerful editing API that empowers you to take full control of your AI-generated assets, including images, audio, video, and text. It provides the precision needed to refine and customize raw AI output, such as adjusting video speed or mirroring an image. This capability effectively solves the lack of control often found in AI video generation, allowing you to easily transform your creative ideas into polished videos.
## 功能特点
- 用户管理:创建草稿、添加视频、保存草稿、云端渲染
- 数据验证:使用 Pydantic 进行请求数据验证
- RESTful API 设计:符合标准的 API 设计规范
- 自动生成文档:FastAPI 自动生成交互式 API 文档
All these features are designed to mirror the functionalities of the CapCut software, ensuring a familiar and efficient editing experience in the cloud.
## 技术栈
- Python 3.11+
- FastAPI:高性能的 Web 框架
- Pydantic:数据验证和模型定义
- Passlib:密码加密
- UvicornASGI 服务器
- uv:Python 包管理器和项目管理工具
Enjoy It! 😀😀😀
## 快速开始
[中文说明](README-zh.md)
### Advantages
1. **API-Powered Editing:** Access all CapCut/Jianying editing features, including multi-track editing and keyframe animation, through a powerful API.
2. **Real-Time Cloud Preview:** Instantly preview your edits on a webpage without downloads, dramatically improving your workflow.
3. **Flexible Local Editing:** Export projects as drafts to import into CapCut or Jianying for further refinement.
4. **Automated Cloud Generation:** Use the API to render and generate final videos directly in the cloud.
## Demos
<div align="center">
**MCP, create your own editing Agent**
[![AI Cut](https://img.youtube.com/vi/fBqy6WFC78E/hqdefault.jpg)](https://www.youtube.com/watch?v=fBqy6WFC78E)
**Combine AI-generated images and videos using CapCutAPI**
[More](pattern)
[![Airbnb](https://img.youtube.com/vi/1zmQWt13Dx0/hqdefault.jpg)](https://www.youtube.com/watch?v=1zmQWt13Dx0)
[![Horse](https://img.youtube.com/vi/IF1RDFGOtEU/hqdefault.jpg)](https://www.youtube.com/watch?v=IF1RDFGOtEU)
[![Song](https://img.youtube.com/vi/rGNLE_slAJ8/hqdefault.jpg)](https://www.youtube.com/watch?v=rGNLE_slAJ8)
</div>
## Key Features
| Feature Module | API | MCP Protocol | Description |
|---------|----------|----------|------|
| **Draft Management** | ✅ | ✅ | Create and save Jianying/CapCut draft files |
| **Video Processing** | ✅ | ✅ | Import, clip, transition, and apply effects to multiple video formats |
| **Audio Editing** | ✅ | ✅ | Audio tracks, volume control, sound effects processing |
| **Image Processing** | ✅ | ✅ | Image import, animation, masks, filters |
| **Text Editing** | ✅ | ✅ | Multi-style text, shadows, backgrounds, animations |
| **Subtitle System** | ✅ | ✅ | SRT subtitle import, style settings, time synchronization |
| **Effects Engine** | ✅ | ✅ | Visual effects, filters, transition animations |
| **Sticker System** | ✅ | ✅ | Sticker assets, position control, animation effects |
| **Keyframes** | ✅ | ✅ | Property animation, timeline control, easing functions |
| **Media Analysis** | ✅ | ✅ | Get video duration, detect format |
## Quick Start
### 1\. System Requirements
- Python 3.10+
- Jianying or CapCut International version
- FFmpeg
### 2\. Installation and Deployment
#### Using uv (Recommended)
### 前提条件
- Python 3.11
- uv:Python 包管理器和项目管理工具
安装方法:
- windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
- linux
sh -c "$(curl -LsSf https://astral.sh/uv/install.sh)"
### 安装步骤
1. 克隆项目
```bash
# 1. Clone the project
git clone https://github.com/sun-guannan/CapCutAPI.git
cd CapCutAPI
# 2. Install uv (if not already installed)
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# 3. Install dependencies
uv sync # Install basic dependencies
uv sync --extra mcp # Install dependencies with MCP protocol support
# 4. Configuration file (optional)
cp config.json.example config.json
# Edit config.json as needed
git clone git@github.com:Hommy-master/capcut-mate.git
cd capcut-mate
```
#### Using Traditional Method
2. 安装依赖
```bash
# 1. Clone the project
git clone https://github.com/sun-guannan/CapCutAPI.git
cd CapCutAPI
# 2. Create a virtual environment (recommended)
python -m venv venv-capcut
source venv-capcut/bin/activate # Linux/macOS
# or venv-capcut\Scripts\activate # Windows
# 3. Install dependencies
pip install -r requirements.txt # HTTP API basic dependencies
pip install -r requirements-mcp.txt # MCP protocol support (optional)
# 4. Configuration file
cp config.json.example config.json
# Edit config.json as needed
# 安装依赖
uv sync
```
### 3\. Start the service
#### Using uv
3. 启动服务器
```bash
uv run capcut_server.py # Start the HTTP API server, default port: 9001
uv run mcp_server.py # Start the MCP protocol service, supports stdio communication
uv run main.py
```
#### Using Traditional Method
4. 容器部署
```bash
python capcut_server.py # Start the HTTP API server, default port: 9001
python mcp_server.py # Start the MCP protocol service, supports stdio communication
docker pull gogoshine/capcut-mate:latest
```
## MCP Integration Guide
## 商业合作
- 微信:
[MCP 中文文档](https://www.google.com/search?q=./MCP_%E6%96%87%E6%A1%A3_%E4%B8%AD%E6%96%87.md) • [MCP English Guide](https://www.google.com/search?q=./MCP_Documentation_English.md)
![微信](./assets/wechat.png)
### 1\. Client Configuration
Create or update the `mcp_config.json` configuration file:
#### Using uv
```json
{
"mcpServers": {
"capcut-api": {
"command": "uv",
"args": ["run", "mcp_server.py"],
"cwd": "/path/to/capcut-mate",
"env": {
"PYTHONPATH": "/path/to/capcut-mate",
"DEBUG": "0"
}
}
}
}
```
#### Using Traditional Python
```json
{
"mcpServers": {
"capcut-api": {
"command": "python3",
"args": ["mcp_server.py"],
"cwd": "/path/to/capcut-mate",
"env": {
"PYTHONPATH": "/path/to/capcut-mate",
"DEBUG": "0"
}
}
}
}
```
### 2\. Connection Test
```bash
# Test MCP connection
python test_mcp_client.py
# Expected output
✅ MCP server started successfully
✅ Got 11 available tools
✅ Draft creation test passed
```
## Usage Examples
### 1\. API Example
Add video material
```python
import requests
# Add background video
response = requests.post("http://localhost:9001/add_video", json={
"video_url": "https://example.com/background.mp4",
"start": 0,
"end": 10
"volume": 0.8,
"transition": "fade_in"
})
print(f"Video addition result: {response.json()}")
```
Create stylized text
```python
import requests
# Add title text
response = requests.post("http://localhost:9001/add_text", json={
"text": "Welcome to CapCutAPI",
"start": 0,
"end": 5,
"font": "Source Han Sans",read
"font_color": "#FFD700",
"font_size": 48,
"shadow_enabled": True,
"background_color": "#000000"
})
print(f"Text addition result: {response.json()}")
```
More examples can be found in the `example.py` file.
### 2\. MCP Protocol Example
Complete workflow
```python
# 1. Create a new project
draft = mcp_client.call_tool("create_draft", {
"width": 1080,
"height": 1920
})
draft_id = draft["result"]["draft_id"]
# 2. Add background video
mcp_client.call_tool("add_video", {
"video_url": "https://example.com/bg.mp4",
"draft_id": draft_id,
"start": 0,
"end": 10,
"volume": 0.6
})
# 3. Add title text
mcp_client.call_tool("add_text", {
"text": "AI-Driven Video Production",
"draft_id": draft_id,
"start": 1,
"end": 6,
"font_size": 56,
"shadow_enabled": True,
"background_color": "#1E1E1E"
})
# 4. Add keyframe animation
mcp_client.call_tool("add_video_keyframe", {
"draft_id": draft_id,
"track_name": "main",
"property_types": ["scale_x", "scale_y", "alpha"],
"times": [0, 2, 4],
"values": ["1.0", "1.2", "0.8"]
})
# 5. Save the project
result = mcp_client.call_tool("save_draft", {
"draft_id": draft_id
})
print(f"Project saved: {result['result']['draft_url']}")
```
Advanced text effects
```python
# Multi-style colored text
mcp_client.call_tool("add_text", {
"text": "Colored text effect demonstration",
"draft_id": draft_id,
"start": 2,
"end": 8,
"font_size": 42,
"shadow_enabled": True,
"shadow_color": "#FFFFFF",
"background_alpha": 0.8,
"background_round_radius": 20,
"text_styles": [
{"start": 0, "end": 2, "font_color": "#FF6B6B"},
{"start": 2, "end": 4, "font_color": "#4ECDC4"},
{"start": 4, "end": 6, "font_color": "#45B7D1"}
]
})
```
### 3\. Downloading Drafts
Calling `save_draft` will generate a folder starting with `dfd_` in the current directory of `capcut_server.py`. Copy this to the CapCut/Jianying drafts directory to see the generated draft in the application.
## Pattern
You can find a lot of pattern in the `pattern` directory.
## Community & Support
We welcome contributions of all forms\! Our iteration rules are:
- No direct PRs to main
- PRs can be submitted to the dev branch
- Merges from dev to main and releases will happen every Monday
## Contact Us
If you want to:
- Feedback on issues
- Feature suggestions
- Get latest news
**Contact**: sguann2023@gmail.com
### 🤝 Collaboration
- **Video Production**: Want to use this API for batch production of videos? I offer free consulting services to help you use this API. In return, I'll ask for the production workflow template to be **open-sourced** in the `template` directory of this project.
- **Join us**: Our goal is to provide a stable and reliable video editing tool that integrates well with AI-generated images, videos, and audio. If you are interested, submit a PR and I'll see it. For more in-depth involvement, the code for the MCP Editing Agent, web-based editing client, and cloud rendering modules has not been open-sourced yet.
**Contact**: sguann2023@gmail.com
## 📈 Star History
<div align="center">
[![Star History Chart](https://api.star-history.com/svg?repos=sun-guannan/CapCutAPI&type=Date)](https://www.star-history.com/#sun-guannan/CapCutAPI&Date)
![GitHub repo size](https://img.shields.io/github/repo-size/sun-guannan/CapCutAPI?style=flat-square)
![GitHub code size](https://img.shields.io/github/languages/code-size/sun-guannan/CapCutAPI?style=flat-square)
![GitHub issues](https://img.shields.io/github/issues/sun-guannan/CapCutAPI?style=flat-square)
![GitHub pull requests](https://img.shields.io/github/issues-pr/sun-guannan/CapCutAPI?style=flat-square)
![GitHub last commit](https://img.shields.io/github/last-commit/sun-guannan/CapCutAPI?style=flat-square)
[![Verified on MSeeP](https://mseep.ai/badge.svg)](https://mseep.ai/app/69c38d28-a97c-4397-849d-c3e3d241b800)
</div>
*Made with ❤️ by the CapCutAPI Community*
- 邮箱:taohongmin51@gmail.com
-162
View File
@@ -1,162 +0,0 @@
# 导入必要的模块
import os
import pyJianYingDraft as draft
import time
from util import generate_draft_url, is_windows_path, url_to_hash
import re
from typing import Optional, Dict, Tuple, List
from pyJianYingDraft import exceptions, Audio_scene_effect_type, Tone_effect_type, Speech_to_song_type, CapCut_Voice_filters_effect_type,CapCut_Voice_characters_effect_type,CapCut_Speech_to_song_effect_type, trange
from create_draft import get_or_create_draft
from settings.local import IS_CAPCUT_ENV
def add_audio_track(
audio_url: str,
draft_folder: Optional[str] = None,
start: float = 0,
end: Optional[float] = None,
target_start: float = 0,
draft_id: Optional[str] = None,
volume: float = 1.0,
track_name: str = "audio_main",
speed: float = 1.0,
sound_effects: Optional[List[Tuple[str, Optional[List[Optional[float]]]]]]=None,
width: int = 1080,
height: int = 1920,
duration: Optional[float] = None # Added duration parameter
) -> Dict[str, str]:
"""
Add an audio track to the specified draft
:param draft_folder: Draft folder path, optional parameter
:param audio_url: Audio URL
:param start: Start time (seconds), default 0
:param end: End time (seconds), default None (use total audio duration)
:param target_start: Target track insertion position (seconds), default 0
:param draft_id: Draft ID, if None or corresponding zip file not found, a new draft will be created
:param volume: Volume level, range 0.0-1.0, default 1.0
:param track_name: Track name, default "audio_main"
:param speed: Playback speed, default 1.0
:param sound_effects: Scene sound effect list, each element is a tuple containing effect type name and parameter list, default None
:return: Updated draft information
"""
# Get or create draft
draft_id, script = get_or_create_draft(
draft_id=draft_id,
width=width,
height=height
)
# Add audio track (only when track doesn't exist)
if track_name is not None:
try:
imported_track = script.get_imported_track(draft.Track_type.audio, name=track_name)
# If no exception is thrown, the track already exists
except exceptions.TrackNotFound:
# Track doesn't exist, create a new track
script.add_track(draft.Track_type.audio, track_name=track_name)
else:
script.add_track(draft.Track_type.audio)
# If duration parameter is provided, prioritize it; otherwise use default audio duration of 0 seconds, real duration will be obtained during download
if duration is not None:
# Use the provided duration, skip duration retrieval and checking
audio_duration = duration
else:
# Use default audio duration of 0 seconds, real duration will be obtained when downloading the draft
audio_duration = 0.0 # Default audio duration is 0 seconds
# duration_result = get_video_duration(audio_url) # Reuse video duration retrieval function
# if not duration_result["success"]:
# print(f"Failed to get audio duration: {duration_result['error']}")
# # Check if audio duration exceeds 10 minutes
# if duration_result["output"] > 600: # 600 seconds = 10 minutes
# raise Exception(f"Audio duration exceeds 10-minute limit, current duration: {duration_result['output']} seconds")
# audio_duration = duration_result["output"]
# Download audio to local
# local_audio_path = download_audio(audio_url, draft_dir)
material_name = f"audio_{url_to_hash(audio_url)}.mp3" # Use original filename + timestamp + fixed mp3 extension
# Build draft_audio_path
draft_audio_path = None
if draft_folder:
if is_windows_path(draft_folder):
# Windows path processing
windows_drive, windows_path = re.match(r'([a-zA-Z]:)(.*)', draft_folder).groups()
parts = [p for p in windows_path.split('\\') if p]
draft_audio_path = os.path.join(windows_drive, *parts, draft_id, "assets", "audio", material_name)
# Normalize path (ensure consistent separators)
draft_audio_path = draft_audio_path.replace('/', '\\')
else:
# macOS/Linux path processing
draft_audio_path = os.path.join(draft_folder, draft_id, "assets", "audio", material_name)
# Set default value for audio end time
audio_end = end if end is not None else audio_duration
# Calculate audio duration
duration = audio_end - start
# Create audio segment
if draft_audio_path:
print('replace_path:', draft_audio_path)
audio_material = draft.Audio_material(replace_path=draft_audio_path, remote_url=audio_url, material_name=material_name, duration=audio_duration)
else:
audio_material = draft.Audio_material(remote_url=audio_url, material_name=material_name, duration=audio_duration)
audio_segment = draft.Audio_segment(
audio_material, # Pass material object
target_timerange=trange(f"{target_start}s", f"{duration}s"), # Use target_start and duration
source_timerange=trange(f"{start}s", f"{duration}s"),
speed=speed, # Set playback speed
volume=volume # Set volume
)
# Add scene sound effects
if sound_effects:
for effect_name, params in sound_effects:
# Choose different effect types based on IS_CAPCUT_ENV
effect_type = None
if IS_CAPCUT_ENV:
# In CapCut environment, look for effects in CapCut_Voice_filters_effect_type
try:
effect_type = getattr(CapCut_Voice_filters_effect_type, effect_name)
except AttributeError:
try:
# Look for effects in CapCut_Voice_characters_effect_type
effect_type = getattr(CapCut_Voice_characters_effect_type, effect_name)
except AttributeError:
# If still not found, look for effects in CapCut_Speech_to_song_effect_type
try:
effect_type = getattr(CapCut_Speech_to_song_effect_type, effect_name)
except AttributeError:
effect_type = None
else:
# In JianYing environment, look for effects in Audio_scene_effect_type
try:
effect_type = getattr(Audio_scene_effect_type, effect_name)
except AttributeError:
# If not found in Audio_scene_effect_type, continue searching in other effect types
try:
effect_type = getattr(Tone_effect_type, effect_name)
except AttributeError:
# If still not found, look for effects in Speech_to_song_type
try:
effect_type = getattr(Speech_to_song_type, effect_name)
except AttributeError:
effect_type = None
# If corresponding effect type is found, add it to the audio segment
if effect_type:
audio_segment.add_effect(effect_type, params)
else:
print(f"Warning: Audio effect named {effect_name} not found")
# Add audio segment to track
script.add_segment(audio_segment, track_name=track_name)
return {
"draft_id": draft_id,
"draft_url": generate_draft_url(draft_id)
}
-90
View File
@@ -1,90 +0,0 @@
from pyJianYingDraft import trange, Video_scene_effect_type, Video_character_effect_type, CapCut_Video_scene_effect_type, CapCut_Video_character_effect_type, exceptions
import pyJianYingDraft as draft
from typing import Optional, Dict, List, Union, Literal
from create_draft import get_or_create_draft
from util import generate_draft_url
from settings import IS_CAPCUT_ENV
def add_effect_impl(
effect_type: str, # Changed to string type
effect_category: Literal["scene", "character"],
start: float = 0,
end: float = 3.0,
draft_id: Optional[str] = None,
track_name: Optional[str] = "effect_01",
params: Optional[List[Optional[float]]] = None,
width: int = 1080,
height: int = 1920
) -> Dict[str, str]:
"""
Add an effect to the specified draft
:param effect_type: Effect type name, will be matched from Video_scene_effect_type or Video_character_effect_type
:param effect_category: Effect category, "scene" or "character", default "scene"
:param start: Start time (seconds), default 0
:param end: End time (seconds), default 3 seconds
:param draft_id: Draft ID, if None or corresponding zip file not found, a new draft will be created
:param track_name: Track name, can be omitted when there is only one effect track
:param params: Effect parameter list, items not provided or None in the parameter list will use default values
:param width: Video width, default 1080
:param height: Video height, default 1920
:return: Updated draft information
"""
# Get or create draft
draft_id, script = get_or_create_draft(
draft_id=draft_id,
width=width,
height=height
)
# Calculate time range
duration = end - start
t_range = trange(f"{start}s", f"{duration}s")
# Select the corresponding effect type based on effect category and environment
effect_enum = None
if IS_CAPCUT_ENV:
# If in CapCut environment, use CapCut effects
if effect_category == "scene":
try:
effect_enum = CapCut_Video_scene_effect_type[effect_type]
except:
effect_enum = None
elif effect_category == "character":
try:
effect_enum = CapCut_Video_character_effect_type[effect_type]
except:
effect_enum = None
else:
# Default to using JianYing effects
if effect_category == "scene":
try:
effect_enum = Video_scene_effect_type[effect_type]
except:
effect_enum = None
elif effect_category == "character":
try:
effect_enum = Video_character_effect_type[effect_type]
except:
effect_enum = None
if effect_enum is None:
raise ValueError(f"Unknown {effect_category} effect type: {effect_type}")
# Add effect track (only when track doesn't exist)
if track_name is not None:
try:
imported_track=script.get_imported_track(draft.Track_type.effect, name=track_name)
# If no exception is thrown, the track already exists
except exceptions.TrackNotFound:
# Track doesn't exist, create a new track
script.add_track(draft.Track_type.effect, track_name=track_name)
else:
script.add_track(draft.Track_type.effect)
# Add effect
script.add_effect(effect_enum, t_range, params=params[::-1], track_name=track_name)
return {
"draft_id": draft_id,
"draft_url": generate_draft_url(draft_id)
}
-251
View File
@@ -1,251 +0,0 @@
import os
import uuid
import pyJianYingDraft as draft
import time
from settings.local import IS_CAPCUT_ENV
from util import generate_draft_url, is_windows_path, url_to_hash
from pyJianYingDraft import trange, Clip_settings
import re
from typing import Optional, Dict
from pyJianYingDraft import exceptions
from create_draft import get_or_create_draft
def add_image_impl(
image_url: str,
draft_folder: Optional[str] = None,
width: int = 1080,
height: int = 1920,
start: float = 0,
end: float = 3.0, # Default display time: 3 seconds
draft_id: Optional[str] = None,
transform_y: float = 0,
scale_x: float = 1,
scale_y: float = 1,
transform_x: float = 0,
track_name: str = "main",
relative_index: int = 0,
animation: Optional[str] = None, # Entrance animation parameter (backward compatibility)
animation_duration: float = 0.5, # Entrance animation duration parameter, default 0.5 seconds
intro_animation: Optional[str] = None, # New entrance animation parameter, higher priority than animation
intro_animation_duration: float = 0.5, # New entrance animation duration parameter, default 0.5 seconds
outro_animation: Optional[str] = None, # Exit animation parameter
outro_animation_duration: float = 0.5, # Exit animation duration parameter, default 0.5 seconds
combo_animation: Optional[str] = None, # Combo animation parameter
combo_animation_duration: float = 0.5, # Combo animation duration parameter, default 0.5 seconds
transition: Optional[str] = None, # Transition type parameter
transition_duration: Optional[float] = 0.5, # Transition duration parameter (seconds), default 0.5 seconds
# Mask related parameters
mask_type: Optional[str] = None, # Mask type: Linear, Mirror, Circle, Rectangle, Heart, Star
mask_center_x: float = 0.0, # Mask center X coordinate
mask_center_y: float = 0.0, # Mask center Y coordinate
mask_size: float = 0.5, # Mask main size
mask_rotation: float = 0.0, # Mask rotation angle
mask_feather: float = 0.0, # Mask feather parameter (0-100)
mask_invert: bool = False, # Whether to invert the mask
mask_rect_width: Optional[float] = None, # Rectangle mask width (rectangle mask only)
mask_round_corner: Optional[float] = None, # Rectangle mask rounded corner (rectangle mask only, 0-100)
background_blur: Optional[int] = None # Background blur level, 1-4, corresponding to four blur intensity levels
) -> Dict[str, str]:
"""
Add an image track to the specified draft
:param animation: Entrance animation name, supported animations include: Zoom Out, Fade In, Zoom In, Rotate, Kira Float, Shake Down, Mirror Flip, Rotate Open, Fold Open, Vortex Rotate, Jump Open, etc.
:param animation_duration: Entrance animation duration (seconds), default 0.5 seconds
:param intro_animation: New entrance animation parameter, higher priority than animation
:param intro_animation_duration: New entrance animation duration (seconds), default 0.5 seconds
:param outro_animation: Exit animation parameter
:param outro_animation_duration: Exit animation duration (seconds), default 0.5 seconds
:param combo_animation: Combo animation parameter
:param combo_animation_duration: Combo animation duration (seconds), default 0.5 seconds
:param transition: Transition type, supported transitions include: Dissolve, Move Up, Move Down, Move Left, Move Right, Split, Compress, Anime Cloud, Anime Vortex, etc.
:param transition_duration: Transition duration (seconds), default 0.5 seconds
:param draft_folder: Draft folder path, optional parameter
:param image_url: Image URL
:param width: Video width, default 1080
:param height: Video height, default 1920
:param start: Start time (seconds), default 0
:param end: End time (seconds), default 3 seconds
:param draft_id: Draft ID, if None or corresponding zip file not found, a new draft will be created
:param transform_y: Y-axis transformation, default 0
:param scale_x: X-axis scaling, default 1
:param scale_y: Y-axis scaling, default 1
:param transform_x: X-axis transformation, default 0
:param track_name: When there is only one video, track name can be omitted
:param relative_index: Track rendering order index, default 0
:param mask_type: Mask type, supports: Linear, Mirror, Circle, Rectangle, Heart, Star
:param mask_center_x: Mask center X coordinate (in material pixels), default set at material center
:param mask_center_y: Mask center Y coordinate (in material pixels), default set at material center
:param mask_size: Main size of the mask, represented as a proportion of material height, default is 0.5
:param mask_rotation: Clockwise rotation angle of the mask, default no rotation
:param mask_feather: Mask feather parameter, range 0~100, default no feathering
:param mask_invert: Whether to invert the mask, default not inverted
:param mask_rect_width: Rectangle mask width, only allowed when mask type is rectangle, represented as a proportion of material width
:param mask_round_corner: Rectangle mask rounded corner parameter, only allowed when mask type is rectangle, range 0~100
:param background_blur: Background blur level, 1-4, corresponding to four blur intensity levels (0.0625, 0.375, 0.75, 1.0)
:return: Updated draft information, including draft_id and draft_url
"""
# Get or create draft
draft_id, script = get_or_create_draft(
draft_id=draft_id,
width=width,
height=height
)
# Check if video track exists, if not, add a default video track
try:
script.get_track(draft.Track_type.video, track_name=None)
except exceptions.TrackNotFound:
script.add_track(draft.Track_type.video, relative_index=0)
except NameError:
# If multiple video tracks exist (NameError), do nothing
pass
# Add video track (only when track doesn't exist)
if track_name is not None:
try:
imported_track=script.get_imported_track(draft.Track_type.video, name=track_name)
# If no exception is thrown, the track already exists
except exceptions.TrackNotFound:
# Track doesn't exist, create a new track
script.add_track(draft.Track_type.video, track_name=track_name, relative_index=relative_index)
else:
script.add_track(draft.Track_type.video, relative_index=relative_index)
# Generate material_name but don't download the image
material_name = f"image_{url_to_hash(image_url)}.png"
# Build draft_image_path
draft_image_path = None
if draft_folder:
# Detect input path type and process
if is_windows_path(draft_folder):
# Windows path processing
windows_drive, windows_path = re.match(r'([a-zA-Z]:)(.*)', draft_folder).groups()
parts = [p for p in windows_path.split('\\') if p] # Split path and filter empty parts
draft_image_path = os.path.join(windows_drive, *parts, draft_id, "assets", "image", material_name)
# Normalize path (ensure consistent separators)
draft_image_path = draft_image_path.replace('/', '\\')
else:
# macOS/Linux path processing
draft_image_path = os.path.join(draft_folder, draft_id, "assets", "image", material_name)
# Print path information
print('replace_path:', draft_image_path)
# Create image material
if draft_image_path:
image_material = draft.Video_material(path=None, material_type='photo', replace_path=draft_image_path, remote_url=image_url, material_name=material_name)
else:
image_material = draft.Video_material(path=None, material_type='photo', remote_url=image_url, material_name=material_name)
# Create target_timerange (image)
duration = end - start
target_timerange = trange(f"{start}s", f"{duration}s")
source_timerange = trange(f"{0}s", f"{duration}s")
# Create image segment
image_segment = draft.Video_segment(
image_material,
target_timerange=target_timerange,
source_timerange=source_timerange,
clip_settings=Clip_settings(
transform_y=transform_y,
scale_x=scale_x,
scale_y=scale_y,
transform_x=transform_x
)
)
# Add entrance animation (prioritize intro_animation, then use animation)
intro_anim = intro_animation if intro_animation is not None else animation
intro_animation_duration = intro_animation_duration if intro_animation_duration is not None else animation_duration
if intro_anim:
try:
if IS_CAPCUT_ENV:
animation_type = getattr(draft.CapCut_Intro_type, intro_anim)
else:
animation_type = getattr(draft.Intro_type, intro_anim)
image_segment.add_animation(animation_type, intro_animation_duration * 1e6) # Use microsecond unit for animation duration
except AttributeError:
raise ValueError(f"Warning: Unsupported entrance animation type {intro_anim}, this parameter will be ignored")
# Add exit animation
if outro_animation:
try:
if IS_CAPCUT_ENV:
outro_type = getattr(draft.CapCut_Outro_type, outro_animation)
else:
outro_type = getattr(draft.Outro_type, outro_animation)
image_segment.add_animation(outro_type, outro_animation_duration * 1e6) # Use microsecond unit for animation duration
except AttributeError:
raise ValueError(f"Warning: Unsupported exit animation type {outro_animation}, this parameter will be ignored")
# Add combo animation
if combo_animation:
try:
if IS_CAPCUT_ENV:
combo_type = getattr(draft.CapCut_Group_animation_type, combo_animation)
else:
combo_type = getattr(draft.Group_animation_type, combo_animation)
image_segment.add_animation(combo_type, combo_animation_duration * 1e6) # Use microsecond unit for animation duration
except AttributeError:
raise ValueError(f"Warning: Unsupported combo animation type {combo_animation}, this parameter will be ignored")
# Add transition effect
if transition:
try:
if IS_CAPCUT_ENV:
transition_type = getattr(draft.CapCut_Transition_type, transition)
else:
transition_type = getattr(draft.Transition_type, transition)
# Convert seconds to microseconds (multiply by 1000000)
duration_microseconds = int(transition_duration * 1000000) if transition_duration is not None else None
image_segment.add_transition(transition_type, duration=duration_microseconds)
except AttributeError:
raise ValueError(f"Warning: Unsupported transition type {transition}, this parameter will be ignored")
# Add mask effect
if mask_type:
try:
if IS_CAPCUT_ENV:
mask_type_enum = getattr(draft.CapCut_Mask_type, mask_type)
else:
mask_type_enum = getattr(draft.Mask_type, mask_type)
image_segment.add_mask(
script,
mask_type_enum, # Remove keyword name, pass as positional argument
center_x=mask_center_x,
center_y=mask_center_y,
size=mask_size,
rotation=mask_rotation,
feather=mask_feather,
invert=mask_invert,
rect_width=mask_rect_width,
round_corner=mask_round_corner
)
except:
raise ValueError(f"Unsupported mask type {mask_type}, supported types include: Linear, Mirror, Circle, Rectangle, Heart, Star")
# Add background blur effect
if background_blur is not None:
# Background blur level mapping table
blur_levels = {
1: 0.0625, # Light blur
2: 0.375, # Medium blur
3: 0.75, # Heavy blur
4: 1.0 # Maximum blur
}
# Validate background blur level
if background_blur not in blur_levels:
raise ValueError(f"Invalid background blur level {background_blur}, valid values are 1-4")
# Add background blur effect
image_segment.add_background_filling("blur", blur=blur_levels[background_blur])
# Add image segment to track
script.add_segment(image_segment, track_name=track_name)
return {
"draft_id": draft_id,
"draft_url": generate_draft_url(draft_id)
}
-86
View File
@@ -1,86 +0,0 @@
import pyJianYingDraft as draft
from pyJianYingDraft import trange
from typing import Optional, Dict
from pyJianYingDraft import exceptions
from create_draft import get_or_create_draft
from util import generate_draft_url
def add_sticker_impl(
resource_id: str,
start: float,
end: float,
draft_id: str = None,
transform_y: float = 0,
transform_x: float = 0,
alpha: float = 1.0,
flip_horizontal: bool = False,
flip_vertical: bool = False,
rotation: float = 0.0,
scale_x: float = 1.0,
scale_y: float = 1.0,
track_name: str = "sticker_main",
relative_index: int = 0,
width: int = 1080,
height: int = 1920
) -> Dict[str, str]:
"""
Add sticker to specified draft
:param resource_id: Sticker resource ID
:param start: Start time (seconds)
:param end: End time (seconds)
:param draft_id: Draft ID (optional, default None creates a new draft)
:param transform_y: Y-axis position (default 0, screen center)
:param transform_x: X-axis position (default 0, screen center)
:param alpha: Image opacity, range 0-1 (default 1.0, completely opaque)
:param flip_horizontal: Whether to flip horizontally (default False)
:param flip_vertical: Whether to flip vertically (default False)
:param rotation: Clockwise rotation angle, can be positive or negative (default 0.0)
:param scale_x: Horizontal scale ratio (default 1.0)
:param scale_y: Vertical scale ratio (default 1.0)
:param track_name: Track name
:param relative_index: Relative layer position (of the same track type), higher is closer to foreground (default 0)
:param width: Video width, default 1080
:param height: Video height, default 1920
:return: Updated draft information
"""
# Get or create draft
draft_id, script = get_or_create_draft(
draft_id=draft_id,
width=width,
height=height
)
# Add sticker track
if track_name is not None:
try:
imported_track = script.get_imported_track(draft.Track_type.sticker, name=track_name)
# If no exception is thrown, the track already exists
except exceptions.TrackNotFound:
# Track doesn't exist, create a new track
script.add_track(draft.Track_type.sticker, track_name=track_name, relative_index=relative_index)
else:
script.add_track(draft.Track_type.sticker, relative_index=relative_index)
# Create sticker segment
sticker_segment = draft.Sticker_segment(
resource_id,
trange(f"{start}s", f"{end-start}s"),
clip_settings=draft.Clip_settings(
transform_y=transform_y,
transform_x=transform_x,
alpha=alpha,
flip_horizontal=flip_horizontal,
flip_vertical=flip_vertical,
rotation=rotation,
scale_x=scale_x,
scale_y=scale_y
)
)
# Add sticker segment to track
script.add_segment(sticker_segment, track_name=track_name)
return {
"draft_id": draft_id,
"draft_url": generate_draft_url(draft_id)
}
-169
View File
@@ -1,169 +0,0 @@
import pyJianYingDraft as draft
from util import generate_draft_url, hex_to_rgb
from create_draft import get_or_create_draft
from pyJianYingDraft.text_segment import TextBubble, TextEffect
from typing import Optional
import requests
import os
def add_subtitle_impl(
srt_path: str,
draft_id: str = None,
track_name: str = "subtitle",
time_offset: float = 0,
# Font style parameters
font: str = None,
font_size: float = 8.0,
bold: bool = False,
italic: bool = False,
underline: bool = False,
font_color: str = "#FFFFFF",
# Border parameters
border_alpha: float = 1.0,
border_color: str = "#000000",
border_width: float = 0.0, # Default no border display
# Background parameters
background_color: str = "#000000",
background_style: int = 1,
background_alpha: float = 0.0, # Default no background display
# Bubble effect
bubble_effect_id: Optional[str] = None,
bubble_resource_id: Optional[str] = None,
# Text effect
effect_effect_id: Optional[str] = None,
# Image adjustment parameters
transform_x: float = 0.0,
transform_y: float = -0.8, # Default subtitle position at bottom
scale_x: float = 1.0,
scale_y: float = 1.0,
rotation: float = 0.0,
style_reference: draft.Text_segment = None,
vertical: bool = True, # New parameter: whether to display vertically
alpha: float = 0.4,
width: int = 1080, # New parameter
height: int = 1920 # New parameter
):
"""
Add subtitles to draft
:param srt_path: Subtitle file path or URL or SRT text content
:param draft_id: Draft ID, if None, create a new draft
:param track_name: Track name, default is "subtitle"
:param time_offset: Time offset, default is "0"s
:param text_style: Text style, default is None
:param clip_settings: Clip settings, default is None
:param style_reference: Style reference, default is None
:return: Draft information
"""
# Get or create draft
draft_id, script = get_or_create_draft(
draft_id=draft_id,
width=width,
height=height
)
# Process subtitle content
srt_content = None
# Check if it's a URL
if srt_path.startswith(('http://', 'https://')):
try:
response = requests.get(srt_path)
response.raise_for_status()
response.encoding = 'utf-8'
srt_content = response.text
except Exception as e:
raise Exception(f"Failed to download subtitle file: {str(e)}")
elif os.path.isfile(srt_path): # Check if it's a file
try:
with open(srt_path, 'r', encoding='utf-8-sig') as f:
srt_content = f.read()
except Exception as e:
raise Exception(f"Failed to read local subtitle file: {str(e)}")
else:
# If not a URL or local file, use content directly
srt_content = srt_path
# Handle possible escape characters
srt_content = srt_content.replace('\\n', '\n').replace('/n', '\n')
# Import subtitles
# Convert hexadecimal color to RGB
rgb_color = hex_to_rgb(font_color)
# Create text_border
text_border = None
if border_width > 0:
text_border = draft.Text_border(
alpha=border_alpha,
color=hex_to_rgb(border_color),
width=border_width
)
# Create text_background
text_background = None
if background_alpha > 0:
text_background = draft.Text_background(
color=background_color,
style=background_style,
alpha=background_alpha
)
# Create text_style
text_style = draft.Text_style(
size=font_size,
bold=bold,
italic=italic,
underline=underline,
color=rgb_color,
align=1, # Keep center alignment
vertical=vertical, # Use the passed vertical parameter
alpha=alpha # Use the passed alpha parameter
)
# Create bubble effect
text_bubble = None
if bubble_effect_id and bubble_resource_id:
text_bubble = TextBubble(
effect_id=bubble_effect_id,
resource_id=bubble_resource_id
)
# Create text effect
text_effect = None
if effect_effect_id:
text_effect = TextEffect(
effect_id=effect_effect_id,
resource_id=effect_effect_id
)
# Create clip_settings
clip_settings = draft.Clip_settings(
transform_x=transform_x,
transform_y=transform_y,
scale_x=scale_x,
scale_y=scale_y,
rotation=rotation
)
script.import_srt(
srt_content,
track_name=track_name,
time_offset=int(time_offset * 1000000), # Convert seconds to microseconds
text_style=text_style,
font=font,
clip_settings=clip_settings,
style_reference=style_reference,
border=text_border,
background=text_background,
bubble=text_bubble,
effect=text_effect
)
return {
"draft_id": draft_id,
"draft_url": generate_draft_url(draft_id)
}
-272
View File
@@ -1,272 +0,0 @@
import pyJianYingDraft as draft
from settings.local import IS_CAPCUT_ENV
from util import generate_draft_url, hex_to_rgb
from pyJianYingDraft import trange, Font_type
from typing import Optional, List # add List type hint
from pyJianYingDraft import exceptions
from create_draft import get_or_create_draft
from pyJianYingDraft.text_segment import TextBubble, TextEffect, TextStyleRange
def add_text_impl(
text: str,
start: float,
end: float,
draft_id: str | None = None, # Python 3.10+ 新语法
transform_y: float = -0.8,
transform_x: float = 0,
font: Optional[str] = None,
font_color: str = "#ffffff",
font_size: float = 8.0,
track_name: str = "text_main",
vertical: bool = False,
font_alpha: float = 1.0,
# Border parameters
border_alpha: float = 1.0,
border_color: str = "#000000",
border_width: float = 0.0,
# Background parameters
background_color: str = "#000000",
background_style: int = 1,
background_alpha: float = 0.0,
background_round_radius: float = 0.0,
background_height: float = 0.14,
background_width: float = 0.14,
background_horizontal_offset: float = 0.5,
background_vertical_offset: float = 0.5,
# Shadow parameters
shadow_enabled: bool = False,
shadow_alpha: float = 0.9,
shadow_angle: float = -45.0,
shadow_color: str = "#000000",
shadow_distance: float = 5.0,
shadow_smoothing: float = 0.15,
# Bubble effect
bubble_effect_id: str | None = None,
bubble_resource_id: str | None = None,
# Text effect
effect_effect_id: str | None = None,
intro_animation: str | None = None,
intro_duration: float = 0.5,
outro_animation: str | None = None,
outro_duration: float = 0.5,
width: int = 1080,
height: int = 1920,
fixed_width: float = -1, # Text fixed width ratio, default -1 means not fixed
fixed_height: float = -1, # Text fixed height ratio, default -1 means not fixed
# 多样式文本参数
text_styles: Optional[List[TextStyleRange]] = None, # 文本的不同部分的样式列表
):
"""
Add text subtitle to the specified draft (configurable parameter version)
:param text: Text content
:param start: Start time (seconds)
:param end: End time (seconds)
:param draft_id: Draft ID (optional, default None creates a new draft)
:param transform_y: Y-axis position (default -0.8, bottom of screen)
:param transform_x: X-axis position (default 0, center of screen)
:param font: Font name (supports all fonts in Font_type)
:param font_color: Font color #FFF0FF
:param font_size: Font size (float value, default 8.0)
:param track_name: Track name
:param vertical: Whether to display vertically (default False)
:param font_alpha: Text transparency, range 0.0-1.0 (default 1.0, completely opaque)
:param border_alpha: Border transparency, range 0.0-1.0 (default 1.0)
:param border_color: Border color (default black)
:param border_width: Border width (default 0.0, no border display)
:param background_color: Background color (default black)
:param background_style: Background style (default 1)
:param background_alpha: Background transparency (default 0.0, no background display)
:param background_round_radius: 背景圆角半径,范围0.0-1.0(默认0.0)
:param background_height: 背景高度,范围0.0-1.0(默认0.14
:param background_width: 背景宽度,范围0.0-1.0(默认0.14
:param background_horizontal_offset: 背景水平偏移,范围0.0-1.0(默认0.5)
:param background_vertical_offset: 背景垂直偏移,范围0.0-1.0(默认0.5)
:param shadow_enabled: 是否启用阴影(默认False)
:param shadow_alpha: 阴影透明度,范围0.0-1.0(默认0.9)
:param shadow_angle: 阴影角度,范围-180.0-180.0(默认-45.0
:param shadow_color: 阴影颜色(默认黑色)
:param shadow_distance: 阴影距离(默认5.0
:param shadow_smoothing: 阴影平滑度,范围0.0-1.0(默认0.15
:param bubble_effect_id: Bubble effect ID
:param bubble_resource_id: Bubble resource ID
:param effect_effect_id: Text effect ID
:param intro_animation: Intro animation type
:param intro_duration: Intro animation duration (seconds), default 0.5 seconds
:param outro_animation: Outro animation type
:param outro_duration: Outro animation duration (seconds), default 0.5 seconds
:param width: Video width (pixels)
:param height: Video height (pixels)
:param fixed_width: Text fixed width ratio, range 0.0-1.0, default -1 means not fixed
:param fixed_height: Text fixed height ratio, range 0.0-1.0, default -1 means not fixed
:param text_styles: 文本的不同部分的样式列表,每个元素是一个TextStyleRange
:return: Updated draft information
"""
# Validate if font is in Font_type
if font is None:
font_type = None
else:
try:
font_type = getattr(Font_type, font)
except:
available_fonts = [attr for attr in dir(Font_type) if not attr.startswith('_')]
raise ValueError(f"Unsupported font: {font}, please use one of the fonts in Font_type: {available_fonts}")
# Validate alpha value range
if not 0.0 <= font_alpha <= 1.0:
raise ValueError("alpha value must be between 0.0 and 1.0")
if not 0.0 <= border_alpha <= 1.0:
raise ValueError("border_alpha value must be between 0.0 and 1.0")
if not 0.0 <= background_alpha <= 1.0:
raise ValueError("background_alpha value must be between 0.0 and 1.0")
# Get or create draft
draft_id, script = get_or_create_draft(
draft_id=draft_id,
width=width,
height=height
)
# Add text track
if track_name is not None:
try:
imported_track = script.get_imported_track(draft.Track_type.text, name=track_name)
# If no exception is thrown, the track already exists
except exceptions.TrackNotFound:
# Track doesn't exist, create a new track
script.add_track(draft.Track_type.text, track_name=track_name)
else:
script.add_track(draft.Track_type.audio)
# Convert hexadecimal color to RGB tuple
try:
rgb_color = hex_to_rgb(font_color)
rgb_border_color = hex_to_rgb(border_color)
except ValueError as e:
raise ValueError(f"Color parameter error: {str(e)}")
# Create text_border
text_border = None
if border_width > 0:
text_border = draft.Text_border(
alpha=border_alpha,
color=rgb_border_color,
width=border_width
)
# Create text_background
text_background = None
if background_alpha > 0:
text_background = draft.Text_background(
color=background_color,
style=background_style,
alpha=background_alpha,
round_radius=background_round_radius,
height=background_height,
width=background_width,
horizontal_offset=background_horizontal_offset,
vertical_offset=background_vertical_offset
)
# 创建text_shadow (阴影)
text_shadow = None
if shadow_enabled:
text_shadow = draft.Text_shadow(
has_shadow=shadow_enabled,
alpha=shadow_alpha,
angle=shadow_angle,
color=shadow_color,
distance=shadow_distance,
smoothing=shadow_smoothing
)
# Create bubble effect
text_bubble = None
if bubble_effect_id and bubble_resource_id:
text_bubble = TextBubble(
effect_id=bubble_effect_id,
resource_id=bubble_resource_id
)
# Create text effect
text_effect = None
if effect_effect_id:
text_effect = TextEffect(
effect_id=effect_effect_id
)
# Convert ratio to pixel value
pixel_fixed_width = -1
pixel_fixed_height = -1
if fixed_width > 0:
pixel_fixed_width = int(fixed_width * script.width)
if fixed_height > 0:
pixel_fixed_height = int(fixed_height * script.height)
# Create text segment (using configurable parameters)
text_segment = draft.Text_segment(
text,
trange(f"{start}s", f"{end-start}s"),
font=font_type, # Use font from Font_type
style=draft.Text_style(
color=rgb_color,
size=font_size,
align=1,
vertical=vertical, # Set whether to display vertically
alpha=font_alpha # Set transparency
),
clip_settings=draft.Clip_settings(transform_y=transform_y, transform_x=transform_x),
border=text_border,
background=text_background,
shadow=text_shadow,
fixed_width=pixel_fixed_width,
fixed_height=pixel_fixed_height
)
# 应用多样式文本设置
if text_styles:
for style_range in text_styles:
# 验证范围有效性
if style_range.start < 0 or style_range.end > len(text) or style_range.start >= style_range.end:
raise ValueError(f"无效的文本范围: [{style_range.start}, {style_range.end}), 文本长度: {len(text)}")
# 应用样式到特定文本范围
text_segment.add_text_style(style_range)
if text_bubble:
text_segment.add_bubble(text_bubble.effect_id, text_bubble.resource_id)
if text_effect:
text_segment.add_effect(text_effect.effect_id)
# Add intro animation
if intro_animation:
try:
if IS_CAPCUT_ENV:
animation_type = getattr(draft.CapCut_Text_intro, intro_animation)
else:
animation_type = getattr(draft.Text_intro, intro_animation)
# Convert seconds to microseconds
duration_microseconds = int(intro_duration * 1000000)
text_segment.add_animation(animation_type, duration_microseconds) # Add intro animation, set duration
except:
print(f"Warning: Unsupported intro animation type {intro_animation}, this parameter will be ignored")
# Add outro animation
if outro_animation:
try:
if IS_CAPCUT_ENV:
animation_type = getattr(draft.CapCut_Text_outro, outro_animation)
else:
animation_type = getattr(draft.Text_outro, outro_animation)
# Convert seconds to microseconds
duration_microseconds = int(outro_duration * 1000000)
text_segment.add_animation(animation_type, duration_microseconds) # Add outro animation, set duration
except:
print(f"Warning: Unsupported outro animation type {outro_animation}, this parameter will be ignored")
# Add text segment to track
script.add_segment(text_segment, track_name=track_name)
return {
"draft_id": draft_id,
"draft_url": generate_draft_url(draft_id)
}
-169
View File
@@ -1,169 +0,0 @@
import pyJianYingDraft as draft
from pyJianYingDraft import exceptions
from create_draft import get_or_create_draft
from typing import Optional, Dict, List
from util import generate_draft_url
def add_video_keyframe_impl(
draft_id: Optional[str] = None,
track_name: str = "main",
property_type: str = "alpha",
time: float = 0.0,
value: str = "1.0",
property_types: Optional[List[str]] = None,
times: Optional[List[float]] = None,
values: Optional[List[str]] = None
) -> Dict[str, str]:
"""
Add keyframes to the specified segment
:param draft_id: Draft ID, if None or corresponding zip file not found, a new draft will be created
:param track_name: Track name, default "main"
:param property_type: Keyframe property type, supports the following values:
- position_x: Horizontal position, range [-1,1], 0 means center, 1 means rightmost
- position_y: Vertical position, range [-1,1], 0 means center, 1 means bottom
- rotation: Clockwise rotation angle
- scale_x: X-axis scale ratio (1.0 means no scaling), mutually exclusive with uniform_scale
- scale_y: Y-axis scale ratio (1.0 means no scaling), mutually exclusive with uniform_scale
- uniform_scale: Overall scale ratio (1.0 means no scaling), mutually exclusive with scale_x and scale_y
- alpha: Opacity, 1.0 means completely opaque
- saturation: Saturation, 0.0 means original saturation, range from -1.0 to 1.0
- contrast: Contrast, 0.0 means original contrast, range from -1.0 to 1.0
- brightness: Brightness, 0.0 means original brightness, range from -1.0 to 1.0
- volume: Volume, 1.0 means original volume
:param time: Keyframe time point (seconds), default 0.0
:param value: Keyframe value, format varies according to property_type:
- position_x/position_y: "0" means center position, range [-1,1]
- rotation: "45deg" means 45 degrees
- scale_x/scale_y/uniform_scale: "1.5" means scale up by 1.5 times
- alpha: "50%" means 50% opacity
- saturation/contrast/brightness: "+0.5" means increase by 0.5, "-0.5" means decrease by 0.5
- volume: "80%" means 80% of original volume
:param property_types: Batch mode: List of keyframe property types, e.g. ["alpha", "position_x", "rotation"]
:param times: Batch mode: List of keyframe time points (seconds), e.g. [0.0, 1.0, 2.0]
:param values: Batch mode: List of keyframe values, e.g. ["1.0", "0.5", "45deg"]
Note: property_types, times, values must be provided together and have equal lengths. If these parameters are provided, single keyframe parameters will be ignored
:return: Updated draft information
"""
# Get or create draft
draft_id, script = get_or_create_draft(
draft_id=draft_id
)
try:
# Get specified track
track = script.get_track(draft.Video_segment, track_name=track_name)
# Get segments in the track
segments = track.segments
if not segments:
raise Exception(f"No segments in track {track_name}")
# Determine the keyframes list to process
if property_types is not None or times is not None or values is not None:
# Batch mode: use three array parameters
if property_types is None or times is None or values is None:
raise Exception("In batch mode, property_types, times, values must be provided together")
if not (isinstance(property_types, list) and isinstance(times, list) and isinstance(values, list)):
raise Exception("property_types, times, values must all be list types")
if len(property_types) == 0:
raise Exception("In batch mode, parameter lists cannot be empty")
if not (len(property_types) == len(times) == len(values)):
raise Exception(f"property_types, times, values must have equal lengths, current lengths are: {len(property_types)}, {len(times)}, {len(values)}")
keyframes_to_process = [
{
"property_type": prop_type,
"time": t,
"value": val
}
for prop_type, t, val in zip(property_types, times, values)
]
else:
# Single mode: use original parameters
keyframes_to_process = [{
"property_type": property_type,
"time": time,
"value": value
}]
# Process each keyframe
added_count = 0
for i, kf in enumerate(keyframes_to_process):
try:
_add_single_keyframe(track, kf["property_type"], kf["time"], kf["value"])
added_count += 1
except Exception as e:
raise Exception(f"Failed to add keyframe #{i+1} (property_type={kf['property_type']}, time={kf['time']}, value={kf['value']}): {str(e)}")
result = {
"draft_id": draft_id,
"draft_url": generate_draft_url(draft_id)
}
# If in batch mode, return the number of added keyframes
if property_types is not None:
result["added_keyframes_count"] = added_count
return result
except exceptions.TrackNotFound:
raise Exception(f"Track named {track_name} not found")
except Exception as e:
raise Exception(f"Failed to add keyframe: {str(e)}")
def _add_single_keyframe(track, property_type: str, time: float, value: str):
"""
Internal function to add a single keyframe
"""
# Convert property type string to enum value, validate if property type is valid
try:
property_enum = getattr(draft.Keyframe_property, property_type)
except:
raise Exception(f"Unsupported keyframe property type: {property_type}")
# Parse value based on property type
try:
if property_type in ['position_x', 'position_y']:
# Handle position, range [0,1]
float_value = float(value)
if not -10 <= float_value <= 10:
raise ValueError(f"Value for {property_type} must be between -10 and 10")
elif property_type == 'rotation':
# Handle rotation angle
if value.endswith('deg'):
float_value = float(value[:-3])
else:
float_value = float(value)
elif property_type == 'alpha':
# Handle opacity
if value.endswith('%'):
float_value = float(value[:-1]) / 100
else:
float_value = float(value)
elif property_type == 'volume':
# Handle volume
if value.endswith('%'):
float_value = float(value[:-1]) / 100
else:
float_value = float(value)
elif property_type in ['saturation', 'contrast', 'brightness']:
# Handle saturation, contrast, brightness
if value.startswith('+'):
float_value = float(value[1:])
elif value.startswith('-'):
float_value = -float(value[1:])
else:
float_value = float(value)
else:
# Other properties directly convert to float
float_value = float(value)
except ValueError:
raise Exception(f"Invalid value format: {value}")
# If track object is provided, use the track's add_pending_keyframe method
track.add_pending_keyframe(property_type, time, value)
-240
View File
@@ -1,240 +0,0 @@
import os
import pyJianYingDraft as draft
import time
from settings.local import IS_CAPCUT_ENV
from util import generate_draft_url, is_windows_path, url_to_hash
from pyJianYingDraft import trange, Clip_settings
import re
from typing import Optional, Dict
from pyJianYingDraft import exceptions
from create_draft import get_or_create_draft
def add_video_track(
video_url: str,
draft_folder: Optional[str] = None,
width: int = 1080,
height: int = 1920,
start: float = 0,
end: Optional[float] = None,
target_start: float = 0,
draft_id: Optional[str] = None,
transform_y: float = 0,
scale_x: float = 1,
scale_y: float = 1,
transform_x: float = 0,
speed: float = 1.0,
track_name: str = "main",
relative_index: int = 0,
duration: Optional[float] = None, # Added duration parameter
transition: Optional[str] = None, # Transition type
transition_duration: Optional[float] = 0.5, # Transition duration (seconds)
# Mask related parameters
mask_type: Optional[str] = None, # Mask type
mask_center_x: float = 0.5, # Mask center X coordinate (0-1)
mask_center_y: float = 0.5, # Mask center Y coordinate (0-1)
mask_size: float = 1.0, # Mask size (0-1)
mask_rotation: float = 0.0, # Mask rotation angle (degrees)
mask_feather: float = 0.0, # Mask feather level (0-1)
mask_invert: bool = False, # Whether to invert mask
mask_rect_width: Optional[float] = None, # Rectangle mask width (only for rectangle mask)
mask_round_corner: Optional[float] = None, # Rectangle mask rounded corner (only for rectangle mask, 0-100)
volume: float = 1.0, # Volume level, default 1.0
background_blur: Optional[int] = None # Background blur level, optional values: 1 (light), 2 (medium), 3 (strong), 4 (maximum), default None (no background blur)
) -> Dict[str, str]:
"""
Add video track to specified draft
:param draft_folder: Draft folder path, optional parameter
:param video_url: Video URL
:param width: Video width, default 1080
:param height: Video height, default 1920
:param start: Source video start time (seconds), default 0
:param end: Source video end time (seconds), default None (use total video duration)
:param target_start: Target video start time (seconds), default 0
:param draft_id: Draft ID, if None or corresponding zip file not found, create new draft
:param transform_y: Y-axis transform, default 0
:param scale_x: X-axis scale, default 1
:param scale_y: Y-axis scale, default 1
:param transform_x: X-axis transform, default 0
:param speed: Video playback speed, default 1.0
:param track_name: When there is only one video, track name can be omitted
:param relative_index: Track rendering order index, default 0
:param duration: Video duration (seconds), if provided, skip duration detection
:param transition: Transition type, optional parameter
:param transition_duration: Transition duration (seconds), default uses the default duration of transition type
:param mask_type: Mask type (linear, mirror, circle, rectangle, heart, star), optional parameter
:param mask_center_x: Mask center X coordinate (0-1), default 0.5
:param mask_center_y: Mask center Y coordinate (0-1), default 0.5
:param mask_size: Mask size (0-1), default 1.0
:param mask_rotation: Mask rotation angle (degrees), default 0.0
:param mask_feather: Mask feather level (0-1), default 0.0
:param mask_invert: Whether to invert mask, default False
:param mask_rect_width: Rectangle mask width, only allowed when mask type is rectangle, represented as a proportion of material width
:param mask_round_corner: Rectangle mask rounded corner parameter, only allowed when mask type is rectangle, range 0~100
:param volume: Volume level, default 1.0 (0.0 is mute, 1.0 is original volume)
:param background_blur: Background blur level, optional values: 1 (light), 2 (medium), 3 (strong), 4 (maximum), default None (no background blur)
:return: Updated draft information, including draft_id and draft_url
"""
# Get or create draft
draft_id, script = get_or_create_draft(
draft_id=draft_id,
width=width,
height=height
)
# Check if video track exists, if not, add a default video track
try:
script.get_track(draft.Track_type.video, track_name=None)
except exceptions.TrackNotFound:
script.add_track(draft.Track_type.video, relative_index=0)
except NameError:
# If multiple video tracks exist (NameError), do nothing
pass
# Add video track (only when track doesn't exist)
if track_name is not None:
try:
imported_track=script.get_imported_track(draft.Track_type.video, name=track_name)
# If no exception is thrown, the track already exists
except exceptions.TrackNotFound:
# Track doesn't exist, create new track
script.add_track(draft.Track_type.video, track_name=track_name, relative_index=relative_index)
else:
script.add_track(draft.Track_type.video, relative_index=relative_index)
# If duration parameter is passed, use it preferentially; otherwise use default duration of 0 seconds, and get the real duration when downloading the draft
if duration is not None:
# Use the passed duration, skip duration retrieval and check
video_duration = duration
else:
# Use default duration of 0 seconds, and get the real duration when downloading the draft
video_duration = 0.0 # Default video duration is 0 seconds
# duration_result = get_video_duration(video_url)
# if not duration_result["success"]:
# print(f"Failed to get video duration: {duration_result['error']}")
# # Check if video duration exceeds 2 minutes
# if duration_result["output"] > 120: # 120 seconds = 2 minutes
# raise Exception(f"Video duration exceeds 2-minute limit, current duration: {duration_result['output']} seconds")
# video_duration = duration_result["output"]
# Generate local filename
material_name = f"video_{url_to_hash(video_url)}.mp4"
# local_video_path = download_video(video_url, draft_dir)
# Build draft_video_path
draft_video_path = None
if draft_folder:
# Detect input path type and process
if is_windows_path(draft_folder):
# Windows path processing
windows_drive, windows_path = re.match(r'([a-zA-Z]:)(.*)', draft_folder).groups()
parts = [p for p in windows_path.split('\\') if p] # Split path and filter empty parts
draft_video_path = os.path.join(windows_drive, *parts, draft_id, "assets", "video", material_name)
# Normalize path (ensure consistent separators)
draft_video_path = draft_video_path.replace('/', '\\')
else:
# macOS/Linux path processing
draft_video_path = os.path.join(draft_folder, draft_id, "assets", "video", material_name)
# Print path information
print('replace_path:', draft_video_path)
# Set video end time
video_end = end if end is not None else video_duration
# Calculate source video duration
source_duration = video_end - start
# Calculate target video duration (considering speed factor)
target_duration = source_duration / speed
# Create video clip
if draft_video_path:
video_material = draft.Video_material(material_type='video', replace_path=draft_video_path, remote_url=video_url, material_name=material_name, duration=video_duration, width=0, height=0)
else:
video_material = draft.Video_material(material_type='video', remote_url=video_url, material_name=material_name, duration = video_duration, width=0, height=0)
# Create source_timerange and target_timerange
source_timerange = trange(f"{start}s", f"{source_duration}s")
target_timerange = trange(f"{target_start}s", f"{target_duration}s")
video_segment = draft.Video_segment(
video_material,
target_timerange=target_timerange,
source_timerange=source_timerange,
speed=speed,
clip_settings=Clip_settings(
transform_y=transform_y,
scale_x=scale_x,
scale_y=scale_y,
transform_x=transform_x
),
volume=volume
)
# Add transition effect
if transition:
try:
# Get transition type
if IS_CAPCUT_ENV:
transition_type = getattr(draft.CapCut_Transition_type, transition)
else:
transition_type = getattr(draft.Transition_type, transition)
# Set transition duration (convert to microseconds)
duration_microseconds = int(transition_duration * 1e6)
# Add transition
video_segment.add_transition(transition_type, duration=duration_microseconds)
except AttributeError:
raise ValueError(f"Unsupported transition type: {transition}, transition setting skipped")
# Add mask effect
if mask_type:
try:
if IS_CAPCUT_ENV:
mask_type_enum = getattr(draft.CapCut_Mask_type, mask_type)
else:
mask_type_enum = getattr(draft.Mask_type, mask_type)
video_segment.add_mask(
script,
mask_type_enum,
center_x=mask_center_x,
center_y=mask_center_y,
size=mask_size,
rotation=mask_rotation,
feather=mask_feather,
invert=mask_invert,
rect_width=mask_rect_width,
round_corner=mask_round_corner
)
except:
raise ValueError(f"Unsupported mask type {mask_type}, supported types include: linear, mirror, circle, rectangle, heart, star")
# Add background blur effect
if background_blur is not None:
# Validate if background blur level is valid
if background_blur not in [1, 2, 3, 4]:
raise ValueError(f"Invalid background blur level: {background_blur}, valid values are: 1, 2, 3, 4")
# Map blur level to specific blur values
blur_values = {
1: 0.0625, # Light blur
2: 0.375, # Medium blur
3: 0.75, # Strong blur
4: 1.0 # Maximum blur
}
# Add background blur
video_segment.add_background_filling("blur", blur=blur_values[background_blur])
# Add video segment to track
# if imported_track is not None:
# imported_track.add_segment(video_segment)
# else:
script.add_segment(video_segment, track_name=track_name)
return {
"draft_id": draft_id,
"draft_url": generate_draft_url(draft_id)
}
-20
View File
@@ -1,20 +0,0 @@
{
"is_capcut_env": true, // Whether to use CapCut environment (true) or JianYing environment (false)
"draft_domain": "https://www.capcutapi.top", // Base domain for draft operations
"port": 30000, // Port number for the local server
"preview_router": "/draft/downloader", // Router path for preview functionality
"is_upload_draft": false, // Whether to upload drafts to remote storage
"oss_config": { // General OSS (Object Storage Service) configuration
"bucket_name": "your-bucket-name", // OSS bucket name for general storage
"access_key_id": "your-access-key-id", // Access key ID for OSS authentication
"access_key_secret": "your-access-key-secret", // Access key secret for OSS authentication
"endpoint": "https://your-endpoint.aliyuncs.com" // OSS service endpoint URL
},
"mp4_oss_config": { // MP4-specific OSS configuration
"bucket_name": "your-mp4-bucket-name", // OSS bucket name for MP4 files
"access_key_id": "your-access-key-id", // Access key ID for MP4 OSS authentication
"access_key_secret": "your-access-key-secret", // Access key secret for MP4 OSS authentication
"region": "your-region", // Region for MP4 storage
"endpoint": "http://your-custom-domain" // Custom domain endpoint for MP4 access
}
}
-20
View File
@@ -1,20 +0,0 @@
{
"is_capcut_env": true, // Whether to use CapCut environment (true) or JianYing environment (false)
"draft_domain": "https://www.capcutapi.top", // Base domain for draft operations
"port": 9001, // Port number for the local server
"preview_router": "/draft/downloader", // Router path for preview functionality
"is_upload_draft": false, // Whether to upload drafts to remote storage
"oss_config": { // General OSS (Object Storage Service) configuration
"bucket_name": "your-bucket-name", // OSS bucket name for general storage
"access_key_id": "your-access-key-id", // Access key ID for OSS authentication
"access_key_secret": "your-access-key-secret", // Access key secret for OSS authentication
"endpoint": "https://your-endpoint.aliyuncs.com" // OSS service endpoint URL
},
"mp4_oss_config": { // MP4-specific OSS configuration
"bucket_name": "your-mp4-bucket-name", // OSS bucket name for MP4 files
"access_key_id": "your-access-key-id", // Access key ID for MP4 OSS authentication
"access_key_secret": "your-access-key-secret", // Access key secret for MP4 OSS authentication
"region": "your-region", // Region for MP4 storage
"endpoint": "http://your-custom-domain" // Custom domain endpoint for MP4 access
}
}
+18
View File
@@ -0,0 +1,18 @@
# 项目常量定义
import os
# 保存剪映草稿的目录
DRAFT_DIR = os.path.join(os.path.dirname(__file__), "output", "draft")
# 临时文件目录
TEMP_DIR = os.path.join(os.path.dirname(__file__), "temp")
# 剪映草稿的下载路径
DRAFT_URL = os.getenv("DRAFT_URL", "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft")
# 将容器内的文件路径转成一个下载路径,执行替换操作,即将/app/ -> https://capcut-mate.jcaigc.cn/
DOWNLOAD_URL = os.getenv("DOWNLOAD_URL", "https://capcut-mate.jcaigc.cn/")
# 草稿提示URL
TIP_URL = os.getenv("TIP_URL", "https://docs.jcaigc.cn/")
-50
View File
@@ -1,50 +0,0 @@
import uuid
import pyJianYingDraft as draft
import time
from draft_cache import DRAFT_CACHE, update_cache
def create_draft(width=1080, height=1920):
"""
Create new CapCut draft
:param width: Video width, default 1080
:param height: Video height, default 1920
:return: (draft_name, draft_path, draft_id, draft_url)
"""
# Generate timestamp and draft_id
unix_time = int(time.time())
unique_id = uuid.uuid4().hex[:8] # Take the first 8 digits of UUID
draft_id = f"dfd_cat_{unix_time}_{unique_id}" # Use Unix timestamp and UUID combination
# Create CapCut draft with specified resolution
script = draft.Script_file(width, height)
# Store in global cache
update_cache(draft_id, script)
return script, draft_id
def get_or_create_draft(draft_id=None, width=1080, height=1920):
"""
Get or create CapCut draft
:param draft_id: Draft ID, if None or corresponding zip file not found, create new draft
:param width: Video width, default 1080
:param height: Video height, default 1920
:return: (draft_name, draft_path, draft_id, draft_dir, script)
"""
global DRAFT_CACHE # Declare use of global variable
if draft_id is not None and draft_id in DRAFT_CACHE:
# Get existing draft information from cache
print(f"Getting draft from cache: {draft_id}")
# Update last access time
update_cache(draft_id, DRAFT_CACHE[draft_id])
return draft_id, DRAFT_CACHE[draft_id]
# Create new draft logic
print("Creating new draft")
script, generate_draft_id = create_draft(
width=width,
height=height,
)
return generate_draft_id, script
+24
View File
@@ -0,0 +1,24 @@
services:
capcut-mate:
image: gogoshine/capcut-mate:latest
#image: gogoshine/capcut-mate:sha-190a61f
ports:
- "60000:60000" # 将主机的 60000 端口映射到容器内部的 60000 端口
volumes:
- /opt/1panel/apps/openresty/openresty/www/sites/cm.jcaigc.cn/index/output:/app/output # 挂载配置文件目录
- /etc/localtime:/etc/localtime:ro # 挂载主机时区
- /etc/timezone:/etc/timezone:ro # 挂载时区名称(可选)
extra_hosts: # 用于容器内访问主机的服务
- "host.docker.internal:10.0.16.6"
environment:
# 草稿下载URL
- DRAFT_URL=https://cm.jcaigc.cn/openapi/v1/get_draft
# 用于将容器内部的文件路径转成URL,本质是将/app/替换成DOWNLOAD_URL得到下载路径
- DOWNLOAD_URL=https://cm.jcaigc.cn/
mem_limit: 1G # 内存限制
memswap_limit: 2G # 总内存(物理内存 + Swap)限制
cpus: '1.6' # CPU使用率限制为150%,即容器最多可以使用1.5个完整的CPU核心
oom_score_adj: -500 # 调整 OOM 杀手优先级
restart: unless-stopped # 除非手动停止,否则总是重启容器
container_name: capcut-mate # 这里指容器名称,非必需,不指定时,名称为:<项目名称>-<服务名称>-<序号>
#entrypoint: ["/bin/sh", "-c", "sleep 10000"]
-274
View File
@@ -1,274 +0,0 @@
# CapCut Mate API 文档中心
欢迎使用 CapCut Mate API 文档!本文档提供了所有 RESTful API 接口的详细说明。
---
## 📚 文档导航
### 🎬 草稿管理
| 接口 | 文档 | 说明 |
|------|------|------|
| `POST /create_draft` | [create_draft.md](create_draft.md) | 创建新的剪映草稿 |
| `POST /save_draft` | [save_draft.md](save_draft.md) | 保存草稿到本地 |
| `POST /query_script` | - | 查询草稿脚本内容 |
| `POST /generate_draft_url` | - | 生成草稿预览 URL |
### 🎥 媒体素材
| 接口 | 文档 | 说明 |
|------|------|------|
| `POST /add_video` | [add_video.md](add_video.md) | 添加视频到草稿 |
| `POST /add_audio` | [add_audio.md](add_audio.md) | 添加音频到草稿 |
| `POST /add_image` | [add_image.md](add_image.md) | 添加图片到草稿 |
| `POST /add_text` | [add_text.md](add_text.md) | 添加文字到草稿 |
| `POST /add_subtitle` | - | 添加字幕(SRT格式) |
| `POST /add_sticker` | - | 添加贴纸到草稿 |
### 🎨 特效和动画
| 接口 | 文档 | 说明 |
|------|------|------|
| `POST /add_effect` | - | 添加视频特效 |
| `POST /add_video_keyframe` | - | 添加关键帧动画 |
| `GET /get_transition_types` | [get_transition_types.md](get_transition_types.md) | 获取转场类型列表 |
| `GET /get_mask_types` | [get_mask_types.md](get_mask_types.md) | 获取蒙版类型列表 |
### 🎭 动画类型查询
| 接口 | 文档 | 说明 |
|------|------|------|
| `GET /get_intro_animation_types` | - | 获取入场动画类型 |
| `GET /get_outro_animation_types` | - | 获取出场动画类型 |
| `GET /get_combo_animation_types` | - | 获取组合动画类型 |
| `GET /get_text_intro_types` | - | 获取文字入场动画 |
| `GET /get_text_outro_types` | - | 获取文字出场动画 |
| `GET /get_text_loop_anim_types` | - | 获取文字循环动画 |
### 📋 资源查询
| 接口 | 文档 | 说明 |
|------|------|------|
| `GET /get_font_types` | - | 获取可用字体列表 |
| `GET /get_audio_effect_types` | - | 获取音效类型列表 |
| `GET /get_video_scene_effect_types` | - | 获取场景特效类型 |
| `GET /get_video_character_effect_types` | - | 获取人物特效类型 |
### 📊 任务查询
| 接口 | 文档 | 说明 |
|------|------|------|
| `POST /query_draft_status` | - | 查询草稿保存状态 |
---
## 🚀 快速开始
### 1. 创建草稿并添加内容
```python
import requests
base_url = "http://localhost:9001"
# 1. 创建草稿
response = requests.post(f"{base_url}/create_draft", json={
"width": 1080,
"height": 1920
})
draft_id = response.json()['output']['draft_id']
# 2. 添加视频
requests.post(f"{base_url}/add_video", json={
"video_url": "https://example.com/video.mp4",
"draft_id": draft_id,
"start": 0,
"end": 10
})
# 3. 添加文字
requests.post(f"{base_url}/add_text", json={
"text": "Hello World",
"start": 0,
"end": 5,
"draft_id": draft_id,
"font_size": 12.0,
"font_color": "#FFFFFF"
})
# 4. 保存草稿
requests.post(f"{base_url}/save_draft", json={
"draft_id": draft_id
})
```
---
## 📖 通用说明
### 接口基础信息
- **服务地址**: `http://localhost:9001`
- **Content-Type**: `application/json`
- **字符编码**: UTF-8
### 通用响应格式
所有接口都返回统一的 JSON 格式:
```json
{
"success": true, // 请求是否成功
"output": {}, // 成功时的返回数据
"error": "" // 失败时的错误信息
}
```
### 通用参数说明
#### 画布尺寸
| 类型 | 宽度 | 高度 | 说明 |
|------|------|------|------|
| 竖屏 | 1080 | 1920 | 抖音、快手等短视频 |
| 横屏 | 1920 | 1080 | YouTube、B站横屏 |
| 方形 | 1080 | 1080 | Instagram 等 |
#### 坐标系统
- **transform_x/y**: 相对坐标,范围 -1.0 到 1.0
- `0` 表示中心位置
- `transform_y = -1.0` 表示顶部
- `transform_y = 1.0` 表示底部
- `transform_x = -1.0` 表示左侧
- `transform_x = 1.0` 表示右侧
#### 时间参数
- **start**: 素材开始时间(秒)
- **end**: 素材结束时间(秒)
- **target_start**: 素材在时间轴上的起始位置(秒)
- **duration**: 素材显示时长(秒)
#### 颜色格式
使用 16 进制颜色码,格式为 `#RRGGBB`,例如:
- `#FF0000` - 红色
- `#00FF00` - 绿色
- `#0000FF` - 蓝色
- `#FFFFFF` - 白色
- `#000000` - 黑色
---
## 🔧 常见问题
### Q: 如何获取 draft_id
A: 调用 `/create_draft` 接口会返回 draft_id,保存它用于后续操作。
### Q: 如何预览草稿?
A: 使用返回的 `draft_url` 在浏览器中预览,或调用 `/generate_draft_url` 生成预览链接。
### Q: 如何导入剪映?
A: 调用 `/save_draft` 保存草稿后,将生成的文件夹复制到剪映的草稿目录。
### Q: 支持哪些媒体格式?
A:
- **视频**: MP4, MOV, AVI, MKV 等
- **音频**: MP3, WAV, AAC, M4A 等
- **图片**: JPG, PNG, GIF, WebP 等
### Q: 如何添加转场效果?
A: 在 `add_video``add_image` 时设置 `transition``transition_duration` 参数。
### Q: 如何使用蒙版?
A: 先调用 `/get_mask_types` 获取可用蒙版,然后在 `add_video``add_image` 时设置蒙版参数。
---
## 📝 注意事项
1. **草稿 ID**: 创建草稿后务必保存返回的 draft_id
2. **URL 格式**: 所有媒体 URL 必须是可访问的完整地址
3. **参数验证**: 注意必填参数和参数类型
4. **时间重叠**: 注意不同素材的时间轴不要冲突
5. **性能考虑**: 大文件和复杂效果会影响处理速度
---
## 🌟 最佳实践
### 1. 错误处理
```python
response = requests.post(url, json=data)
result = response.json()
if result['success']:
print(f"Success: {result['output']}")
else:
print(f"Error: {result['error']}")
```
### 2. 批量操作
```python
draft_id = create_draft()
# 添加多个视频
for video_url in video_list:
add_video(video_url, draft_id)
# 最后保存
save_draft(draft_id)
```
### 3. 动画效果组合
```python
# 先获取可用动画
intro_types = get_intro_animation_types()
transition_types = get_transition_types()
# 使用动画
add_image(
image_url=url,
intro_animation=intro_types[0]['name'],
transition=transition_types[0]['name']
)
```
---
## 🔗 相关资源
- [GitHub 仓库](https://github.com/sun-guannan/CapCutAPI)
- [在线体验](https://www.capcutapi.top)
- [问题反馈](https://github.com/sun-guannan/CapCutAPI/issues)
---
## 📧 技术支持
如有问题,请联系:
- **Email**: sguann2023@gmail.com
- **GitHub Issues**: https://github.com/sun-guannan/CapCutAPI/issues
---
## 📅 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2025-10-21 | 初始版本,包含主要接口文档 |
---
**© 2025 CapCut Mate - 让视频编辑更简单**
-388
View File
@@ -1,388 +0,0 @@
# add_audio 接口文档
## 接口概述
添加音频到剪映草稿中,支持音频裁剪、音量调节、变速、音效等功能。
---
## 接口信息
### RESTful API 端点
```
POST /add_audio
```
### Content-Type
```
application/json
```
---
## 请求参数
### 请求体 (JSON)
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| **audio_url** | string | **是** | - | 音频文件的 URL 地址(必需参数) |
| draft_folder | string | 否 | null | 草稿文件夹路径 |
| draft_id | string | 否 | null | 草稿 ID,不提供则创建新草稿 |
| width | integer | 否 | 1080 | 画布宽度(像素) |
| height | integer | 否 | 1920 | 画布高度(像素) |
| start | number | 否 | 0 | 音频起始时间(秒) |
| end | number | 否 | null | 音频结束时间(秒),null 表示到音频末尾 |
| target_start | number | 否 | 0 | 音频在时间轴上的起始位置(秒) |
| duration | number | 否 | null | 音频显示时长(秒) |
### 播放控制参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| volume | number | 否 | 1.0 | 音量大小,范围 0.0 到 1.0 |
| speed | number | 否 | 1.0 | 播放速度,1.0 为正常速度 |
### 轨道参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| track_name | string | 否 | "audio_main" | 音频轨道名称 |
### 音效参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| effect_type | string | 否 | null | 音效类型名称 |
| effect_params | array | 否 | null | 音效参数列表 |
---
## 响应参数
### 响应体 (JSON)
| 参数名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 请求是否成功 |
| output | object/string | 成功时返回草稿结果信息 |
| error | string | 失败时的错误信息 |
### 成功响应的 output 字段
| 参数名 | 类型 | 说明 |
|--------|------|------|
| draft_id | string | 草稿唯一标识符 |
| draft_url | string | 草稿预览 URL |
---
## 请求示例
### 示例 1: 基础音频添加
```bash
curl -X POST http://localhost:9001/add_audio \
-H "Content-Type: application/json" \
-d '{
"audio_url": "https://example.com/music.mp3"
}'
```
**请求体 (JSON):**
```json
{
"audio_url": "https://example.com/music.mp3"
}
```
### 示例 2: 添加背景音乐(降低音量)
```bash
curl -X POST http://localhost:9001/add_audio \
-H "Content-Type: application/json" \
-d '{
"audio_url": "https://example.com/bgm.mp3",
"draft_id": "dfd_12345",
"start": 0,
"end": 30,
"volume": 0.3,
"track_name": "audio_bgm"
}'
```
**请求体 (JSON):**
```json
{
"audio_url": "https://example.com/bgm.mp3",
"draft_id": "dfd_12345",
"start": 0,
"end": 30,
"volume": 0.3,
"track_name": "audio_bgm"
}
```
### 示例 3: 添加音效并加速
```bash
curl -X POST http://localhost:9001/add_audio \
-H "Content-Type: application/json" \
-d '{
"audio_url": "https://example.com/sound_effect.wav",
"draft_id": "dfd_12345",
"target_start": 5.0,
"duration": 2.0,
"speed": 1.5,
"volume": 0.8,
"track_name": "audio_sfx"
}'
```
**请求体 (JSON):**
```json
{
"audio_url": "https://example.com/sound_effect.wav",
"draft_id": "dfd_12345",
"target_start": 5.0,
"duration": 2.0,
"speed": 1.5,
"volume": 0.8,
"track_name": "audio_sfx"
}
```
### 示例 4: 添加带音效的音频
```bash
curl -X POST http://localhost:9001/add_audio \
-H "Content-Type: application/json" \
-d '{
"audio_url": "https://example.com/voice.mp3",
"draft_id": "dfd_12345",
"effect_type": "reverb",
"effect_params": [0.5, 0.3],
"volume": 1.0
}'
```
**请求体 (JSON):**
```json
{
"audio_url": "https://example.com/voice.mp3",
"draft_id": "dfd_12345",
"effect_type": "reverb",
"effect_params": [0.5, 0.3],
"volume": 1.0
}
```
### 示例 5: Python 请求示例
```python
import requests
url = "http://localhost:9001/add_audio"
headers = {
"Content-Type": "application/json"
}
data = {
"audio_url": "https://example.com/music.mp3",
"draft_id": "dfd_abc123",
"start": 10,
"end": 40,
"target_start": 0,
"volume": 0.5,
"speed": 1.0,
"track_name": "audio_main"
}
response = requests.post(url, json=data, headers=headers)
result = response.json()
print(f"Success: {result['success']}")
if result['success']:
print(f"Draft ID: {result['output']['draft_id']}")
print(f"Draft URL: {result['output']['draft_url']}")
else:
print(f"Error: {result['error']}")
```
---
## 响应示例
### 成功响应
**状态码:** 200 OK
```json
{
"success": true,
"output": {
"draft_id": "dfd_1234567890abcdef",
"draft_url": "http://example.com/preview?draft_id=dfd_1234567890abcdef"
},
"error": ""
}
```
### 失败响应 - 缺少必需参数
**状态码:** 200 OK
```json
{
"success": false,
"output": "",
"error": "Hi, the required parameters 'audio_url' are missing."
}
```
### 失败响应 - 处理错误
**状态码:** 200 OK
```json
{
"success": false,
"output": "",
"error": "Error occurred while processing audio: Invalid audio format."
}
```
---
## 错误码说明
| 错误信息 | 说明 | 解决方案 |
|---------|------|---------|
| "Hi, the required parameters 'audio_url' are missing." | 缺少必需的 audio_url 参数 | 请在请求体中提供 audio_url 参数 |
| "Error occurred while processing audio: ..." | 音频处理过程中出错 | 检查音频 URL 是否有效,格式是否支持 |
---
## 使用场景
### 场景 1: 添加背景音乐
```json
{
"audio_url": "https://example.com/bgm.mp3",
"volume": 0.2,
"track_name": "audio_bgm"
}
```
### 场景 2: 添加配音
```json
{
"audio_url": "https://example.com/voiceover.mp3",
"target_start": 2.0,
"duration": 15.0,
"volume": 1.0,
"track_name": "audio_voice"
}
```
### 场景 3: 添加音效
```json
{
"audio_url": "https://example.com/swoosh.wav",
"target_start": 5.5,
"duration": 0.5,
"volume": 0.8,
"track_name": "audio_sfx"
}
```
### 场景 4: 音频循环
```json
{
"audio_url": "https://example.com/loop.mp3",
"start": 0,
"end": 10,
"volume": 0.4,
"speed": 1.0
}
```
### 场景 5: 音频变速(慢放)
```json
{
"audio_url": "https://example.com/speech.mp3",
"speed": 0.75,
"volume": 1.0
}
```
---
## 音频格式支持
| 格式 | 扩展名 | 说明 |
|------|--------|------|
| MP3 | .mp3 | 最常用,兼容性好 |
| WAV | .wav | 无损音质,文件较大 |
| AAC | .aac, .m4a | 高质量压缩格式 |
| OGG | .ogg | 开源格式 |
| FLAC | .flac | 无损压缩 |
---
## 注意事项
1. **必需参数**: `audio_url` 是唯一的必需参数
2. **时间参数**: `start``end` 的单位都是秒,支持小数
3. **音量范围**: volume 的有效范围是 0.0(静音)到 1.0(原始音量)
4. **速度调节**: speed 可以大于 1(加速)或小于 1(减速),建议范围 0.5-2.0
5. **音频格式**: 支持常见音频格式(MP3, WAV, AAC 等)
6. **URL 要求**: audio_url 必须是可访问的完整 URL
7. **多轨道**: 可以通过不同的 track_name 添加多个音频轨道
8. **时长优先级**: 如果同时提供 `end``duration``duration` 优先级更高
---
## 音效类型
可通过 `/get_audio_effect_types` 接口获取支持的音效类型:
- **Tone effects**: 变调效果(如低音、高音)
- **Scene effects**: 场景效果(如回声、混响)
- **Speech to song**: 语音转唱歌
---
## 相关接口
- `POST /create_draft` - 创建新草稿
- `POST /save_draft` - 保存草稿
- `GET /get_audio_effect_types` - 获取可用音效类型
- `POST /add_video` - 添加视频
- `POST /add_text` - 添加文字
---
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2025-10-21 | 初始版本 |
---
## 技术支持
如有问题,请联系:
- Email: sguann2023@gmail.com
- GitHub Issues: https://github.com/sun-guannan/CapCutAPI/issues
+619
View File
@@ -0,0 +1,619 @@
# ADD_AUDIOS API 接口文档
## 接口信息
```
POST /openapi/capcut-mate/v1/add_audios
```
## 功能描述
批量向现有草稿中添加音频素材。该接口支持添加多个音频文件到剪映草稿,为视频创建背景音乐、音效、旁白等音频内容。音频将被添加到独立的音频轨道中,不会影响视频内容。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"audio_infos": "[{\"audio_url\":\"https://assets.jcaigc.cn/audio1.mp3\",\"start\":0,\"end\":5000000,\"duration\":10000000,\"volume\":0.8,\"fade_in\":1000000,\"fade_out\":1000000}]"
}
```
### 主要参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| draft_url | string | ✅ | - | 目标草稿的完整URL |
| audio_infos | string | ✅ | - | 音频信息数组的JSON字符串 |
### audio_infos 数组结构
audio_infos是一个JSON字符串,解析后为数组,每个元素包含以下字段:
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| audio_url | string | ✅ | - | 音频文件的URL地址 |
| start | number | ✅ | - | 音频开始播放时间(微秒) |
| end | number | ✅ | - | 音频结束播放时间(微秒) |
| duration | number | ✅ | - | 音频总时长(微秒) |
| volume | number | ❌ | 1.0 | 音量大小(0-1) |
| fade_in | number | ❌ | 0 | 淡入时长(微秒) |
| fade_out | number | ❌ | 0 | 淡出时长(微秒) |
### 参数详解
#### 时间参数
- **start**: 音频在时间轴上的开始时间,单位为微秒(1秒 = 1,000,000微秒)
- **end**: 音频在时间轴上的结束时间,单位为微秒
- **duration**: 音频文件的总时长,用于素材创建,单位为微秒
- **播放时长**: 实际播放时长 = end - start
#### 音量控制
- **volume**: 音频音量大小
- 1.0 = 原始音量
- 0.5 = 一半音量
- 0.0 = 静音
- 范围:0.0 - 1.0
#### 淡入淡出效果
- **fade_in**: 淡入效果时长
- 0 = 无淡入效果
- 建议范围:500,000 - 3,000,000微秒(0.5-3秒)
- **fade_out**: 淡出效果时长
- 0 = 无淡出效果
- 建议范围:500,000 - 3,000,000微秒(0.5-3秒)
## 响应格式
### 成功响应 (200)
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"track_id": "audio-track-uuid",
"audio_ids": ["audio1-uuid", "audio2-uuid", "audio3-uuid"]
}
```
### 响应字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| draft_url | string | 更新后的草稿URL |
| track_id | string | 音频轨道ID |
| audio_ids | array | 添加的音频ID列表 |
### 错误响应 (4xx/5xx)
```json
{
"detail": "错误信息描述"
}
```
## 使用示例
### cURL 示例
#### 1. 基本音频添加
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_audios \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"audio_infos": "[{\"audio_url\":\"https://assets.jcaigc.cn/bgm.mp3\",\"start\":0,\"end\":10000000,\"duration\":15000000,\"volume\":0.8}]"
}'
```
#### 2. 多音频批量添加
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_audios \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"audio_infos": "[{\"audio_url\":\"https://assets.jcaigc.cn/intro.mp3\",\"start\":0,\"end\":3000000,\"duration\":5000000,\"volume\":1.0,\"fade_in\":500000},{\"audio_url\":\"https://assets.jcaigc.cn/bgm.mp3\",\"start\":3000000,\"end\":30000000,\"duration\":35000000,\"volume\":0.6}]"
}'
```
#### 3. 带淡入淡出效果的音频
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_audios \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"audio_infos": "[{\"audio_url\":\"https://assets.jcaigc.cn/outro.mp3\",\"start\":25000000,\"end\":30000000,\"duration\":8000000,\"volume\":0.9,\"fade_in\":1000000,\"fade_out\":2000000}]"
}'
```
### JavaScript 示例
```javascript
const addAudios = async (draftUrl, audioConfig) => {
const response = await fetch('/openapi/capcut-mate/v1/add_audios', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
draft_url: draftUrl,
...audioConfig
})
});
return response.json();
};
// 基本音频添加
const basicAudio = {
audio_infos: JSON.stringify([
{
audio_url: "https://assets.jcaigc.cn/bgm.mp3",
start: 0,
end: 10000000,
duration: 15000000,
volume: 0.8
}
])
};
// 音频序列
const audioSequence = {
audio_infos: JSON.stringify([
{
audio_url: "https://assets.jcaigc.cn/intro.mp3",
start: 0,
end: 3000000,
duration: 5000000,
volume: 1.0,
fade_in: 500000
},
{
audio_url: "https://assets.jcaigc.cn/main-bgm.mp3",
start: 2000000,
end: 25000000,
duration: 30000000,
volume: 0.6
},
{
audio_url: "https://assets.jcaigc.cn/outro.mp3",
start: 24000000,
end: 28000000,
duration: 6000000,
volume: 0.9,
fade_out: 1500000
}
])
};
// 音效组合
const soundEffects = {
audio_infos: JSON.stringify([
{
audio_url: "https://assets.jcaigc.cn/applause.mp3",
start: 5000000,
end: 8000000,
duration: 4000000,
volume: 0.7
},
{
audio_url: "https://assets.jcaigc.cn/transition.mp3",
start: 12000000,
end: 13500000,
duration: 2000000,
volume: 0.5
}
])
};
try {
const result1 = await addAudios(draftUrl, basicAudio);
const result2 = await addAudios(draftUrl, audioSequence);
const result3 = await addAudios(draftUrl, soundEffects);
console.log('音频添加成功:', {
basic: result1,
sequence: result2,
effects: result3
});
} catch (error) {
console.error('添加失败:', error);
}
```
### 高级JavaScript示例
```javascript
class AudioManager {
constructor(baseUrl = 'https://capcut-mate.jcaigc.cn') {
this.baseUrl = baseUrl;
}
async addAudios(draftUrl, audioConfig) {
const response = await fetch(`${this.baseUrl}/openapi/capcut-mate/v1/add_audios`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
draft_url: draftUrl,
...audioConfig
})
});
return response.json();
}
// 创建背景音乐
createBackgroundMusic(audioUrl, totalDuration, volume = 0.6, loop = false) {
const audios = [];
if (loop) {
// 循环播放逻辑
let currentTime = 0;
while (currentTime < totalDuration) {
audios.push({
audio_url: audioUrl,
start: currentTime,
end: Math.min(currentTime + 30000000, totalDuration), // 假设30秒循环
duration: 30000000,
volume: volume
});
currentTime += 30000000;
}
} else {
audios.push({
audio_url: audioUrl,
start: 0,
end: totalDuration,
duration: totalDuration,
volume: volume
});
}
return {
audio_infos: JSON.stringify(audios)
};
}
// 创建音频序列
createAudioSequence(audioList, crossFadeDuration = 1000000) {
const audios = [];
let currentTime = 0;
audioList.forEach((audio, index) => {
const audioInfo = {
audio_url: audio.url,
start: currentTime,
end: currentTime + audio.playDuration,
duration: audio.totalDuration,
volume: audio.volume || 1.0
};
// 添加交叉淡入淡出
if (index > 0) {
audioInfo.fade_in = crossFadeDuration;
// 调整前一个音频的淡出
if (audios[index - 1]) {
audios[index - 1].fade_out = crossFadeDuration;
}
}
// 最后一个音频淡出
if (index === audioList.length - 1) {
audioInfo.fade_out = audio.fadeOut || crossFadeDuration;
}
audios.push(audioInfo);
currentTime += audio.playDuration - (index > 0 ? crossFadeDuration : 0);
});
return {
audio_infos: JSON.stringify(audios)
};
}
// 创建音效轨道
createSoundEffects(effects) {
const audios = effects.map(effect => ({
audio_url: effect.url,
start: effect.startTime,
end: effect.startTime + effect.duration,
duration: effect.duration,
volume: effect.volume || 0.7,
fade_in: effect.fadeIn || 0,
fade_out: effect.fadeOut || 0
}));
return {
audio_infos: JSON.stringify(audios)
};
}
// 创建旁白音频
createNarration(narrationList) {
const audios = narrationList.map(narration => ({
audio_url: narration.url,
start: narration.startTime,
end: narration.startTime + narration.duration,
duration: narration.duration,
volume: narration.volume || 0.9,
fade_in: 200000, // 0.2秒淡入
fade_out: 200000 // 0.2秒淡出
}));
return {
audio_infos: JSON.stringify(audios)
};
}
// 批量处理音频
async batchProcessAudios(draftUrl, audioConfigs) {
const results = [];
for (const config of audioConfigs) {
try {
const result = await this.addAudios(draftUrl, config);
results.push(result);
// 添加延迟避免请求过快
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
console.error('音频处理失败:', error);
results.push({ error: error.message });
}
}
return results;
}
}
// 使用示例
const audioManager = new AudioManager();
// 创建背景音乐
const bgm = audioManager.createBackgroundMusic(
"https://assets.jcaigc.cn/bgm.mp3",
60000000, // 60秒
0.6,
true // 循环播放
);
// 创建音频序列
const sequence = audioManager.createAudioSequence([
{
url: "https://assets.jcaigc.cn/intro.mp3",
playDuration: 5000000,
totalDuration: 5000000,
volume: 1.0
},
{
url: "https://assets.jcaigc.cn/main.mp3",
playDuration: 20000000,
totalDuration: 25000000,
volume: 0.8
},
{
url: "https://assets.jcaigc.cn/outro.mp3",
playDuration: 3000000,
totalDuration: 3000000,
volume: 1.0,
fadeOut: 2000000
}
]);
// 创建音效
const effects = audioManager.createSoundEffects([
{
url: "https://assets.jcaigc.cn/whoosh.mp3",
startTime: 10000000,
duration: 1500000,
volume: 0.5
},
{
url: "https://assets.jcaigc.cn/ding.mp3",
startTime: 25000000,
duration: 1000000,
volume: 0.8
}
]);
// 批量处理
await audioManager.batchProcessAudios(draftUrl, [bgm, sequence, effects]);
```
### Python 示例
```python
import requests
import json
from typing import List, Dict, Optional
class AudioProcessor:
def __init__(self, base_url="https://capcut-mate.jcaigc.cn"):
self.base_url = base_url
def add_audios(self, draft_url: str, audio_config: Dict) -> Dict:
response = requests.post(
f'{self.base_url}/openapi/capcut-mate/v1/add_audios',
headers={'Content-Type': 'application/json'},
json={
"draft_url": draft_url,
**audio_config
}
)
return response.json()
def create_background_music(self, audio_url: str, total_duration: int,
volume: float = 0.6, loop: bool = False) -> Dict:
"""创建背景音乐"""
audios = []
if loop:
current_time = 0
audio_duration = 30000000 # 假设30秒循环
while current_time < total_duration:
end_time = min(current_time + audio_duration, total_duration)
audios.append({
"audio_url": audio_url,
"start": current_time,
"end": end_time,
"duration": audio_duration,
"volume": volume
})
current_time += audio_duration
else:
audios.append({
"audio_url": audio_url,
"start": 0,
"end": total_duration,
"duration": total_duration,
"volume": volume
})
return {"audio_infos": json.dumps(audios)}
def create_audio_sequence(self, audio_list: List[Dict],
cross_fade_duration: int = 1000000) -> Dict:
"""创建音频序列"""
audios = []
current_time = 0
for i, audio in enumerate(audio_list):
audio_info = {
"audio_url": audio["url"],
"start": current_time,
"end": current_time + audio["play_duration"],
"duration": audio["total_duration"],
"volume": audio.get("volume", 1.0)
}
# 添加交叉淡入淡出
if i > 0:
audio_info["fade_in"] = cross_fade_duration
if audios:
audios[-1]["fade_out"] = cross_fade_duration
# 最后一个音频淡出
if i == len(audio_list) - 1:
audio_info["fade_out"] = audio.get("fade_out", cross_fade_duration)
audios.append(audio_info)
current_time += audio["play_duration"] - (cross_fade_duration if i > 0 else 0)
return {"audio_infos": json.dumps(audios)}
def create_sound_effects(self, effects: List[Dict]) -> Dict:
"""创建音效轨道"""
audios = []
for effect in effects:
audios.append({
"audio_url": effect["url"],
"start": effect["start_time"],
"end": effect["start_time"] + effect["duration"],
"duration": effect["duration"],
"volume": effect.get("volume", 0.7),
"fade_in": effect.get("fade_in", 0),
"fade_out": effect.get("fade_out", 0)
})
return {"audio_infos": json.dumps(audios)}
# 使用示例
processor = AudioProcessor()
# 背景音乐
bgm_config = processor.create_background_music(
"https://assets.jcaigc.cn/bgm.mp3",
60000000, # 60秒
volume=0.6,
loop=True
)
# 音频序列
sequence_config = processor.create_audio_sequence([
{
"url": "https://assets.jcaigc.cn/intro.mp3",
"play_duration": 5000000,
"total_duration": 5000000,
"volume": 1.0
},
{
"url": "https://assets.jcaigc.cn/main.mp3",
"play_duration": 20000000,
"total_duration": 25000000,
"volume": 0.8
}
])
# 音效
effects_config = processor.create_sound_effects([
{
"url": "https://assets.jcaigc.cn/whoosh.mp3",
"start_time": 10000000,
"duration": 1500000,
"volume": 0.5
}
])
# 添加到草稿
draft_url = "YOUR_DRAFT_URL"
results = []
for config in [bgm_config, sequence_config, effects_config]:
result = processor.add_audios(draft_url, config)
results.append(result)
print(f"音频添加成功: {result['track_id']}")
```
## 错误码说明
| 错误码 | 错误信息 | 说明 | 解决方案 |
|--------|----------|------|----------|
| 400 | draft_url是必填项 | 缺少草稿URL参数 | 提供有效的草稿URL |
| 400 | audio_infos是必填项 | 缺少音频信息参数 | 提供有效的音频信息JSON |
| 400 | audio_infos格式错误 | JSON格式不正确 | 检查JSON字符串格式 |
| 400 | 音频配置验证失败 | 音频参数不符合要求 | 检查每个音频的参数 |
| 400 | audio_url是必填项 | 音频URL缺失 | 为每个音频提供URL |
| 400 | 时间范围无效 | end必须大于start | 确保结束时间大于开始时间 |
| 400 | 音量值无效 | volume不在0-1范围内 | 使用0-1之间的音量值 |
| 404 | 草稿不存在 | 指定的草稿URL无效 | 检查草稿URL是否正确 |
| 404 | 音频资源不存在 | 音频URL无法访问 | 检查音频URL是否可访问 |
| 500 | 音频处理失败 | 内部处理错误 | 联系技术支持 |
## 注意事项
1. **JSON格式**: audio_infos必须是合法的JSON字符串
2. **时间单位**: 所有时间参数使用微秒(1秒 = 1,000,000微秒)
3. **音频格式**: 确保音频文件格式被支持(如MP3、WAV、AAC等)
4. **文件大小**: 大音频文件可能影响处理速度
5. **网络访问**: 音频URL必须可以正常访问
6. **音量范围**: 音量值必须在0.0-1.0范围内
7. **淡入淡出**: 淡入淡出时长不能超过音频播放时长
8. **轨道限制**: 同一时间段可能存在音频重叠
## 工作流程
1. 验证必填参数(draft_url, audio_infos
2. 解析audio_infos JSON字符串
3. 验证每个音频的参数配置
4. 获取并解密草稿内容
5. 创建音频轨道
6. 添加音频片段到轨道
7. 应用音量和淡入淡出效果
8. 保存并加密草稿
9. 返回处理结果
## 相关接口
- [创建草稿](./create_draft.md)
- [添加视频](./add_videos.md)
- [添加图片](./add_images.md)
- [保存草稿](./save_draft.md)
- [生成视频](./gen_video.md)
+232
View File
@@ -0,0 +1,232 @@
# add_captions 接口文档
## 接口描述
向剪映草稿批量添加字幕,支持丰富的字幕样式设置,包括关键词高亮、字体样式、边框效果、对齐方式、透明度和动画效果等。
## 接口信息
- **方法**: POST
- **路径**: `/openapi/capcut-mate/v1/add_captions`
- **Content-Type**: `application/json`
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### 请求体
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"captions": "[{\"start\":0,\"end\":10000000,\"text\":\"你好,剪映\",\"keyword\":\"好\",\"keyword_color\":\"#457616\",\"keyword_font_size\":15,\"font_size\":15}]",
"text_color": "#ffffff",
"border_color": null,
"alignment": 1,
"alpha": 1.0,
"font": null,
"font_size": 15,
"letter_spacing": null,
"line_spacing": null,
"scale_x": 1.0,
"scale_y": 1.0,
"transform_x": 0,
"transform_y": 0,
"style_text": false
}
```
### 参数说明
| 字段名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| draft_url | string | 是 | - | 草稿URL |
| captions | string | 是 | - | 字幕信息列表的JSON字符串 |
| text_color | string | 否 | "#ffffff" | 文本颜色(十六进制) |
| border_color | string | 否 | null | 边框颜色(十六进制) |
| alignment | integer | 否 | 1 | 文本对齐方式(0-5) |
| alpha | number | 否 | 1.0 | 文本透明度(0.0-1.0 |
| font | string | 否 | null | 字体名称 |
| font_size | integer | 否 | 15 | 字体大小 |
| letter_spacing | number | 否 | null | 字间距 |
| line_spacing | number | 否 | null | 行间距 |
| scale_x | number | 否 | 1.0 | 水平缩放 |
| scale_y | number | 否 | 1.0 | 垂直缩放 |
| transform_x | integer | 否 | 0 | 水平位移 |
| transform_y | integer | 否 | 0 | 垂直位移 |
| style_text | boolean | 否 | false | 是否使用样式文本 |
### captions 字段详细说明
captions 是一个JSON字符串,包含字幕数组,每个字幕对象包含以下字段:
| 字段名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| start | integer | 是 | - | 字幕开始时间(微秒) |
| end | integer | 是 | - | 字幕结束时间(微秒) |
| text | string | 是 | - | 字幕文本内容 |
| keyword | string | 否 | null | 关键词(用\|分隔多个关键词) |
| keyword_color | string | 否 | "#ff7100" | 关键词颜色 |
| keyword_font_size | integer | 否 | 15 | 关键词字体大小 |
| font_size | integer | 否 | 15 | 文本字体大小 |
| in_animation | string | 否 | null | 入场动画 |
| out_animation | string | 否 | null | 出场动画 |
| loop_animation | string | 否 | null | 循环动画 |
| in_animation_duration | integer | 否 | null | 入场动画时长 |
| out_animation_duration | integer | 否 | null | 出场动画时长 |
| loop_animation_duration | integer | 否 | null | 循环动画时长 |
### 对齐方式说明
| 值 | 说明 |
|---|------|
| 0 | 左对齐 |
| 1 | 居中对齐 |
| 2 | 右对齐 |
| 3 | 垂直居中 |
| 4 | 垂直左对齐 |
| 5 | 垂直右对齐 |
## 响应结果
### 成功响应
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"track_id": "text_track_123",
"text_ids": ["text_001", "text_002"],
"segment_ids": ["seg_001", "seg_002"]
}
```
### 响应字段说明
| 字段名 | 类型 | 描述 |
|--------|------|------|
| draft_url | string | 草稿URL |
| track_id | string | 字幕轨道ID |
| text_ids | array | 字幕ID列表 |
| segment_ids | array | 字幕片段ID列表 |
### 错误响应
```json
{
"code": 2018,
"message": "无效的字幕信息,请检查captions字段值是否正确"
}
```
## 使用示例
### cURL 示例
```bash
curl -X POST "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_captions" \
-H "Content-Type: application/json" \
-d '{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"captions": "[{\"start\":0,\"end\":5000000,\"text\":\"你好,剪映\",\"keyword\":\"好\",\"keyword_color\":\"#ff0000\"}]",
"text_color": "#ffffff",
"alignment": 1,
"alpha": 1.0,
"font_size": 20
}'
```
### Python 示例
```python
import requests
import json
url = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_captions"
captions_data = [
{
"start": 0,
"end": 5000000,
"text": "你好,剪映",
"keyword": "",
"keyword_color": "#ff0000",
"font_size": 20
},
{
"start": 5000000,
"end": 10000000,
"text": "欢迎使用字幕功能",
"keyword": "字幕",
"keyword_color": "#00ff00",
"font_size": 18
}
]
payload = {
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"captions": json.dumps(captions_data),
"text_color": "#ffffff",
"alignment": 1,
"alpha": 1.0,
"font_size": 16,
"transform_y": -100
}
response = requests.post(url, json=payload)
print(response.json())
```
### JavaScript 示例
```javascript
const url = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_captions";
const captionsData = [
{
start: 0,
end: 5000000,
text: "你好,剪映",
keyword: "好",
keyword_color: "#ff0000",
font_size: 20
}
];
const payload = {
draft_url: "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
captions: JSON.stringify(captionsData),
text_color: "#ffffff",
alignment: 1,
alpha: 1.0,
font_size: 16
};
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data));
```
## 注意事项
1. **时间单位**: 所有时间参数使用微秒为单位(1秒 = 1,000,000微秒)
2. **字幕时长**: end 时间必须大于 start 时间
3. **颜色格式**: 颜色值使用十六进制格式,如 "#ffffff"、"#ff0000"
4. **关键词高亮**: 暂未完全实现,目前为预留功能
5. **动画效果**: 暂未完全实现,目前为预留功能
6. **字体支持**: 字体名称需要系统支持或使用默认字体
7. **对齐方式**: 目前仅支持基础对齐方式(0-2),高级对齐方式(3-5)为预留功能
8. **坐标系统**: transform_x 和 transform_y 使用像素值,会自动转换为草稿相对坐标
## 错误码说明
| 错误码 | 错误信息 | 说明 |
|--------|----------|------|
| 2001 | 无效的草稿URL | 草稿URL格式错误或草稿不存在 |
| 2018 | 无效的字幕信息 | captions字段格式错误或包含无效数据 |
| 2019 | 字幕添加失败 | 添加字幕过程中发生错误 |
## 高级功能(待实现)
1. **关键词高亮**: 支持对指定关键词设置不同颜色和字体大小
2. **入场/出场动画**: 支持字幕的动画效果
3. **循环动画**: 支持字幕的循环动画效果
4. **样式文本**: 支持富文本格式的字幕样式
5. **字体选择**: 支持自定义字体文件
6. **边框和阴影**: 支持字幕边框和阴影效果
+124
View File
@@ -0,0 +1,124 @@
# 添加特效接口文档
## 接口概述
向现有剪映草稿中添加视频特效轨道和特效片段。支持批量添加多种视频特效,包括边框特效、滤镜特效、动态特效等,为视频内容增加丰富的视觉效果。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 接口信息
- **请求方式**: POST
- **接口路径**: `/openapi/capcut-mate/v1/add_effects`
- **Content-Type**: `application/json`
## 请求参数
### 请求体 (Body)
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| draft_url | string | 是 | "" | 目标草稿的完整URL |
| effect_infos | string | 是 | "" | JSON字符串格式的特效信息数组 |
#### effect_infos 字段格式
`effect_infos` 是一个JSON字符串,包含特效信息数组,每个特效对象包含以下字段:
```json
[
{
"effect_title": "录制边框 III", // 特效名称/标题,必选参数
"start": 0, // 特效开始时间(微秒),必选参数
"end": 5000000 // 特效结束时间(微秒),必选参数
}
]
```
**字段说明**:
- `effect_title`: 特效名称,必须是系统中已存在的特效名称
- `start`: 特效开始时间,单位为微秒,必须大于等于0
- `end`: 特效结束时间,单位为微秒,必须大于start
### 常见特效名称
| 特效类型 | 特效名称示例 |
|----------|--------------|
| 边框特效 | "录制边框 III", "简约边框", "霓虹边框" |
| 滤镜特效 | "复古滤镜", "黑白滤镜", "暖色调" |
| 动态特效 | "粒子效果", "光晕效果", "闪烁特效" |
| 转场特效 | "淡入淡出", "推拉门", "马赛克转场" |
## 请求示例
```bash
curl -X POST "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_effects" \
-H "Content-Type: application/json" \
-d '{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"effect_infos": "[{\"effect_title\": \"录制边框 III\", \"start\": 0, \"end\": 5000000}, {\"effect_title\": \"复古滤镜\", \"start\": 2000000, \"end\": 7000000}]"
}'
```
## 响应格式
### 成功响应
```json
{
"code": 0,
"message": "Success",
"data": {
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"track_id": "effect_track_123",
"effect_ids": ["effect_001", "effect_002"],
"segment_ids": ["seg_001", "seg_002"]
}
}
```
**响应字段说明**:
- `draft_url`: 草稿URL
- `track_id`: 创建的特效轨道ID
- `effect_ids`: 添加的特效ID列表
- `segment_ids`: 创建的特效片段ID列表
### 错误响应
```json
{
"code": 2020,
"message": "无效的特效信息,请检查effect_infos字段值是否正确"
}
```
## 错误码说明
| 错误码 | 错误信息 | 描述 |
|--------|----------|------|
| 2001 | 无效的草稿URL | 草稿URL格式错误或草稿不存在 |
| 2020 | 无效的特效信息 | effect_infos格式错误或字段值无效 |
| 2021 | 特效添加失败 | 添加特效过程中发生错误 |
| 2022 | 特效未找到 | 指定的特效名称不存在 |
## 使用说明
1. **时间单位**: 所有时间参数使用微秒(μs)为单位,1秒 = 1,000,000微秒
2. **时间范围**: 确保 `start < end`,且时间范围合理
3. **特效名称**: 特效名称必须完全匹配系统中预定义的特效名称,区分大小写
4. **批量添加**: 支持一次添加多个特效,按数组顺序依次处理
5. **轨道管理**: 系统会自动创建特效轨道,无需手动管理
## 注意事项
- 特效会按照指定的时间范围添加到视频中
- 如果特效名称不存在,会返回特效未找到错误
- 特效的时间范围不能超出视频总时长
- 建议在添加特效前确保草稿中已有视频内容
- 特效效果可能因版本差异而有所不同
## 相关接口
- [创建草稿](./create_draft.md) - 创建新的剪映草稿
- [添加视频](./add_videos.md) - 向草稿添加视频内容
- [保存草稿](./save_draft.md) - 保存草稿更改
-357
View File
@@ -1,357 +0,0 @@
# add_image 接口文档
## 接口概述
添加图片到剪映草稿中,支持位置调整、缩放、动画、转场、蒙版、背景模糊等功能。
---
## 接口信息
### RESTful API 端点
```
POST /add_image
```
### Content-Type
```
application/json
```
---
## 请求参数
### 基础参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| **image_url** | string | **是** | - | 图片文件的 URL 地址(必需参数) |
| draft_folder | string | 否 | null | 草稿文件夹路径 |
| draft_id | string | 否 | null | 草稿 ID |
| width | integer | 否 | 1080 | 画布宽度 |
| height | integer | 否 | 1920 | 画布高度 |
| start | number | 否 | 0 | 图片开始时间(秒) |
| end | number | 否 | 3.0 | 图片结束时间(秒) |
### 位置和缩放参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| transform_x | number | 否 | 0 | X 轴位移(-1.0 到 1.0 |
| transform_y | number | 否 | 0 | Y 轴位移(-1.0 到 1.0 |
| scale_x | number | 否 | 1 | X 轴缩放比例 |
| scale_y | number | 否 | 1 | Y 轴缩放比例 |
### 轨道参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| track_name | string | 否 | "image_main" | 图片轨道名称 |
| relative_index | integer | 否 | 0 | 轨道渲染顺序索引 |
### 动画参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| animation | string | 否 | null | 入场动画(向后兼容) |
| animation_duration | number | 否 | 0.5 | 入场动画时长 |
| intro_animation | string | 否 | null | 入场动画(优先级高) |
| intro_animation_duration | number | 否 | 0.5 | 入场动画时长 |
| outro_animation | string | 否 | null | 出场动画 |
| outro_animation_duration | number | 否 | 0.5 | 出场动画时长 |
| combo_animation | string | 否 | null | 组合动画 |
| combo_animation_duration | number | 否 | 0.5 | 组合动画时长 |
### 转场参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| transition | string | 否 | null | 转场效果类型 |
| transition_duration | number | 否 | 0.5 | 转场时长(秒) |
### 蒙版参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| mask_type | string | 否 | null | 蒙版类型 |
| mask_center_x | number | 否 | 0.0 | 蒙版中心 X 坐标 |
| mask_center_y | number | 否 | 0.0 | 蒙版中心 Y 坐标 |
| mask_size | number | 否 | 0.5 | 蒙版大小 |
| mask_rotation | number | 否 | 0.0 | 蒙版旋转角度 |
| mask_feather | number | 否 | 0.0 | 蒙版羽化程度 |
| mask_invert | boolean | 否 | false | 是否反转蒙版 |
| mask_rect_width | number | 否 | null | 矩形蒙版宽度 |
| mask_round_corner | number | 否 | null | 矩形蒙版圆角 |
### 背景模糊参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| background_blur | integer | 否 | null | 背景模糊级别(1-4 |
---
## 响应参数
### 响应体 (JSON)
| 参数名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 请求是否成功 |
| output | object/string | 成功时返回草稿结果信息 |
| error | string | 失败时的错误信息 |
---
## 请求示例
### 示例 1: 基础图片添加
```bash
curl -X POST http://localhost:9001/add_image \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://example.com/photo.jpg"
}'
```
### 示例 2: 带入场动画的图片
```json
{
"image_url": "https://example.com/photo.jpg",
"draft_id": "dfd_12345",
"start": 0,
"end": 5,
"intro_animation": "fade_in",
"intro_animation_duration": 1.0,
"outro_animation": "zoom_out",
"outro_animation_duration": 0.8
}
```
### 示例 3: 画中画效果
```json
{
"image_url": "https://example.com/pip.png",
"draft_id": "dfd_12345",
"track_name": "image_pip",
"transform_x": 0.6,
"transform_y": -0.6,
"scale_x": 0.3,
"scale_y": 0.3,
"relative_index": 1
}
```
### 示例 4: 圆形蒙版效果
```json
{
"image_url": "https://example.com/portrait.jpg",
"draft_id": "dfd_12345",
"mask_type": "circle",
"mask_center_x": 0.5,
"mask_center_y": 0.5,
"mask_size": 0.8,
"mask_feather": 0.1
}
```
### 示例 5: 带转场和背景模糊
```json
{
"image_url": "https://example.com/landscape.jpg",
"draft_id": "dfd_12345",
"start": 3,
"end": 8,
"transition": "dissolve",
"transition_duration": 1.0,
"background_blur": 3,
"scale_x": 0.9,
"scale_y": 0.9
}
```
### 示例 6: Python 完整示例
```python
import requests
url = "http://localhost:9001/add_image"
data = {
"image_url": "https://example.com/photo.jpg",
"draft_id": "dfd_abc123",
"start": 0,
"end": 5,
"transform_y": -0.2,
"scale_x": 1.2,
"scale_y": 1.2,
"intro_animation": "slide_in",
"intro_animation_duration": 1.0,
"transition": "fade",
"transition_duration": 0.8
}
response = requests.post(url, json=data)
result = response.json()
print(f"Success: {result['success']}")
if result['success']:
print(f"Draft ID: {result['output']['draft_id']}")
else:
print(f"Error: {result['error']}")
```
---
## 响应示例
### 成功响应
```json
{
"success": true,
"output": {
"draft_id": "dfd_1234567890abcdef",
"draft_url": "http://example.com/preview?draft_id=dfd_1234567890abcdef"
},
"error": ""
}
```
### 失败响应
```json
{
"success": false,
"output": "",
"error": "Hi, the required parameters 'image_url' are missing."
}
```
---
## 使用场景
### 场景 1: 封面图片
```json
{
"image_url": "https://example.com/cover.jpg",
"start": 0,
"end": 3,
"intro_animation": "zoom_in",
"intro_animation_duration": 1.5
}
```
### 场景 2: 照片墙
```json
{
"image_url": "https://example.com/photo1.jpg",
"start": 0,
"end": 2,
"transform_x": -0.5,
"transform_y": -0.5,
"scale_x": 0.4,
"scale_y": 0.4
}
```
### 场景 3: Logo 水印
```json
{
"image_url": "https://example.com/logo.png",
"start": 0,
"end": 30,
"transform_x": 0.8,
"transform_y": -0.8,
"scale_x": 0.2,
"scale_y": 0.2,
"track_name": "image_watermark"
}
```
### 场景 4: 产品展示
```json
{
"image_url": "https://example.com/product.png",
"start": 2,
"end": 8,
"intro_animation": "fade_in",
"combo_animation": "float",
"outro_animation": "fade_out",
"background_blur": 2
}
```
---
## 图片格式支持
| 格式 | 扩展名 | 说明 |
|------|--------|------|
| JPEG | .jpg, .jpeg | 有损压缩,文件小 |
| PNG | .png | 支持透明通道 |
| GIF | .gif | 支持动画(仅显示第一帧) |
| WebP | .webp | 现代格式,压缩率高 |
| BMP | .bmp | 无压缩,文件大 |
---
## 注意事项
1. **必需参数**: image_url 是唯一的必需参数
2. **默认时长**: 默认显示 3 秒
3. **坐标系统**: transform_x/y 使用相对坐标(-1.0 到 1.0
4. **动画优先级**: intro_animation 优先于 animation 参数
5. **透明图片**: PNG 格式支持透明背景
6. **图片尺寸**: 建议使用适当大小的图片,过大会影响性能
7. **URL 要求**: image_url 必须是可访问的完整 URL
---
## 动画类型
可通过以下接口获取可用动画类型:
- `/get_intro_animation_types` - 入场动画
- `/get_outro_animation_types` - 出场动画
- `/get_combo_animation_types` - 组合动画
---
## 相关接口
- `POST /create_draft` - 创建新草稿
- `POST /save_draft` - 保存草稿
- `GET /get_intro_animation_types` - 获取入场动画类型
- `GET /get_transition_types` - 获取转场类型
- `GET /get_mask_types` - 获取蒙版类型
- `POST /add_video` - 添加视频
- `POST /add_text` - 添加文字
---
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2025-10-21 | 初始版本 |
---
## 技术支持
如有问题,请联系:
- Email: sguann2023@gmail.com
- GitHub Issues: https://github.com/sun-guannan/CapCutAPI/issues
+321
View File
@@ -0,0 +1,321 @@
# ADD_IMAGES API 接口文档
## 接口信息
```
POST /openapi/capcut-mate/v1/add_images
```
## 功能描述
批量向现有草稿中添加图片素材。该接口支持多个图片的批量处理,包括透明度调整、缩放变换、位置偏移、动画效果等功能。在剪映系统中,图片被作为VideoSegment处理。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"image_infos": "[{\"image_url\":\"https://assets.jcaigc.cn/image1.jpg\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":5000000,\"duration\":5000000,\"animation\":\"淡入淡出\",\"transition\":\"溶解\",\"transition_duration\":500000}]",
"alpha": 1.0,
"scale_x": 1.0,
"scale_y": 1.0,
"transform_x": 0,
"transform_y": 0
}
```
### 主要参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| draft_url | string | ✅ | - | 目标草稿的完整URL |
| image_infos | string | ✅ | - | 图片信息数组的JSON字符串 |
| alpha | number | ❌ | 1.0 | 全局透明度(0-1) |
| scale_x | number | ❌ | 1.0 | X轴缩放比例 |
| scale_y | number | ❌ | 1.0 | Y轴缩放比例 |
| transform_x | number | ❌ | 0 | X轴位置偏移(像素) |
| transform_y | number | ❌ | 0 | Y轴位置偏移(像素) |
### image_infos 数组结构
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| image_url | string | ✅ | - | 图片文件的URL地址 |
| width | number | ✅ | - | 图片宽度(像素) |
| height | number | ✅ | - | 图片高度(像素) |
| start | number | ✅ | - | 图片开始显示时间(微秒) |
| end | number | ✅ | - | 图片结束显示时间(微秒) |
| duration | number | ✅ | - | 图片显示总时长(微秒) |
| animation | string | ❌ | - | 动画效果名称 |
| transition | string | ❌ | - | 转场效果名称 |
| transition_duration | number | ❌ | 500000 | 转场持续时间(微秒) |
### 参数详解
#### 时间参数
- **start**: 图片开始显示时间,单位微秒(1秒 = 1,000,000微秒)
- **end**: 图片结束显示时间,单位微秒
- **duration**: 图片总显示时长,通常等于 end - start
#### 透明度和变换
- **alpha**: 全局透明度,范围0.0-1.0
- **scale_x/scale_y**: 缩放比例,1.0为原始大小
- **transform_x/transform_y**: 位置偏移,以画布中心为原点
#### 动画和转场
- **animation**: 支持"淡入淡出"、"缩放入场"、"滑动入场"等
- **transition**: 转场效果名称
- **transition_duration**: 转场时长,范围100,000-2,500,000微秒
## 响应格式
### 成功响应 (200)
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"track_id": "video-track-uuid",
"image_ids": ["image1-uuid", "image2-uuid"],
"segment_ids": ["segment1-uuid", "segment2-uuid"],
"segment_infos": [
{
"id": "segment1-uuid",
"start": 0,
"end": 5000000
}
]
}
```
### 响应字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| draft_url | string | 更新后的草稿URL |
| track_id | string | 视频轨道ID |
| image_ids | array | 添加的图片ID列表 |
| segment_ids | array | 片段ID列表 |
| segment_infos | array | 片段详细信息列表 |
## 使用示例
### cURL 示例
#### 基本图片添加
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_images \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"image_infos": "[{\"image_url\":\"https://assets.jcaigc.cn/photo1.jpg\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":5000000,\"duration\":5000000}]"
}'
```
#### 带动画效果的图片
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_images \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"image_infos": "[{\"image_url\":\"https://assets.jcaigc.cn/logo.png\",\"width\":800,\"height\":600,\"start\":1000000,\"end\":4000000,\"duration\":3000000,\"animation\":\"缩放入场\",\"transition\":\"淡入淡出\"}]",
"alpha": 0.9,
"scale_x": 1.2,
"scale_y": 1.2,
"transform_x": 200,
"transform_y": -100
}'
```
### JavaScript 示例
```javascript
const addImages = async (draftUrl, imageConfig) => {
const response = await fetch('/openapi/capcut-mate/v1/add_images', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
draft_url: draftUrl,
...imageConfig
})
});
return response.json();
};
// 基本图片添加
const basicImages = {
image_infos: JSON.stringify([
{
image_url: "https://assets.jcaigc.cn/cover.jpg",
width: 1920,
height: 1080,
start: 0,
end: 5000000,
duration: 5000000
}
])
};
// 图片幻灯片
const slideshow = {
image_infos: JSON.stringify([
{
image_url: "https://assets.jcaigc.cn/slide1.jpg",
width: 1920,
height: 1080,
start: 0,
end: 3000000,
duration: 3000000,
animation: "淡入淡出",
transition: "淡入淡出"
},
{
image_url: "https://assets.jcaigc.cn/slide2.jpg",
width: 1920,
height: 1080,
start: 3000000,
end: 6000000,
duration: 3000000,
animation: "滑动入场",
transition: "滑动"
}
])
};
// 图片水印
const watermark = {
image_infos: JSON.stringify([
{
image_url: "https://assets.jcaigc.cn/logo.png",
width: 300,
height: 100,
start: 0,
end: 30000000,
duration: 30000000,
animation: "淡入淡出"
}
]),
alpha: 0.7,
scale_x: 0.5,
scale_y: 0.5,
transform_x: 700,
transform_y: -400
};
try {
const result1 = await addImages(draftUrl, basicImages);
const result2 = await addImages(draftUrl, slideshow);
const result3 = await addImages(draftUrl, watermark);
console.log('图片添加成功');
} catch (error) {
console.error('添加失败:', error);
}
```
### Python 示例
```python
import requests
import json
class ImageProcessor:
def __init__(self, base_url="https://capcut-mate.jcaigc.cn"):
self.base_url = base_url
def add_images(self, draft_url: str, image_config: dict) -> dict:
response = requests.post(
f'{self.base_url}/openapi/capcut-mate/v1/add_images',
headers={'Content-Type': 'application/json'},
json={
"draft_url": draft_url,
**image_config
}
)
return response.json()
def create_slideshow(self, images: list, slide_duration: int = 3000000) -> dict:
"""创建幻灯片播放"""
current_time = 0
image_infos = []
for image in images:
image_info = {
"image_url": image["url"],
"width": image["width"],
"height": image["height"],
"start": current_time,
"end": current_time + slide_duration,
"duration": slide_duration,
"animation": image.get("animation", "淡入淡出")
}
image_infos.append(image_info)
current_time += slide_duration
return {"image_infos": json.dumps(image_infos)}
# 使用示例
processor = ImageProcessor()
slideshow_config = processor.create_slideshow([
{
"url": "https://assets.jcaigc.cn/slide1.jpg",
"width": 1920,
"height": 1080,
"animation": "淡入淡出"
}
])
result = processor.add_images("YOUR_DRAFT_URL", slideshow_config)
print(f"图片添加成功: {result['track_id']}")
```
## 错误码说明
| 错误码 | 错误信息 | 说明 | 解决方案 |
|--------|----------|------|----------|
| 400 | draft_url是必填项 | 缺少草稿URL | 提供有效的草稿URL |
| 400 | image_infos是必填项 | 缺少图片信息 | 提供有效的图片信息JSON |
| 400 | image_infos格式错误 | JSON格式不正确 | 检查JSON字符串格式 |
| 400 | image_url是必填项 | 图片URL缺失 | 为每个图片提供URL |
| 400 | 图片尺寸无效 | width或height无效 | 提供正数的宽度和高度 |
| 400 | 时间范围无效 | end必须大于start | 确保结束时间大于开始时间 |
| 404 | 草稿不存在 | 草稿URL无效 | 检查草稿URL是否正确 |
| 404 | 图片资源不存在 | 图片URL无法访问 | 检查图片URL是否可访问 |
| 500 | 图片处理失败 | 内部处理错误 | 联系技术支持 |
## 注意事项
1. **JSON格式**: image_infos必须是合法的JSON字符串
2. **时间单位**: 所有时间参数使用微秒(1秒 = 1,000,000微秒)
3. **图片格式**: 支持JPG、PNG、GIF等格式
4. **网络访问**: 图片URL必须可以正常访问
5. **透明度范围**: alpha值必须在0.0-1.0范围内
6. **图片处理**: 图片在剪映中作为VideoSegment处理
7. **动画效果**: 不是所有动画效果都兼容所有转场效果
## 工作流程
1. 验证必填参数(draft_url, image_infos
2. 解析image_infos JSON字符串
3. 验证每个图片的参数配置
4. 获取并解密草稿内容
5. 创建视频轨道(图片作为VideoSegment
6. 添加图片片段到轨道
7. 应用透明度、缩放和位置变换
8. 添加动画和转场效果
9. 保存并加密草稿
10. 返回处理结果
## 相关接口
- [创建草稿](./create_draft.md)
- [添加视频](./add_videos.md)
- [添加音频](./add_audios.md)
- [保存草稿](./save_draft.md)
- [生成视频](./gen_video.md)
+140
View File
@@ -0,0 +1,140 @@
# add_keyframes 接口文档
## 接口描述
向剪映草稿添加关键帧,支持多种动画属性的关键帧设置。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 接口信息
- **方法**: POST
- **路径**: `/openapi/capcut-mate/v1/add_keyframes`
- **Content-Type**: `application/json`
## 请求参数
### 请求体
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"keyframes": "[{\"segment_id\":\"d62994b4-25fe-422a-a123-87ef05038558\",\"property\":\"KFTypePositionX\",\"offset\":0.5,\"value\":-0.1}]"
}
```
### 参数说明
| 字段名 | 类型 | 必填 | 描述 |
|--------|------|------|------|
| draft_url | string | 是 | 草稿URL |
| keyframes | string | 是 | 关键帧信息列表的JSON字符串 |
### keyframes 字段详细说明
keyframes 是一个JSON字符串,包含关键帧数组,每个关键帧对象包含以下字段:
| 字段名 | 类型 | 必填 | 描述 |
|--------|------|------|------|
| segment_id | string | 是 | 目标片段的唯一标识ID |
| property | string | 是 | 动画属性类型,支持的类型见下表 |
| offset | number | 是 | 关键帧在片段中的时间偏移(0-1范围,0表示开始,1表示结束) |
| value | number | 是 | 属性在该时间点的值 |
### 支持的动画属性类型
| 属性类型 | 描述 | 值范围 | 示例 |
|---------|------|--------|------|
| KFTypePositionX | X轴位置 | -1.0 到 1.0 | 0.0 (居中), -0.5 (左移), 0.5 (右移) |
| KFTypePositionY | Y轴位置 | -1.0 到 1.0 | 0.0 (居中), -0.5 (上移), 0.5 (下移) |
| KFTypeScaleX | X轴缩放 | 0.1 到 10.0 | 1.0 (原始), 0.5 (缩小), 2.0 (放大) |
| KFTypeScaleY | Y轴缩放 | 0.1 到 10.0 | 1.0 (原始), 0.5 (缩小), 2.0 (放大) |
| KFTypeRotation | 旋转角度 | -360 到 360 | 0 (无旋转), 90 (顺时针90度) |
| KFTypeAlpha | 透明度 | 0.0 到 1.0 | 1.0 (不透明), 0.5 (半透明), 0.0 (透明) |
## 响应结果
### 成功响应
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"keyframes_added": 3,
"affected_segments": ["segment_001", "segment_002"]
}
```
### 响应字段说明
| 字段名 | 类型 | 描述 |
|--------|------|------|
| draft_url | string | 草稿URL |
| keyframes_added | integer | 添加的关键帧数量 |
| affected_segments | array | 受影响的片段ID列表 |
### 错误响应
```json
{
"code": 2013,
"message": "无效的关键帧信息,请检查keyframes字段值是否正确"
}
```
## 使用示例
### cURL 示例
```bash
curl -X POST "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_keyframes" \
-H "Content-Type: application/json" \
-d '{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"keyframes": "[{\"segment_id\":\"d62994b4-25fe-422a-a123-87ef05038558\",\"property\":\"KFTypePositionX\",\"offset\":0,\"value\":0},{\"segment_id\":\"d62994b4-25fe-422a-a123-87ef05038558\",\"property\":\"KFTypePositionX\",\"offset\":1,\"value\":-0.5}]"
}'
```
### Python 示例
```python
import requests
import json
url = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_keyframes"
keyframes_data = [
{
"segment_id": "d62994b4-25fe-422a-a123-87ef05038558",
"property": "KFTypePositionX",
"offset": 0,
"value": 0
},
{
"segment_id": "d62994b4-25fe-422a-a123-87ef05038558",
"property": "KFTypePositionX",
"offset": 1,
"value": -0.5
}
]
payload = {
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"keyframes": json.dumps(keyframes_data)
}
response = requests.post(url, json=payload)
print(response.json())
```
## 注意事项
1. **片段ID验证**: segment_id 必须是草稿中存在的有效片段ID
2. **片段类型限制**: 只有视觉片段(视频、图片、贴纸、文本)支持关键帧
3. **时间偏移范围**: offset 值必须在 0.0-1.0 范围内
4. **属性值范围**: 不同的属性类型有不同的值范围限制
5. **重复关键帧**: 相同片段相同属性的关键帧会被累加,不会覆盖
6. **性能考虑**: 单次请求建议不超过100个关键帧
## 错误码说明
| 错误码 | 错误信息 | 说明 |
|--------|----------|------|
| 2001 | 无效的草稿URL | 草稿URL格式错误或草稿不存在 |
| 2013 | 无效的关键帧信息 | keyframes字段格式错误或包含无效数据 |
| 2014 | 关键帧添加失败 | 添加关键帧过程中发生错误 |
| 2015 | 片段未找到 | 指定的segment_id在草稿中不存在 |
| 2016 | 无效的片段类型 | 该片段不支持关键帧功能 |
| 2017 | 无效的关键帧属性类型 | 指定的property类型不受支持 |
+158
View File
@@ -0,0 +1,158 @@
# 添加遮罩接口文档
## 接口概述
向现有草稿中的指定片段添加遮罩效果。遮罩是视频编辑中的重要功能,通过遮罩可以控制图像的可见区域,创造出各种视觉效果。支持多种遮罩类型(线性、镜面、圆形、矩形、爱心、星形),每种遮罩都可以精确配置位置、大小、羽化、旋转等属性。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 接口信息
- **请求方式**: POST
- **接口路径**: `/openapi/capcut-mate/v1/add_masks`
- **Content-Type**: `application/json`
## 请求参数
### 请求体 (Body)
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| draft_url | string | 是 | "" | 目标草稿的完整URL |
| segment_ids | array | 是 | [] | 要应用遮罩的片段ID数组 |
| name | string | 否 | "线性" | 遮罩类型名称 |
| X | integer | 否 | 0 | 遮罩中心X坐标(像素) |
| Y | integer | 否 | 0 | 遮罩中心Y坐标(像素) |
| width | integer | 否 | 512 | 遮罩宽度(像素) |
| height | integer | 否 | 512 | 遮罩高度(像素) |
| feather | integer | 否 | 0 | 羽化程度(0-100 |
| rotation | integer | 否 | 0 | 旋转角度(度) |
| invert | boolean | 否 | false | 是否反转遮罩 |
| roundCorner | integer | 否 | 0 | 圆角半径(0-100 |
### 支持的遮罩类型
| 遮罩名称 | 描述 | 适用场景 |
|----------|------|----------|
| 线性 | 线性渐变遮罩 | 线性过渡效果、渐变显示隐藏 |
| 镜面 | 镜像对称遮罩 | 对称效果、镜像反射 |
| 圆形 | 圆形遮罩 | 聚光灯效果、圆形裁剪 |
| 矩形 | 矩形遮罩 | 窗口效果、矩形裁剪 |
| 爱心 | 爱心形状遮罩 | 浪漫场景、特殊形状裁剪 |
| 星形 | 星形遮罩 | 闪光效果、装饰性裁剪 |
### 遮罩配置详解
- **位置控制**: X、Y参数控制遮罩在画面中的位置
- **尺寸控制**: width、height控制遮罩的大小
- **羽化效果**: feather参数控制边缘的柔化程度,值越大边缘越柔和
- **旋转变换**: rotation参数控制遮罩的旋转角度
- **反转效果**: invert参数可以反转遮罩的显示/隐藏区域
- **圆角处理**: roundCorner参数为矩形遮罩添加圆角效果
## 请求示例
```bash
curl -X POST "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_masks" \
-H "Content-Type: application/json" \
-d '{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"segment_ids": ["d62994b4-25fe-422a-a123-87ef05038558", "e73995c5-36ef-533b-b234-98fg16149669"],
"name": "圆形",
"X": 100,
"Y": 200,
"width": 300,
"height": 300,
"feather": 20,
"rotation": 0,
"invert": false,
"roundCorner": 0
}'
```
## 响应格式
### 成功响应
```json
{
"code": 0,
"message": "Success",
"data": {
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"masks_added": 2,
"affected_segments": ["d62994b4-25fe-422a-a123-87ef05038558", "e73995c5-36ef-533b-b234-98fg16149669"],
"mask_ids": ["mask_001", "mask_002"]
}
}
```
**响应字段说明**:
- `draft_url`: 草稿URL
- `masks_added`: 成功添加的遮罩数量
- `affected_segments`: 受影响的片段ID列表
- `mask_ids`: 遮罩ID列表
### 错误响应
```json
{
"code": 2023,
"message": "无效的遮罩信息,请检查遮罩参数是否正确"
}
```
## 错误码说明
| 错误码 | 错误信息 | 描述 |
|--------|----------|------|
| 2001 | 无效的草稿URL | 草稿URL格式错误或草稿不存在 |
| 2015 | 片段未找到 | 指定的segment_id不存在 |
| 2016 | 无效的片段类型 | 片段类型不支持添加遮罩 |
| 2023 | 无效的遮罩信息 | 遮罩参数格式错误或值无效 |
| 2024 | 遮罩添加失败 | 添加遮罩过程中发生错误 |
| 2025 | 遮罩类型未找到 | 指定的遮罩名称不存在 |
## 使用说明
1. **片段要求**: 只有视频片段(VideoSegment)支持添加遮罩
2. **遮罩限制**: 每个片段只能添加一个遮罩,重复添加会失败
3. **坐标系统**: X、Y坐标以像素为单位,原点位于素材中心
4. **参数范围**:
- feather: 0-100,羽化程度
- rotation: 0-360度,旋转角度
- roundCorner: 0-100,圆角半径(仅矩形遮罩有效)
5. **批量处理**: 支持同时为多个片段添加相同配置的遮罩
## 应用场景
### 创意视觉效果
- **聚光灯效果**: 使用圆形遮罩突出画面重点
- **窗口效果**: 使用矩形遮罩创建窗口视觉
- **浪漫场景**: 使用爱心遮罩营造浪漫氛围
- **装饰效果**: 使用星形遮罩增加装饰元素
### 画面过渡
- **渐变显示**: 使用线性遮罩实现渐进显示效果
- **对称效果**: 使用镜面遮罩创建对称视觉
- **柔和边缘**: 通过羽化参数实现柔和的边缘过渡
### 内容遮挡
- **隐私保护**: 遮挡敏感信息区域
- **焦点引导**: 突出重要内容,弱化无关区域
- **艺术创作**: 创造独特的视觉艺术效果
## 注意事项
- 遮罩效果只对视频片段有效,不支持音频、文本或贴纸片段
- 添加遮罩后会影响片段的视觉呈现,请确保遮罩配置符合预期
- 遮罩参数的单位和坐标系以素材自身为基准
- 建议在添加遮罩前预览效果,确保达到预期的视觉效果
- 遮罩的渲染性能可能影响导出速度,请根据需要合理使用
## 相关接口
- [创建草稿](./create_draft.md) - 创建新的剪映草稿
- [添加视频](./add_videos.md) - 向草稿添加视频内容
- [添加特效](./add_effects.md) - 向草稿添加视频特效
- [保存草稿](./save_draft.md) - 保存草稿更改
+591
View File
@@ -0,0 +1,591 @@
# ADD_STICKER API 接口文档
## 接口信息
```
POST /openapi/capcut-mate/v1/add_sticker
```
## 功能描述
向现有草稿中添加贴纸。该接口用于在指定的时间段内添加贴纸素材到剪映草稿中,支持贴纸的缩放和位置调整。贴纸可以用于增强视频的视觉效果,如表情、装饰、文字等。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"sticker_id": "7326810673609018675",
"start": 0,
"end": 5000000,
"scale": 1.0,
"transform_x": 0,
"transform_y": 0
}
```
### 参数说明
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| draft_url | string | ✅ | - | 目标草稿的完整URL |
| sticker_id | string | ✅ | - | 贴纸的唯一标识ID |
| start | number | ✅ | - | 贴纸开始时间(微秒) |
| end | number | ✅ | - | 贴纸结束时间(微秒) |
| scale | number | ❌ | 1.0 | 贴纸缩放比例,建议范围[0.1, 5.0] |
| transform_x | number | ❌ | 0 | X轴位置偏移(像素) |
| transform_y | number | ❌ | 0 | Y轴位置偏移(像素) |
### 参数详解
#### 时间参数
- **start**: 贴纸在时间轴上的开始时间,单位为微秒(1秒 = 1,000,000微秒)
- **end**: 贴纸在时间轴上的结束时间,单位为微秒
- **duration**: 贴纸显示时长 = end - start
#### 缩放参数
- **scale**: 贴纸的缩放比例
- 1.0 = 原始大小
- 0.5 = 缩小到一半
- 2.0 = 放大到两倍
- 建议范围:0.1 - 5.0
#### 位置参数
- **transform_x**: 贴纸在X轴方向的位置偏移,单位为像素
- 正值向右移动
- 负值向左移动
- 以画布中心为原点
- **transform_y**: 贴纸在Y轴方向的位置偏移,单位为像素
- 正值向下移动
- 负值向上移动
- 以画布中心为原点
#### 贴纸ID说明
- **sticker_id**: 贴纸的唯一标识符
- 格式:通常为数字字符串
- 示例:`"7326810673609018675"`
- 获取方式:通过剪映贴纸库或相关API获取
## 响应格式
### 成功响应 (200)
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"sticker_id": "7326810673609018675",
"track_id": "track-uuid",
"segment_id": "segment-uuid",
"duration": 5000000
}
```
### 响应字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| draft_url | string | 更新后的草稿URL |
| sticker_id | string | 贴纸的唯一标识ID |
| track_id | string | 贴纸轨道ID |
| segment_id | string | 贴纸片段ID |
| duration | number | 贴纸显示时长(微秒) |
### 错误响应 (4xx/5xx)
```json
{
"detail": "错误信息描述"
}
```
## 使用示例
### cURL 示例
#### 1. 基本贴纸添加
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_sticker \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"sticker_id": "7326810673609018675",
"start": 0,
"end": 5000000
}'
```
#### 2. 带缩放的贴纸
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_sticker \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"sticker_id": "7326810673609018675",
"start": 1000000,
"end": 6000000,
"scale": 1.5
}'
```
#### 3. 带位置偏移的贴纸
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_sticker \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"sticker_id": "7326810673609018675",
"start": 2000000,
"end": 7000000,
"scale": 0.8,
"transform_x": 200,
"transform_y": -100
}'
```
### JavaScript 示例
```javascript
const addSticker = async (draftUrl, stickerConfig) => {
const response = await fetch('/openapi/capcut-mate/v1/add_sticker', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
draft_url: draftUrl,
...stickerConfig
})
});
return response.json();
};
// 基本贴纸添加
const basicSticker = {
sticker_id: "7326810673609018675",
start: 0,
end: 5000000
};
// 自定义大小和位置的贴纸
const customSticker = {
sticker_id: "7326810673609018675",
start: 3000000,
end: 8000000,
scale: 1.2,
transform_x: 150,
transform_y: -50
};
// 小尺寸装饰贴纸
const decorationSticker = {
sticker_id: "7326810673609018675",
start: 10000000,
end: 15000000,
scale: 0.6,
transform_x: -200,
transform_y: 200
};
try {
const result1 = await addSticker(draftUrl, basicSticker);
const result2 = await addSticker(draftUrl, customSticker);
const result3 = await addSticker(draftUrl, decorationSticker);
console.log('贴纸添加成功:', {
basic: result1,
custom: result2,
decoration: result3
});
} catch (error) {
console.error('添加失败:', error);
}
```
### 高级JavaScript示例
```javascript
class StickerManager {
constructor(baseUrl = 'https://capcut-mate.jcaigc.cn') {
this.baseUrl = baseUrl;
}
async addSticker(draftUrl, stickerConfig) {
const response = await fetch(`${this.baseUrl}/openapi/capcut-mate/v1/add_sticker`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
draft_url: draftUrl,
...stickerConfig
})
});
if (!response.ok) {
throw new Error(`贴纸添加失败: ${response.statusText}`);
}
return response.json();
}
// 创建贴纸序列
createStickerSequence(stickers, intervalDuration = 1000000) {
return stickers.map((sticker, index) => ({
sticker_id: sticker.id,
start: index * intervalDuration,
end: (index + 1) * intervalDuration,
scale: sticker.scale || 1.0,
transform_x: sticker.x || 0,
transform_y: sticker.y || 0
}));
}
// 创建动画贴纸效果
createAnimatedSticker(stickerId, startTime, duration, keyframes) {
const configs = [];
const segmentDuration = duration / keyframes.length;
keyframes.forEach((keyframe, index) => {
configs.push({
sticker_id: stickerId,
start: startTime + (index * segmentDuration),
end: startTime + ((index + 1) * segmentDuration),
scale: keyframe.scale || 1.0,
transform_x: keyframe.x || 0,
transform_y: keyframe.y || 0
});
});
return configs;
}
// 创建随机位置贴纸
createRandomPositionStickers(stickerId, count, startTime, duration) {
const configs = [];
const segmentDuration = duration / count;
for (let i = 0; i < count; i++) {
configs.push({
sticker_id: stickerId,
start: startTime + (i * segmentDuration),
end: startTime + ((i + 1) * segmentDuration),
scale: 0.5 + Math.random() * 1.0, // 0.5-1.5倍缩放
transform_x: (Math.random() - 0.5) * 400, // -200到200像素
transform_y: (Math.random() - 0.5) * 400 // -200到200像素
});
}
return configs;
}
// 批量添加贴纸
async batchAddStickers(draftUrl, stickerConfigs) {
const results = [];
for (const config of stickerConfigs) {
try {
const result = await this.addSticker(draftUrl, config);
results.push(result);
// 添加延迟避免请求过快
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
console.error('贴纸添加失败:', error);
results.push({ error: error.message });
}
}
return results;
}
// 创建贴纸模板
createStickerTemplate(templateType, stickerId, baseTime, baseDuration) {
switch (templateType) {
case 'corner-decoration':
return [
{
sticker_id: stickerId,
start: baseTime,
end: baseTime + baseDuration,
scale: 0.3,
transform_x: -400,
transform_y: -300
},
{
sticker_id: stickerId,
start: baseTime,
end: baseTime + baseDuration,
scale: 0.3,
transform_x: 400,
transform_y: -300
},
{
sticker_id: stickerId,
start: baseTime,
end: baseTime + baseDuration,
scale: 0.3,
transform_x: -400,
transform_y: 300
},
{
sticker_id: stickerId,
start: baseTime,
end: baseTime + baseDuration,
scale: 0.3,
transform_x: 400,
transform_y: 300
}
];
case 'center-highlight':
return [{
sticker_id: stickerId,
start: baseTime,
end: baseTime + baseDuration,
scale: 2.0,
transform_x: 0,
transform_y: 0
}];
case 'floating-animation':
return this.createAnimatedSticker(stickerId, baseTime, baseDuration, [
{ x: -100, y: -100, scale: 0.8 },
{ x: 100, y: -100, scale: 1.0 },
{ x: 100, y: 100, scale: 1.2 },
{ x: -100, y: 100, scale: 1.0 },
{ x: -100, y: -100, scale: 0.8 }
]);
default:
return [{
sticker_id: stickerId,
start: baseTime,
end: baseTime + baseDuration,
scale: 1.0,
transform_x: 0,
transform_y: 0
}];
}
}
}
// 使用示例
const stickerManager = new StickerManager();
// 创建贴纸序列
const stickerSequence = stickerManager.createStickerSequence([
{ id: "7326810673609018675", scale: 1.0, x: 0, y: 0 },
{ id: "7326810673609018676", scale: 1.2, x: 100, y: -50 },
{ id: "7326810673609018677", scale: 0.8, x: -100, y: 50 }
], 2000000);
// 创建动画贴纸
const animatedSticker = stickerManager.createAnimatedSticker(
"7326810673609018675",
5000000,
3000000,
[
{ x: -200, y: 0, scale: 0.5 },
{ x: 0, y: 0, scale: 1.0 },
{ x: 200, y: 0, scale: 1.5 },
{ x: 0, y: 0, scale: 1.0 }
]
);
// 创建模板贴纸
const cornerDecorations = stickerManager.createStickerTemplate(
'corner-decoration',
"7326810673609018675",
0,
10000000
);
// 批量添加
const allConfigs = [...stickerSequence, ...animatedSticker, ...cornerDecorations];
await stickerManager.batchAddStickers(draftUrl, allConfigs);
```
### Python 示例
```python
import requests
import time
import random
from typing import List, Dict
class StickerProcessor:
def __init__(self, base_url: str = "https://api.assets.jcaigc.cn"):
self.base_url = base_url
def add_sticker(self, draft_url: str, sticker_config: Dict) -> Dict:
response = requests.post(
f'{self.base_url}/openapi/capcut-mate/v1/add_sticker',
headers={'Content-Type': 'application/json'},
json={
"draft_url": draft_url,
**sticker_config
}
)
response.raise_for_status()
return response.json()
def create_sticker_sequence(self, stickers: List[Dict], interval_duration: int = 1000000) -> List[Dict]:
"""创建贴纸序列"""
configs = []
for i, sticker in enumerate(stickers):
configs.append({
"sticker_id": sticker["id"],
"start": i * interval_duration,
"end": (i + 1) * interval_duration,
"scale": sticker.get("scale", 1.0),
"transform_x": sticker.get("x", 0),
"transform_y": sticker.get("y", 0)
})
return configs
def create_animated_sticker(self, sticker_id: str, start_time: int,
duration: int, keyframes: List[Dict]) -> List[Dict]:
"""创建动画贴纸效果"""
configs = []
segment_duration = duration // len(keyframes)
for i, keyframe in enumerate(keyframes):
configs.append({
"sticker_id": sticker_id,
"start": start_time + (i * segment_duration),
"end": start_time + ((i + 1) * segment_duration),
"scale": keyframe.get("scale", 1.0),
"transform_x": keyframe.get("x", 0),
"transform_y": keyframe.get("y", 0)
})
return configs
def create_random_stickers(self, sticker_id: str, count: int,
start_time: int, duration: int) -> List[Dict]:
"""创建随机位置贴纸"""
configs = []
segment_duration = duration // count
for i in range(count):
configs.append({
"sticker_id": sticker_id,
"start": start_time + (i * segment_duration),
"end": start_time + ((i + 1) * segment_duration),
"scale": 0.5 + random.random() * 1.0, # 0.5-1.5倍缩放
"transform_x": int((random.random() - 0.5) * 400), # -200到200像素
"transform_y": int((random.random() - 0.5) * 400) # -200到200像素
})
return configs
def batch_add_stickers(self, draft_url: str, sticker_configs: List[Dict]) -> List[Dict]:
"""批量添加贴纸"""
results = []
for config in sticker_configs:
try:
result = self.add_sticker(draft_url, config)
results.append(result)
time.sleep(0.1) # 避免请求过快
except Exception as e:
print(f"贴纸添加失败: {e}")
results.append({"error": str(e)})
return results
# 使用示例
processor = StickerProcessor()
# 基本贴纸
basic_config = {
"sticker_id": "7326810673609018675",
"start": 0,
"end": 5000000,
"scale": 1.0
}
# 贴纸序列
sequence_configs = processor.create_sticker_sequence([
{"id": "7326810673609018675", "scale": 1.0, "x": 0, "y": 0},
{"id": "7326810673609018676", "scale": 1.2, "x": 100, "y": -50},
{"id": "7326810673609018677", "scale": 0.8, "x": -100, "y": 50}
], interval_duration=2000000)
# 动画贴纸
animated_configs = processor.create_animated_sticker(
"7326810673609018675",
start_time=10000000,
duration=4000000,
keyframes=[
{"x": -200, "y": 0, "scale": 0.5},
{"x": 0, "y": 0, "scale": 1.0},
{"x": 200, "y": 0, "scale": 1.5},
{"x": 0, "y": 0, "scale": 1.0}
]
)
# 批量添加
draft_url = "YOUR_DRAFT_URL"
all_configs = [basic_config] + sequence_configs + animated_configs
results = processor.batch_add_stickers(draft_url, all_configs)
for i, result in enumerate(results):
if "error" not in result:
print(f"贴纸 {i+1} 添加成功: {result['segment_id']}")
else:
print(f"贴纸 {i+1} 添加失败: {result['error']}")
```
## 错误码说明
| 错误码 | 错误信息 | 说明 | 解决方案 |
|--------|----------|------|----------|
| 400 | draft_url是必填项 | 缺少草稿URL参数 | 提供有效的draft_url |
| 400 | sticker_id是必填项 | 缺少贴纸ID参数 | 提供有效的sticker_id |
| 400 | start是必填项 | 缺少开始时间参数 | 提供有效的start时间 |
| 400 | end是必填项 | 缺少结束时间参数 | 提供有效的end时间 |
| 400 | 时间范围无效 | end必须大于start | 确保结束时间大于开始时间 |
| 400 | 缩放比例无效 | scale超出建议范围 | 使用0.1-5.0范围内的缩放值 |
| 404 | 草稿不存在 | 指定的草稿URL无效 | 检查草稿URL是否正确 |
| 404 | 贴纸不存在 | 指定的贴纸ID无效 | 确认贴纸ID是否正确 |
| 500 | 贴纸添加失败 | 内部处理错误 | 联系技术支持 |
## 注意事项
1. **时间单位**: 所有时间参数使用微秒(1秒 = 1,000,000微秒)
2. **贴纸ID**: 确保使用有效的贴纸ID
3. **时间范围**: end必须大于start
4. **缩放范围**: scale建议在0.1-5.0范围内
5. **位置范围**: transform_x和transform_y应在合理范围内
6. **轨道管理**: 系统自动创建贴纸轨道
7. **性能考虑**: 避免同时添加大量贴纸
## 工作流程
1. 验证必填参数(draft_url, sticker_id, start, end
2. 检查时间范围的有效性
3. 从缓存中获取草稿
4. 创建贴纸轨道(如果不存在)
5. 创建图像调节设置
6. 创建贴纸片段
7. 添加片段到轨道
8. 保存草稿
9. 返回贴纸信息
## 相关接口
- [创建草稿](./create_draft.md)
- [添加视频](./add_videos.md)
- [添加音频](./add_audios.md)
- [添加图片](./add_images.md)
- [保存草稿](./save_draft.md)
- [生成视频](./gen_video.md)
-385
View File
@@ -1,385 +0,0 @@
# add_text 接口文档
## 接口概述
添加文字到剪映草稿中,支持丰富的文字样式、动画效果、阴影、背景、边框等功能。
---
## 接口信息
### RESTful API 端点
```
POST /add_text
```
### Content-Type
```
application/json
```
---
## 请求参数
### 基础参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| **text** | string | **是** | - | 文字内容(必需参数) |
| **start** | number | **是** | - | 文字开始时间(秒) |
| **end** | number | **是** | - | 文字结束时间(秒) |
| draft_id | string | 否 | null | 草稿 ID |
| width | integer | 否 | 1080 | 画布宽度 |
| height | integer | 否 | 1920 | 画布高度 |
### 文字样式参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| font | string | 否 | "文轩体" | 字体名称 |
| font_color/color | string | 否 | "#FF0000" | 文字颜色(16进制) |
| font_size/size | number | 否 | 8.0 | 文字大小 |
| font_alpha/alpha | number | 否 | 1.0 | 文字透明度(0.0-1.0 |
| vertical | boolean | 否 | false | 是否竖排文字 |
| track_name | string | 否 | "text_main" | 文字轨道名称 |
### 位置和尺寸参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| transform_x | number | 否 | 0 | X 轴位移(-1.0 到 1.0 |
| transform_y | number | 否 | 0 | Y 轴位移(-1.0 到 1.0 |
| fixed_width | number | 否 | -1 | 固定宽度(-1 表示自动) |
| fixed_height | number | 否 | -1 | 固定高度(-1 表示自动) |
### 边框参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| border_alpha | number | 否 | 1.0 | 边框透明度 |
| border_color | string | 否 | "#000000" | 边框颜色 |
| border_width | number | 否 | 0.0 | 边框宽度 |
### 背景参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| background_color | string | 否 | "#000000" | 背景颜色 |
| background_style | integer | 否 | 0 | 背景样式 |
| background_alpha | number | 否 | 0.0 | 背景透明度 |
| background_round_radius | number | 否 | 0.0 | 背景圆角半径 |
| background_height | number | 否 | 0.14 | 背景高度(0.0-1.0 |
| background_width | number | 否 | 0.14 | 背景宽度(0.0-1.0 |
| background_horizontal_offset | number | 否 | 0.5 | 背景水平偏移 |
| background_vertical_offset | number | 否 | 0.5 | 背景垂直偏移 |
### 阴影参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| shadow_enabled | boolean | 否 | false | 是否启用阴影 |
| shadow_alpha | number | 否 | 0.9 | 阴影透明度 |
| shadow_angle | number | 否 | -45.0 | 阴影角度(-180 到 180 |
| shadow_color | string | 否 | "#000000" | 阴影颜色 |
| shadow_distance | number | 否 | 5.0 | 阴影距离 |
| shadow_smoothing | number | 否 | 0.15 | 阴影平滑度 |
### 特效参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| bubble_effect_id | string | 否 | null | 气泡特效 ID |
| bubble_resource_id | string | 否 | null | 气泡资源 ID |
| effect_effect_id | string | 否 | null | 装饰特效 ID |
### 动画参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| intro_animation | string | 否 | null | 入场动画类型 |
| intro_duration | number | 否 | 0.5 | 入场动画时长(秒) |
| outro_animation | string | 否 | null | 出场动画类型 |
| outro_duration | number | 否 | 0.5 | 出场动画时长(秒) |
### 多样式文本参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| text_styles | array | 否 | [] | 多样式文本配置数组 |
**text_styles 数组元素结构:**
```json
{
"start": 0,
"end": 5,
"font": "字体名称",
"style": {
"size": 10.0,
"color": "#FF0000",
"alpha": 1.0,
"bold": false,
"italic": false,
"underline": false
},
"border": {
"width": 0.0,
"color": "#000000",
"alpha": 1.0
}
}
```
---
## 响应参数
### 响应体 (JSON)
| 参数名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 请求是否成功 |
| output | object/string | 成功时返回草稿结果信息 |
| error | string | 失败时的错误信息 |
---
## 请求示例
### 示例 1: 基础文字添加
```bash
curl -X POST http://localhost:9001/add_text \
-H "Content-Type: application/json" \
-d '{
"text": "Hello World",
"start": 0,
"end": 5
}'
```
### 示例 2: 带样式的文字
```json
{
"text": "标题文字",
"start": 0,
"end": 3,
"draft_id": "dfd_12345",
"font": "思源黑体",
"font_color": "#FFD700",
"font_size": 12.0,
"transform_y": -0.7,
"shadow_enabled": true,
"shadow_color": "#000000",
"shadow_alpha": 0.8
}
```
### 示例 3: 带背景的文字
```json
{
"text": "重要提示",
"start": 2,
"end": 8,
"draft_id": "dfd_12345",
"font_size": 10.0,
"font_color": "#FFFFFF",
"background_color": "#FF0000",
"background_alpha": 0.8,
"background_round_radius": 10.0,
"transform_y": 0.8
}
```
### 示例 4: 多样式彩色文字
```json
{
"text": "彩色文字效果展示",
"start": 0,
"end": 5,
"draft_id": "dfd_12345",
"text_styles": [
{
"start": 0,
"end": 2,
"style": {"color": "#FF0000", "size": 10.0}
},
{
"start": 2,
"end": 4,
"style": {"color": "#00FF00", "size": 10.0}
},
{
"start": 4,
"end": 6,
"style": {"color": "#0000FF", "size": 10.0}
}
]
}
```
### 示例 5: 带入场动画的文字
```json
{
"text": "欢迎观看",
"start": 0,
"end": 3,
"draft_id": "dfd_12345",
"font_size": 15.0,
"intro_animation": "fade_in",
"intro_duration": 1.0,
"outro_animation": "fade_out",
"outro_duration": 0.5
}
```
### 示例 6: Python 完整示例
```python
import requests
url = "http://localhost:9001/add_text"
data = {
"text": "精彩内容",
"start": 1,
"end": 6,
"draft_id": "dfd_abc123",
"font": "思源黑体",
"font_color": "#FFFFFF",
"font_size": 12.0,
"transform_y": -0.6,
"shadow_enabled": True,
"shadow_alpha": 0.9,
"shadow_color": "#000000",
"shadow_distance": 5.0,
"background_alpha": 0.6,
"background_color": "#000000",
"background_round_radius": 8.0,
"intro_animation": "slide_in",
"intro_duration": 0.8
}
response = requests.post(url, json=data)
result = response.json()
print(f"Success: {result['success']}")
```
---
## 响应示例
### 成功响应
```json
{
"success": true,
"output": {
"draft_id": "dfd_1234567890abcdef",
"draft_url": "http://example.com/preview?draft_id=dfd_1234567890abcdef"
},
"error": ""
}
```
### 失败响应
```json
{
"success": false,
"output": "",
"error": "Hi, the required parameters 'text', 'start' or 'end' are missing."
}
```
---
## 使用场景
### 场景 1: 视频标题
```json
{
"text": "旅行VLOG第1集",
"start": 0,
"end": 3,
"font_size": 15.0,
"font_color": "#FFFFFF",
"transform_y": -0.7,
"shadow_enabled": true,
"intro_animation": "zoom_in"
}
```
### 场景 2: 字幕
```json
{
"text": "这是一段字幕文字",
"start": 5,
"end": 10,
"font_size": 6.0,
"font_color": "#FFFFFF",
"transform_y": 0.8,
"background_alpha": 0.7,
"background_color": "#000000"
}
```
### 场景 3: 水印
```json
{
"text": "© 2025",
"start": 0,
"end": 30,
"font_size": 4.0,
"font_alpha": 0.5,
"transform_x": 0.8,
"transform_y": 0.85
}
```
---
## 注意事项
1. **必需参数**: text, start, end 是必需的
2. **坐标系统**: transform_x/y 使用相对坐标(-1.0 到 1.0
3. **颜色格式**: 使用 16 进制颜色码,如 "#FF0000"
4. **透明度**: alpha 值范围 0.0(完全透明)到 1.0(完全不透明)
5. **动画类型**: 需先通过 `/get_text_intro_types` 等接口获取可用类型
6. **多样式文本**: text_styles 的 start/end 是字符索引,不是时间
7. **字体支持**: 不同环境支持的字体可能不同
---
## 相关接口
- `GET /get_text_intro_types` - 获取文字入场动画类型
- `GET /get_text_outro_types` - 获取文字出场动画类型
- `GET /get_text_loop_anim_types` - 获取文字循环动画类型
- `GET /get_font_types` - 获取可用字体列表
- `POST /add_subtitle` - 添加字幕(SRT格式)
---
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2025-10-21 | 初始版本 |
---
## 技术支持
如有问题,请联系:
- Email: sguann2023@gmail.com
- GitHub Issues: https://github.com/sun-guannan/CapCutAPI/issues
+229
View File
@@ -0,0 +1,229 @@
# 创建文本富文本样式接口文档
## 接口概述
为文本创建富文本样式,支持关键词高亮、颜色设置、字体大小调整等功能。该接口可以将普通文本转换为包含样式信息的富文本格式,实现关键词突出显示、多样化的文本展示效果。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 接口信息
- **请求方式**: POST
- **接口路径**: `/openapi/capcut-mate/v1/add_text_style`
- **Content-Type**: `application/json`
## 请求参数
### 请求体 (Body)
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| text | string | 是 | - | 要处理的文本内容 |
| keyword | string | 是 | - | 关键词,多个用 \| 分隔 |
| font_size | integer | 否 | 12 | 普通文本的字体大小 |
| keyword_color | string | 否 | "#ff7100" | 关键词文本颜色(十六进制) |
| keyword_font_size | integer | 否 | 15 | 关键词字体大小 |
### 参数详细说明
#### text (必填)
- **类型**: string
- **描述**: 需要进行样式处理的原始文本内容
- **示例**: "五个快乐到死的顶级思维"
#### keyword (必填)
- **类型**: string
- **描述**: 需要高亮显示的关键词,支持多个关键词用竖线(|)分隔
- **示例**: "快乐|顶级思维"
- **注意**: 系统会按关键词长度优先匹配,避免短关键词覆盖长关键词
#### font_size (可选)
- **类型**: integer
- **默认值**: 12
- **描述**: 普通文本(非关键词)的字体大小
- **范围**: 建议 8-72
#### keyword_color (可选)
- **类型**: string
- **默认值**: "#ff7100" (橙色)
- **描述**: 关键词的文本颜色,使用十六进制格式
- **格式**: #RRGGBB
- **示例**: "#ff0000" (红色), "#00ff00" (绿色), "#0000ff" (蓝色)
#### keyword_font_size (可选)
- **类型**: integer
- **默认值**: 15
- **描述**: 关键词的字体大小
- **范围**: 建议 8-72
## 请求示例
```bash
curl -X POST "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_text_style" \
-H "Content-Type: application/json" \
-d '{
"text": "五个快乐到死的顶级思维",
"keyword": "快乐|顶级思维",
"font_size": 12,
"keyword_color": "#ff7100",
"keyword_font_size": 15
}'
```
## 响应格式
### 成功响应
```json
{
"code": 0,
"message": "Success",
"data": {
"text_style": "{\"styles\":[{\"fill\":{\"content\":{\"solid\":{\"color\":[1,1,1]}}},\"range\":[0,2],\"size\":12,\"font\":{\"id\":\"\",\"path\":\"\"}},{\"fill\":{\"content\":{\"solid\":{\"color\":[1,0.44313725490196076,0]}}},\"range\":[2,4],\"size\":15,\"font\":{\"id\":\"\",\"path\":\"\"},\"useLetterColor\":true},{\"fill\":{\"content\":{\"solid\":{\"color\":[1,1,1]}}},\"range\":[4,7],\"size\":12,\"font\":{\"id\":\"\",\"path\":\"\"}},{\"fill\":{\"content\":{\"solid\":{\"color\":[1,0.44313725490196076,0]}}},\"range\":[7,11],\"size\":15,\"font\":{\"id\":\"\",\"path\":\"\"},\"useLetterColor\":true}],\"text\":\"五个快乐到死的顶级思维\"}"
}
}
```
### text_style 字段解析
`text_style` 字段是一个JSON字符串,解析后的结构如下:
```json
{
"text": "五个快乐到死的顶级思维",
"styles": [
{
"fill": {
"content": {
"solid": {
"color": [1, 1, 1]
}
}
},
"range": [0, 2],
"size": 12,
"font": {
"id": "",
"path": ""
}
},
{
"fill": {
"content": {
"solid": {
"color": [1, 0.44313725490196076, 0]
}
}
},
"range": [2, 4],
"size": 15,
"font": {
"id": "",
"path": ""
},
"useLetterColor": true
}
]
}
```
#### 样式对象字段说明
| 字段名 | 类型 | 描述 |
|--------|------|------|
| text | string | 原始文本内容 |
| styles | array | 样式片段数组 |
#### 样式片段字段说明
| 字段名 | 类型 | 描述 |
|--------|------|------|
| fill.content.solid.color | array | RGB颜色值数组,值范围0-1 |
| range | array | 文本范围 [起始位置, 结束位置] |
| size | integer | 字体大小 |
| font.id | string | 字体ID(当前为空) |
| font.path | string | 字体路径(当前为空) |
| useLetterColor | boolean | 是否使用字母颜色(仅关键词包含) |
### 错误响应
```json
{
"code": 2026,
"message": "无效的文本样式信息,请检查文本或关键词参数"
}
```
## 错误码说明
| 错误码 | 错误信息 | 描述 |
|--------|----------|------|
| 2026 | 无效的文本样式信息 | 文本或关键词参数格式错误或值无效 |
| 2027 | 文本样式创建失败 | 创建文本样式过程中发生错误 |
## 使用说明
### 关键词匹配规则
1. **优先级匹配**: 长关键词优先于短关键词,避免匹配冲突
2. **完全匹配**: 关键词必须完全匹配文本中的内容
3. **无重叠**: 已匹配的文本位置不会被其他关键词重复匹配
4. **大小写敏感**: 关键词匹配区分大小写
### 颜色格式
- **十六进制格式**: #RRGGBB,如 #ff7100
- **自动转换**: 系统会自动将十六进制颜色转换为0-1范围的RGB值
- **容错处理**: 无效颜色会自动使用默认橙色 #ff7100
### 样式生成逻辑
1. **文本分割**: 根据关键词位置将文本分割为多个片段
2. **样式应用**: 为每个片段应用相应的样式(普通样式或关键词样式)
3. **连续排列**: 样式片段按文本顺序连续排列,确保完整覆盖
## 应用场景
### 内容创作
- **标题制作**: 突出标题中的关键信息
- **字幕设计**: 为视频字幕添加重点强调
- **广告文案**: 突出产品特色和卖点
### 教育培训
- **重点标记**: 标记学习材料中的重点概念
- **知识强化**: 通过视觉差异加强记忆
- **层次展示**: 区分不同重要级别的内容
### 营销推广
- **品牌突出**: 强调品牌名称和标语
- **优惠信息**: 突出价格、折扣等关键信息
- **行动召唤**: 强调"立即购买"、"马上行动"等词语
## 技术实现细节
### 文本处理流程
1. **关键词解析**: 将关键词字符串按 | 分割并按长度排序
2. **位置查找**: 在原文本中查找所有关键词的位置
3. **冲突处理**: 处理关键词重叠问题,优先匹配长关键词
4. **样式生成**: 为每个文本片段生成对应的样式信息
### 颜色处理
- **RGB转换**: 十六进制颜色转换为浮点RGB值
- **范围标准化**: 将0-255的整数值转换为0-1的浮点值
- **精度保持**: 保持足够的小数精度确保颜色准确
### 性能优化
- **高效匹配**: 使用正则表达式进行快速文本匹配
- **内存管理**: 合理管理文本片段和样式对象的内存使用
- **错误恢复**: 提供完善的错误处理和默认值机制
## 注意事项
- 关键词长度建议控制在合理范围内,过长的关键词可能影响匹配效果
- 颜色值建议使用标准的十六进制格式,确保颜色显示准确
- 字体大小建议在8-72范围内,过小或过大都可能影响显示效果
- 关键词数量建议适中,过多的关键词可能导致文本过于复杂
- 建议在前端预览样式效果,确保符合设计要求
## 相关接口
- [添加字幕](./add_captions.md) - 向草稿添加字幕内容
- [创建草稿](./create_draft.md) - 创建新的剪映草稿
- [保存草稿](./save_draft.md) - 保存草稿更改
-411
View File
@@ -1,411 +0,0 @@
# add_video 接口文档
## 接口概述
添加视频到剪映草稿中,支持视频裁剪、位置调整、缩放、变速、转场、蒙版、背景模糊等功能。
---
## 接口信息
### RESTful API 端点
```
POST /add_video
```
### Content-Type
```
application/json
```
---
## 请求参数
### 请求体 (JSON)
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| **video_url** | string | **是** | - | 视频文件的 URL 地址(必需参数) |
| draft_folder | string | 否 | null | 草稿文件夹路径 |
| draft_id | string | 否 | null | 草稿 ID,不提供则创建新草稿 |
| width | integer | 否 | 1080 | 画布宽度(像素) |
| height | integer | 否 | 1920 | 画布高度(像素) |
| start | number | 否 | 0 | 视频起始时间(秒) |
| end | number | 否 | 0 | 视频结束时间(秒),0 表示到视频末尾 |
| target_start | number | 否 | 0 | 视频在时间轴上的起始位置(秒) |
| duration | number | 否 | null | 视频显示时长(秒),优先级高于 end |
### 位置和缩放参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| transform_x | number | 否 | 0 | X 轴位移,范围 -1.0 到 1.0(相对画布) |
| transform_y | number | 否 | 0 | Y 轴位移,范围 -1.0 到 1.0(相对画布) |
| scale_x | number | 否 | 1 | X 轴缩放比例 |
| scale_y | number | 否 | 1 | Y 轴缩放比例 |
### 播放控制参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| speed | number | 否 | 1.0 | 播放速度,1.0 为正常速度 |
| volume | number | 否 | 1.0 | 音量大小,范围 0.0 到 1.0 |
### 轨道参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| track_name | string | 否 | "video_main" | 视频轨道名称 |
| relative_index | integer | 否 | 0 | 轨道渲染顺序索引 |
### 转场参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| transition | string | 否 | null | 转场效果类型(如 "fade_in", "dissolve" 等) |
| transition_duration | number | 否 | 0.5 | 转场效果持续时间(秒) |
### 蒙版参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| mask_type | string | 否 | null | 蒙版类型 |
| mask_center_x | number | 否 | 0.5 | 蒙版中心 X 坐标(0.0-1.0 |
| mask_center_y | number | 否 | 0.5 | 蒙版中心 Y 坐标(0.0-1.0 |
| mask_size | number | 否 | 1.0 | 蒙版大小(相对屏幕高度) |
| mask_rotation | number | 否 | 0.0 | 蒙版旋转角度(度) |
| mask_feather | number | 否 | 0.0 | 蒙版羽化程度(0.0-1.0 |
| mask_invert | boolean | 否 | false | 是否反转蒙版 |
| mask_rect_width | number | 否 | null | 矩形蒙版宽度 |
| mask_round_corner | number | 否 | null | 矩形蒙版圆角半径 |
### 背景模糊参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| background_blur | integer | 否 | null | 背景模糊级别:1(轻度)、2(中度)、3(强度)、4(最大) |
---
## 响应参数
### 响应体 (JSON)
| 参数名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 请求是否成功 |
| output | object/string | 成功时返回草稿结果信息 |
| error | string | 失败时的错误信息 |
### 成功响应的 output 字段
| 参数名 | 类型 | 说明 |
|--------|------|------|
| draft_id | string | 草稿唯一标识符 |
| draft_url | string | 草稿预览 URL |
---
## 请求示例
### 示例 1: 基础视频添加
```bash
curl -X POST http://localhost:9001/add_video \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://example.com/video.mp4",
"start": 0,
"end": 10
}'
```
**请求体 (JSON):**
```json
{
"video_url": "https://example.com/video.mp4",
"start": 0,
"end": 10
}
```
### 示例 2: 完整参数视频添加
```bash
curl -X POST http://localhost:9001/add_video \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://example.com/background.mp4",
"draft_id": "dfd_12345",
"width": 1920,
"height": 1080,
"start": 5,
"end": 15,
"target_start": 0,
"transform_x": 0.2,
"transform_y": -0.1,
"scale_x": 1.2,
"scale_y": 1.2,
"speed": 1.5,
"volume": 0.8,
"track_name": "video_main",
"transition": "fade_in",
"transition_duration": 1.0
}'
```
**请求体 (JSON):**
```json
{
"video_url": "https://example.com/background.mp4",
"draft_id": "dfd_12345",
"width": 1920,
"height": 1080,
"start": 5,
"end": 15,
"target_start": 0,
"transform_x": 0.2,
"transform_y": -0.1,
"scale_x": 1.2,
"scale_y": 1.2,
"speed": 1.5,
"volume": 0.8,
"track_name": "video_main",
"transition": "fade_in",
"transition_duration": 1.0
}
```
### 示例 3: 带蒙版和背景模糊
```bash
curl -X POST http://localhost:9001/add_video \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://example.com/portrait.mp4",
"width": 1080,
"height": 1920,
"mask_type": "circle",
"mask_center_x": 0.5,
"mask_center_y": 0.5,
"mask_size": 0.8,
"mask_feather": 0.1,
"background_blur": 3
}'
```
**请求体 (JSON):**
```json
{
"video_url": "https://example.com/portrait.mp4",
"width": 1080,
"height": 1920,
"mask_type": "circle",
"mask_center_x": 0.5,
"mask_center_y": 0.5,
"mask_size": 0.8,
"mask_feather": 0.1,
"background_blur": 3
}
```
### 示例 4: Python 请求示例
```python
import requests
url = "http://localhost:9001/add_video"
headers = {
"Content-Type": "application/json"
}
data = {
"video_url": "https://example.com/video.mp4",
"draft_id": "dfd_abc123",
"start": 0,
"end": 10,
"transform_y": -0.5,
"scale_x": 1.5,
"scale_y": 1.5,
"speed": 2.0,
"volume": 0.6,
"transition": "dissolve",
"transition_duration": 0.8
}
response = requests.post(url, json=data, headers=headers)
result = response.json()
print(f"Success: {result['success']}")
if result['success']:
print(f"Draft ID: {result['output']['draft_id']}")
print(f"Draft URL: {result['output']['draft_url']}")
else:
print(f"Error: {result['error']}")
```
---
## 响应示例
### 成功响应
**状态码:** 200 OK
```json
{
"success": true,
"output": {
"draft_id": "dfd_1234567890abcdef",
"draft_url": "http://example.com/preview?draft_id=dfd_1234567890abcdef"
},
"error": ""
}
```
### 失败响应 - 缺少必需参数
**状态码:** 200 OK
```json
{
"success": false,
"output": "",
"error": "Hi, the required parameters 'video_url' are missing."
}
```
### 失败响应 - 处理错误
**状态码:** 200 OK
```json
{
"success": false,
"output": "",
"error": "Error occurred while processing video: Invalid video format."
}
```
---
## 错误码说明
| 错误信息 | 说明 | 解决方案 |
|---------|------|---------|
| "Hi, the required parameters 'video_url' are missing." | 缺少必需的 video_url 参数 | 请在请求体中提供 video_url 参数 |
| "Error occurred while processing video: ..." | 视频处理过程中出错 | 检查视频 URL 是否有效,格式是否支持 |
---
## 使用场景
### 场景 1: 添加背景视频
```json
{
"video_url": "https://example.com/background.mp4",
"start": 0,
"end": 30,
"volume": 0.5
}
```
### 场景 2: 添加画中画视频
```json
{
"video_url": "https://example.com/pip.mp4",
"track_name": "video_pip",
"transform_x": 0.6,
"transform_y": -0.6,
"scale_x": 0.3,
"scale_y": 0.3,
"relative_index": 1
}
```
### 场景 3: 快进视频片段
```json
{
"video_url": "https://example.com/timelapse.mp4",
"start": 10,
"end": 40,
"speed": 3.0,
"volume": 0
}
```
### 场景 4: 视频慢动作效果
```json
{
"video_url": "https://example.com/action.mp4",
"start": 5,
"duration": 10,
"speed": 0.5,
"transition": "fade_in",
"transition_duration": 1.0
}
```
### 场景 5: 竖屏视频添加模糊背景
```json
{
"video_url": "https://example.com/portrait.mp4",
"width": 1080,
"height": 1920,
"background_blur": 4,
"scale_x": 0.8,
"scale_y": 0.8
}
```
---
## 注意事项
1. **必需参数**: `video_url` 是唯一的必需参数,其他参数都有默认值
2. **时间参数**: `start``end` 的单位都是秒,支持小数
3. **坐标系统**: `transform_x``transform_y` 使用相对坐标系,范围通常在 -1.0 到 1.0 之间
4. **优先级**: 如果同时提供 `end``duration``duration` 优先级更高
5. **视频格式**: 支持常见视频格式(MP4, MOV, AVI 等)
6. **URL 要求**: video_url 必须是可访问的完整 URL
7. **draft_id**: 如果不提供 draft_id,系统会自动创建新草稿
8. **转场效果**: 需要先查询可用的转场类型,使用 `/get_transition_types` 接口
9. **蒙版类型**: 需要先查询可用的蒙版类型,使用 `/get_mask_types` 接口
---
## 相关接口
- `POST /create_draft` - 创建新草稿
- `POST /save_draft` - 保存草稿
- `GET /get_transition_types` - 获取可用转场类型
- `GET /get_mask_types` - 获取可用蒙版类型
- `POST /add_audio` - 添加音频
- `POST /add_text` - 添加文字
- `POST /add_image` - 添加图片
---
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2025-10-21 | 初始版本 |
---
## 技术支持
如有问题,请联系:
- Email: sguann2023@gmail.com
- GitHub Issues: https://github.com/sun-guannan/CapCutAPI/issues
+611
View File
@@ -0,0 +1,611 @@
# ADD_VIDEOS API 接口文档
## 接口信息
```
POST /openapi/capcut-mate/v1/add_videos
```
## 功能描述
批量向现有草稿中添加视频素材。该接口是一个功能强大的视频添加工具,支持多个视频的批量处理,包括时间范围控制、透明度调整、遮罩效果、转场动画、音量控制、缩放变换等高级功能。特别适合创建复杂的多视频组合场景,如画中画效果、视频拼接、过渡动画等。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"video_infos": "[{\"video_url\":\"https://assets.jcaigc.cn/video1.mp4\",\"width\":1024,\"height\":1024,\"start\":0,\"end\":5000000,\"duration\":5000000,\"mask\":\"圆形\",\"transition\":\"淡入淡出\",\"transition_duration\":500000,\"volume\":0.8}]",
"alpha": 0.5,
"scale_x": 1.0,
"scale_y": 1.0,
"transform_x": 100,
"transform_y": 200
}
```
### 主要参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| draft_url | string | ✅ | - | 目标草稿的完整URL |
| video_infos | string | ✅ | - | 视频信息数组的JSON字符串 |
| alpha | number | ❌ | 1.0 | 全局透明度(0-1) |
| scale_x | number | ❌ | 1.0 | X轴缩放比例 |
| scale_y | number | ❌ | 1.0 | Y轴缩放比例 |
| transform_x | number | ❌ | 0 | X轴位置偏移(像素) |
| transform_y | number | ❌ | 0 | Y轴位置偏移(像素) |
### video_infos 数组结构
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| video_url | string | ✅ | - | 视频文件的URL地址 |
| width | number | ✅ | - | 视频宽度(像素) |
| height | number | ✅ | - | 视频高度(像素) |
| start | number | ✅ | - | 视频开始播放时间(微秒) |
| end | number | ✅ | - | 视频结束播放时间(微秒) |
| duration | number | ✅ | - | 视频总时长(微秒) |
| mask | string | ❌ | - | 遮罩类型 |
| transition | string | ❌ | - | 转场效果名称 |
| transition_duration | number | ❌ | 500000 | 转场持续时间(微秒) |
| volume | number | ❌ | 1.0 | 音量大小(0-1) |
### 参数详解
#### 时间参数
- **start**: 视频在时间轴上的开始时间,单位微秒(1秒 = 1,000,000微秒)
- **end**: 视频在时间轴上的结束时间,单位微秒
- **duration**: 视频文件的总时长,用于素材创建
- **播放时长**: 实际播放时长 = end - start
#### 透明度参数
- **alpha**: 全局透明度,应用于所有添加的视频
- 1.0 = 完全不透明
- 0.5 = 半透明
- 0.0 = 完全透明
- 范围:0.0 - 1.0
#### 缩放参数
- **scale_x/scale_y**: X/Y轴方向的缩放比例
- 1.0 = 原始大小,0.5 = 缩小一半,2.0 = 放大两倍
- 建议范围:0.1 - 5.0
#### 位置参数
- **transform_x/transform_y**: X/Y轴方向的位置偏移,单位像素
- 正值向右/下移动,负值向左/上移动
- 以画布中心为原点
#### 遮罩类型
支持的遮罩类型:
- `圆形` - 圆形遮罩效果
- `爱心` - 爱心形状遮罩
- `星形` - 星形遮罩
- `矩形` - 矩形遮罩
- `线性` - 线性渐变遮罩
- `镜面` - 镜面反射遮罩
#### 转场效果
- **transition**: 转场效果名称
- **transition_duration**: 转场持续时间
- 最小值:100,000微秒(0.1秒)
- 最大值:2,500,000微秒(2.5秒)
- 推荐值:500,000微秒(0.5秒)
#### 音量控制
- **volume**: 视频音量大小
- 1.0 = 原始音量
- 0.5 = 一半音量
- 0.0 = 静音
- 范围:0.0 - 1.0
## 响应格式
### 成功响应 (200)
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"track_id": "video-track-uuid",
"video_ids": ["video1-uuid", "video2-uuid", "video3-uuid"],
"segment_ids": ["segment1-uuid", "segment2-uuid", "segment3-uuid"]
}
```
### 响应字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| draft_url | string | 更新后的草稿URL |
| track_id | string | 视频轨道ID |
| video_ids | array | 添加的视频ID列表 |
| segment_ids | array | 片段ID列表 |
## 使用示例
### cURL 示例
#### 1. 基本视频添加
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_videos \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"video_infos": "[{\"video_url\":\"https://assets.jcaigc.cn/video1.mp4\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":5000000,\"duration\":10000000}]"
}'
```
#### 2. 多视频批量添加
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_videos \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"video_infos": "[{\"video_url\":\"https://assets.jcaigc.cn/video1.mp4\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":5000000,\"duration\":10000000},{\"video_url\":\"https://assets.jcaigc.cn/video2.mp4\",\"width\":1280,\"height\":720,\"start\":5000000,\"end\":10000000,\"duration\":8000000}]",
"alpha": 0.8
}'
```
#### 3. 带遮罩和转场的视频
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_videos \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"video_infos": "[{\"video_url\":\"https://assets.jcaigc.cn/video1.mp4\",\"width\":1024,\"height\":1024,\"start\":0,\"end\":5000000,\"duration\":10000000,\"mask\":\"圆形\",\"transition\":\"淡入淡出\",\"transition_duration\":500000,\"volume\":0.8}]",
"alpha": 1.0,
"scale_x": 1.2,
"scale_y": 1.2
}'
```
#### 4. 画中画效果
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/add_videos \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"video_infos": "[{\"video_url\":\"https://assets.jcaigc.cn/main.mp4\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":10000000,\"duration\":15000000},{\"video_url\":\"https://assets.jcaigc.cn/pip.mp4\",\"width\":640,\"height\":360,\"start\":2000000,\"end\":8000000,\"duration\":10000000}]",
"transform_x": 300,
"transform_y": -200,
"scale_x": 0.3,
"scale_y": 0.3
}'
```
### JavaScript 示例
```javascript
const addVideos = async (draftUrl, videoConfig) => {
const response = await fetch('/openapi/capcut-mate/v1/add_videos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
draft_url: draftUrl,
...videoConfig
})
});
return response.json();
};
// 基本视频添加
const basicVideos = {
video_infos: JSON.stringify([
{
video_url: "https://assets.jcaigc.cn/video1.mp4",
width: 1920,
height: 1080,
start: 0,
end: 5000000,
duration: 10000000
}
])
};
// 多视频序列
const videoSequence = {
video_infos: JSON.stringify([
{
video_url: "https://assets.jcaigc.cn/intro.mp4",
width: 1920,
height: 1080,
start: 0,
end: 3000000,
duration: 5000000,
transition: "淡入淡出",
transition_duration: 500000
},
{
video_url: "https://assets.jcaigc.cn/main.mp4",
width: 1920,
height: 1080,
start: 3000000,
end: 15000000,
duration: 20000000,
volume: 0.8
},
{
video_url: "https://assets.jcaigc.cn/outro.mp4",
width: 1920,
height: 1080,
start: 15000000,
end: 18000000,
duration: 5000000,
mask: "圆形"
}
]),
alpha: 1.0
};
// 画中画效果
const pipEffect = {
video_infos: JSON.stringify([
{
video_url: "https://assets.jcaigc.cn/background.mp4",
width: 1920,
height: 1080,
start: 0,
end: 10000000,
duration: 15000000
},
{
video_url: "https://assets.jcaigc.cn/overlay.mp4",
width: 640,
height: 360,
start: 2000000,
end: 8000000,
duration: 10000000,
mask: "圆形"
}
]),
scale_x: 0.8,
scale_y: 0.8,
transform_x: 200,
transform_y: -150,
alpha: 0.9
};
try {
const result1 = await addVideos(draftUrl, basicVideos);
const result2 = await addVideos(draftUrl, videoSequence);
const result3 = await addVideos(draftUrl, pipEffect);
console.log('视频添加成功:', {
basic: result1,
sequence: result2,
pip: result3
});
} catch (error) {
console.error('添加失败:', error);
}
```
### 高级JavaScript示例
```javascript
class VideoManager {
constructor(baseUrl = 'https://capcut-mate.jcaigc.cn') {
this.baseUrl = baseUrl;
}
async addVideos(draftUrl, videoConfig) {
const response = await fetch(`${this.baseUrl}/openapi/capcut-mate/v1/add_videos`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
draft_url: draftUrl,
...videoConfig
})
});
return response.json();
}
// 创建视频序列
createVideoSequence(videos, transitionType = "淡入淡出", transitionDuration = 500000) {
let currentTime = 0;
const videoInfos = videos.map((video, index) => {
const videoInfo = {
video_url: video.url,
width: video.width,
height: video.height,
start: currentTime,
end: currentTime + video.playDuration,
duration: video.totalDuration,
volume: video.volume || 1.0
};
// 添加转场效果(除了最后一个视频)
if (index < videos.length - 1) {
videoInfo.transition = transitionType;
videoInfo.transition_duration = transitionDuration;
}
// 添加遮罩效果
if (video.mask) {
videoInfo.mask = video.mask;
}
currentTime += video.playDuration;
return videoInfo;
});
return {
video_infos: JSON.stringify(videoInfos)
};
}
// 创建画中画效果
createPictureInPicture(mainVideo, overlayVideo, position = { x: 300, y: -200 }, scale = 0.3) {
const videoInfos = [
{
video_url: mainVideo.url,
width: mainVideo.width,
height: mainVideo.height,
start: 0,
end: mainVideo.duration,
duration: mainVideo.duration
},
{
video_url: overlayVideo.url,
width: overlayVideo.width,
height: overlayVideo.height,
start: overlayVideo.start || 0,
end: overlayVideo.end || overlayVideo.duration,
duration: overlayVideo.duration,
mask: overlayVideo.mask || "圆形"
}
];
return {
video_infos: JSON.stringify(videoInfos),
transform_x: position.x,
transform_y: position.y,
scale_x: scale,
scale_y: scale
};
}
// 创建分屏效果
createSplitScreen(videos, layout = "horizontal") {
const videoInfos = videos.map((video, index) => {
let transform_x = 0, transform_y = 0;
if (layout === "horizontal") {
// 水平分屏
const sectionWidth = 1 / videos.length;
transform_x = (index - (videos.length - 1) / 2) * sectionWidth * video.width;
} else if (layout === "vertical") {
// 垂直分屏
const sectionHeight = 1 / videos.length;
transform_y = (index - (videos.length - 1) / 2) * sectionHeight * video.height;
}
return {
video_url: video.url,
width: video.width,
height: video.height,
start: video.start || 0,
end: video.end || video.duration,
duration: video.duration
};
});
return {
video_infos: JSON.stringify(videoInfos)
};
}
}
// 使用示例
const videoManager = new VideoManager();
// 创建视频序列
const sequence = videoManager.createVideoSequence([
{
url: "https://assets.jcaigc.cn/intro.mp4",
width: 1920,
height: 1080,
playDuration: 3000000,
totalDuration: 5000000
},
{
url: "https://assets.jcaigc.cn/main.mp4",
width: 1920,
height: 1080,
playDuration: 10000000,
totalDuration: 15000000,
volume: 0.8
}
]);
// 创建画中画
const pip = videoManager.createPictureInPicture(
{
url: "https://assets.jcaigc.cn/background.mp4",
width: 1920,
height: 1080,
duration: 10000000
},
{
url: "https://assets.jcaigc.cn/overlay.mp4",
width: 640,
height: 360,
duration: 6000000,
start: 2000000,
end: 8000000,
mask: "圆形"
}
);
await videoManager.addVideos(draftUrl, sequence);
await videoManager.addVideos(draftUrl, pip);
```
### Python 示例
```python
import requests
import json
from typing import List, Dict
class VideoProcessor:
def __init__(self, base_url="https://capcut-mate.jcaigc.cn"):
self.base_url = base_url
def add_videos(self, draft_url: str, video_config: Dict) -> Dict:
response = requests.post(
f'{self.base_url}/openapi/capcut-mate/v1/add_videos',
headers={'Content-Type': 'application/json'},
json={
"draft_url": draft_url,
**video_config
}
)
return response.json()
def create_video_sequence(self, videos: List[Dict], transition_type: str = "淡入淡出") -> Dict:
current_time = 0
video_infos = []
for i, video in enumerate(videos):
video_info = {
"video_url": video["url"],
"width": video["width"],
"height": video["height"],
"start": current_time,
"end": current_time + video["play_duration"],
"duration": video["total_duration"],
"volume": video.get("volume", 1.0)
}
# 添加转场效果(除了最后一个)
if i < len(videos) - 1:
video_info["transition"] = transition_type
video_info["transition_duration"] = 500000
# 添加遮罩
if "mask" in video:
video_info["mask"] = video["mask"]
video_infos.append(video_info)
current_time += video["play_duration"]
return {
"video_infos": json.dumps(video_infos)
}
def create_picture_in_picture(self, main_video: Dict, overlay_video: Dict,
position: Dict = None, scale: float = 0.3) -> Dict:
if position is None:
position = {"x": 300, "y": -200}
video_infos = [
{
"video_url": main_video["url"],
"width": main_video["width"],
"height": main_video["height"],
"start": 0,
"end": main_video["duration"],
"duration": main_video["duration"]
},
{
"video_url": overlay_video["url"],
"width": overlay_video["width"],
"height": overlay_video["height"],
"start": overlay_video.get("start", 0),
"end": overlay_video.get("end", overlay_video["duration"]),
"duration": overlay_video["duration"],
"mask": overlay_video.get("mask", "圆形")
}
]
return {
"video_infos": json.dumps(video_infos),
"transform_x": position["x"],
"transform_y": position["y"],
"scale_x": scale,
"scale_y": scale
}
# 使用示例
processor = VideoProcessor()
# 视频序列
videos = [
{
"url": "https://assets.jcaigc.cn/intro.mp4",
"width": 1920,
"height": 1080,
"play_duration": 3000000,
"total_duration": 5000000
},
{
"url": "https://assets.jcaigc.cn/main.mp4",
"width": 1920,
"height": 1080,
"play_duration": 10000000,
"total_duration": 15000000,
"volume": 0.8
}
]
sequence_config = processor.create_video_sequence(videos)
result = processor.add_videos("YOUR_DRAFT_URL", sequence_config)
print(f"结果: {result}")
```
## 错误码说明
| 错误码 | 错误信息 | 说明 | 解决方案 |
|--------|----------|------|----------|
| 400 | draft_url是必填项 | 缺少草稿URL参数 | 提供有效的草稿URL |
| 400 | video_infos是必填项 | 缺少视频信息参数 | 提供有效的视频信息JSON |
| 400 | video_infos格式错误 | JSON格式不正确 | 检查JSON字符串格式 |
| 400 | video_url是必填项 | 视频URL缺失 | 为每个视频提供URL |
| 400 | 视频尺寸无效 | width或height无效 | 提供正数的宽度和高度 |
| 400 | 时间范围无效 | end必须大于start | 确保结束时间大于开始时间 |
| 400 | 透明度值无效 | alpha不在0-1范围内 | 使用0-1之间的透明度值 |
| 404 | 草稿不存在 | 指定的草稿URL无效 | 检查草稿URL是否正确 |
| 404 | 视频资源不存在 | 视频URL无法访问 | 检查视频URL是否可访问 |
| 500 | 视频处理失败 | 内部处理错误 | 联系技术支持 |
## 注意事项
1. **JSON格式**: video_infos必须是合法的JSON字符串
2. **时间单位**: 所有时间参数使用微秒(1秒 = 1,000,000微秒)
3. **视频格式**: 确保视频文件格式被支持(如MP4、AVI等)
4. **文件大小**: 大视频文件可能影响处理速度
5. **网络访问**: 视频URL必须可以正常访问
6. **遮罩限制**: 只支持预定义的遮罩类型
7. **转场限制**: 转场时长有固定范围限制
8. **性能考虑**: 批量添加大量视频可能影响性能
## 工作流程
1. 验证必填参数(draft_url, video_infos
2. 解析video_infos JSON字符串
3. 验证每个视频的参数配置
4. 获取并解密草稿内容
5. 创建视频轨道
6. 添加视频片段到轨道
7. 应用透明度、缩放和位置变换
8. 添加遮罩和转场效果
9. 设置音量
10. 保存并加密草稿
11. 返回处理结果
## 相关接口
- [创建草稿](./create_draft.md)
- [添加音频](./add_audios.md)
- [添加图片](./add_images.md)
- [保存草稿](./save_draft.md)
- [生成视频](./gen_video.md)
+262 -193
View File
@@ -1,260 +1,329 @@
# create_draft 接口文档
## 接口概述
创建一个新的剪映草稿项目,支持自定义画布宽度和高度。
---
# CREATE_DRAFT API 接口文档
## 接口信息
### RESTful API 端点
```
POST /create_draft
POST /openapi/capcut-mate/v1/create_draft
```
### Content-Type
## 功能描述
```
application/json
```
创建剪映草稿。该接口用于创建一个新的剪映草稿项目,可以自定义视频的宽度和高度。创建成功后会返回草稿URL和帮助文档URL,为后续的视频编辑操作提供基础。
---
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### 请求体 (JSON)
```json
{
"width": 1920,
"height": 1080
}
```
### 参数说明
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| width | integer | | 1080 | 画布宽度像素 |
| height | integer | | 1920 | 画布高度像素 |
| width | number | | 1920 | 视频宽度(像素),必须大于等于1 |
| height | number | | 1080 | 视频高度(像素),必须大于等于1 |
---
### 参数详解
## 响应参数
#### 尺寸参数
### 响应体 (JSON)
- **width**: 草稿视频的宽度
- 最小值:1像素
- 建议常用值:1920、1280、720
- 支持自定义尺寸
| 参数名 | 类型 | 说明 |
- **height**: 草稿视频的高度
- 最小值:1像素
- 建议常用值:1080、720、480
- 支持自定义尺寸
#### 常用分辨率
| 分辨率名称 | 宽度 | 高度 | 适用场景 |
|------------|------|------|----------|
| 1080P | 1920 | 1080 | 高清视频制作 |
| 720P | 1280 | 720 | 标清视频制作 |
| 4K | 3840 | 2160 | 超高清视频制作 |
| 竖屏短视频 | 1080 | 1920 | 手机短视频 |
| 正方形 | 1080 | 1080 | 社交媒体内容 |
## 响应格式
### 成功响应 (200)
```json
{
"draft_url": "https://cm.jcaigc.cn/openapi/v1/get_draft?draft_id=2025092811473036584258",
"tip_url": "https://help.assets.jcaigc.cn/draft-usage"
}
```
### 响应字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 请求是否成功 |
| output | object | 成功时返回草稿信息 |
| error | string | 失败时的错误信息 |
| draft_url | string | 新创建的草稿URL,用于后续的编辑操作 |
| tip_url | string | 草稿使用帮助文档URL |
### 成功响应的 output 字段
### 错误响应 (4xx/5xx)
| 参数名 | 类型 | 说明 |
|--------|------|------|
| draft_id | string | 草稿唯一标识符 |
| draft_url | string | 草稿预览 URL |
```json
{
"detail": "错误信息描述"
}
```
---
## 使用示例
## 请求示例
### cURL 示例
### 示例 1: 创建默认竖屏草稿(1080x1920
#### 1. 创建默认分辨率草稿
```bash
curl -X POST http://localhost:9001/create_draft \
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/create_draft \
-H "Content-Type: application/json" \
-d '{}'
```
**请求体 (JSON):**
```json
{}
```
### 示例 2: 创建横屏草稿(1920x1080
#### 2. 创建自定义分辨率草稿
```bash
curl -X POST http://localhost:9001/create_draft \
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/create_draft \
-H "Content-Type: application/json" \
-d '{
"width": 1920,
"height": 1080
"width": 1280,
"height": 720
}'
```
**请求体 (JSON):**
```json
{
"width": 1920,
"height": 1080
}
```
### 示例 3: 创建方形草稿(1080x1080
#### 3. 创建竖屏短视频草稿
```bash
curl -X POST http://localhost:9001/create_draft \
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/create_draft \
-H "Content-Type: application/json" \
-d '{
"width": 1080,
"height": 1080
"height": 1920
}'
```
**请求体 (JSON):**
### JavaScript 示例
```json
{
"width": 1080,
"height": 1080
}
```javascript
const createDraft = async (width = 1920, height = 1080) => {
const response = await fetch('/openapi/capcut-mate/v1/create_draft', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ width, height })
});
return response.json();
};
// 创建默认分辨率草稿
const defaultDraft = await createDraft();
// 创建720P草稿
const hdDraft = await createDraft(1280, 720);
// 创建正方形草稿
const squareDraft = await createDraft(1080, 1080);
console.log('草稿创建成功:', {
default: defaultDraft.draft_url,
hd: hdDraft.draft_url,
square: squareDraft.draft_url
});
```
### 示例 4: Python 请求示例
### 高级JavaScript示例
```javascript
class DraftManager {
constructor(baseUrl = 'https://capcut-mate.jcaigc.cn') {
this.baseUrl = baseUrl;
}
async createDraft(config = {}) {
const { width = 1920, height = 1080 } = config;
const response = await fetch(`${this.baseUrl}/openapi/capcut-mate/v1/create_draft`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ width, height })
});
if (!response.ok) {
throw new Error(`创建草稿失败: ${response.statusText}`);
}
return response.json();
}
// 预设分辨率创建方法
async create1080p() {
return this.createDraft({ width: 1920, height: 1080 });
}
async create720p() {
return this.createDraft({ width: 1280, height: 720 });
}
async create4K() {
return this.createDraft({ width: 3840, height: 2160 });
}
async createVertical() {
return this.createDraft({ width: 1080, height: 1920 });
}
async createSquare() {
return this.createDraft({ width: 1080, height: 1080 });
}
// 批量创建多种规格草稿
async createMultipleFormats() {
const formats = [
{ name: '1080P', width: 1920, height: 1080 },
{ name: '720P', width: 1280, height: 720 },
{ name: '竖屏', width: 1080, height: 1920 },
{ name: '正方形', width: 1080, height: 1080 }
];
const results = {};
for (const format of formats) {
try {
const draft = await this.createDraft({
width: format.width,
height: format.height
});
results[format.name] = draft;
// 添加延迟避免请求过快
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
console.error(`创建${format.name}草稿失败:`, error);
results[format.name] = { error: error.message };
}
}
return results;
}
}
// 使用示例
const draftManager = new DraftManager();
// 创建单个草稿
const draft = await draftManager.create1080p();
console.log('草稿URL:', draft.draft_url);
// 批量创建多种格式
const multipleDrafts = await draftManager.createMultipleFormats();
console.log('多种格式草稿:', multipleDrafts);
```
### Python 示例
```python
import requests
from typing import Optional, Dict
url = "http://localhost:9001/create_draft"
headers = {
"Content-Type": "application/json"
}
data = {
"width": 1920,
"height": 1080
class DraftCreator:
def __init__(self, base_url: str = "https://api.assets.jcaigc.cn"):
self.base_url = base_url
def create_draft(self, width: int = 1920, height: int = 1080) -> Dict:
"""创建草稿"""
response = requests.post(
f'{self.base_url}/openapi/capcut-mate/v1/create_draft',
headers={'Content-Type': 'application/json'},
json={
"width": width,
"height": height
}
)
response.raise_for_status()
return response.json()
# 预设分辨率方法
def create_1080p(self) -> Dict:
return self.create_draft(1920, 1080)
def create_720p(self) -> Dict:
return self.create_draft(1280, 720)
def create_4k(self) -> Dict:
return self.create_draft(3840, 2160)
def create_vertical(self) -> Dict:
return self.create_draft(1080, 1920)
def create_square(self) -> Dict:
return self.create_draft(1080, 1080)
# 使用示例
creator = DraftCreator()
# 创建不同分辨率的草稿
drafts = {
"1080p": creator.create_1080p(),
"720p": creator.create_720p(),
"vertical": creator.create_vertical(),
"square": creator.create_square()
}
response = requests.post(url, json=data, headers=headers)
result = response.json()
print(f"Success: {result['success']}")
if result['success']:
print(f"Draft ID: {result['output']['draft_id']}")
print(f"Draft URL: {result['output']['draft_url']}")
else:
print(f"Error: {result['error']}")
for name, draft in drafts.items():
print(f"{name} 草稿URL: {draft['draft_url']}")
```
---
## 错误码说明
## 响应示例
### 成功响应
**状态码:** 200 OK
```json
{
"success": true,
"output": {
"draft_id": "dfd_1234567890abcdef",
"draft_url": "http://example.com/preview?draft_id=dfd_1234567890abcdef"
},
"error": ""
}
```
### 失败响应
**状态码:** 200 OK
```json
{
"success": false,
"output": "",
"error": "Error occurred while creating draft: Invalid dimensions."
}
```
---
## 常见画布尺寸
| 类型 | 宽度 | 高度 | 说明 |
|------|------|------|------|
| 竖屏 | 1080 | 1920 | 默认,适合抖音、快手等短视频平台 |
| 横屏 | 1920 | 1080 | 适合 YouTube、B站横屏视频 |
| 方形 | 1080 | 1080 | 适合 Instagram 等社交平台 |
| 4K竖屏 | 2160 | 3840 | 高清竖屏视频 |
| 4K横屏 | 3840 | 2160 | 高清横屏视频 |
---
## 使用场景
### 场景 1: 创建抖音短视频草稿
```json
{
"width": 1080,
"height": 1920
}
```
### 场景 2: 创建 YouTube 视频草稿
```json
{
"width": 1920,
"height": 1080
}
```
### 场景 3: 创建 Instagram 方形视频
```json
{
"width": 1080,
"height": 1080
}
```
---
| 错误码 | 错误信息 | 说明 | 解决方案 |
|--------|----------|------|----------|
| 400 | width必须大于等于1 | 宽度参数无效 | 提供大于等于1的宽度值 |
| 400 | height必须大于等于1 | 高度参数无效 | 提供大于等于1的高度值 |
| 400 | 参数类型错误 | 参数类型不正确 | 确保width和height为数字类型 |
| 500 | 草稿创建失败 | 内部服务错误 | 联系技术支持 |
| 503 | 服务不可用 | 系统维护中 | 稍后重试 |
## 注意事项
1. **默认值**: 如果不提供任何参数,将创建 1080x1920 的竖屏草稿
2. **分辨率**: 建议使用常见的视频分辨率,避免过大或过小的尺寸
3. **草稿 ID**: 返回的 draft_id 需要保存,后续所有操作都需要使用它
4. **预览 URL**: draft_url 可用于在浏览器中预览草稿内容
---
1. **参数验证**: width和height必须为正整数
2. **分辨率建议**: 建议使用常见的视频分辨率以确保兼容性
3. **性能考虑**: 超高分辨率可能影响后续处理性能
4. **存储占用**: 高分辨率草稿会占用更多存储空间
5. **URL有效期**: 返回的draft_url具有一定的有效期
## 工作流程
```
1. 调用 create_draft 创建草稿
2. 保存返回的 draft_id
3. 使用 draft_id 添加视频、音频、文字等素材
4. 调用 save_draft 保存草稿
5. 导入剪映或在线预览
```
1. 接收并验证请求参数
2. 创建草稿基础结构
3. 设置画布尺寸
4. 生成草稿URL
5. 返回草稿信息和帮助文档链接
---
## 下一步操作
创建草稿后,您可以使用以下接口继续编辑:
- **add_videos**: 添加视频素材
- **add_audios**: 添加音频素材
- **add_images**: 添加图片素材
- **save_draft**: 保存草稿
- **gen_video**: 导出视频
## 相关接口
- `POST /add_video` - 添加视频到草稿
- `POST /add_audio` - 添加音频到草稿
- `POST /add_text` - 添加文字到草稿
- `POST /add_image` - 添加图片到草稿
- `POST /save_draft` - 保存草稿
- `POST /query_script` - 查询草稿脚本
---
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2025-10-21 | 初始版本 |
---
## 技术支持
如有问题,请联系:
- Email: sguann2023@gmail.com
- GitHub Issues: https://github.com/sun-guannan/CapCutAPI/issues
- [添加视频](./add_videos.md)
- [添加音频](./add_audios.md)
- [添加图片](./add_images.md)
- [保存草稿](./save_draft.md)
- [生成视频](./gen_video.md)
+217
View File
@@ -0,0 +1,217 @@
# easy_create_material 接口文档
## 接口概述
**接口名称**easy_create_material
**接口地址**`POST /openapi/capcut-mate/v1/easy_create_material`
**功能描述**:在现有草稿中添加多种类型的素材内容,包括音频、视频、图片和文字。该接口可以一次性向草稿添加多种媒体素材,自动处理素材的时长、尺寸等属性,并智能管理不同类型的媒体轨道。是视频创作的核心接口之一。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### 请求体 (application/json)
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| draft_url | string | 是 | - | 目标草稿的完整URL |
| audio_url | string | 是 | - | 音频文件URL,不能为空或null |
| text | string | 否 | null | 要添加的文字内容 |
| img_url | string | 否 | null | 图片文件URL |
| video_url | string | 否 | null | 视频文件URL |
| text_color | string | 否 | "#ffffff" | 文字颜色(十六进制格式) |
| font_size | integer | 否 | 15 | 字体大小 |
| text_transform_y | integer | 否 | 0 | 文字Y轴位置偏移 |
### 素材类型说明
| 素材类型 | 支持格式 | 自动处理 | 时长设置 |
|----------|----------|----------|----------|
| 音频 | MP3, WAV, AAC | 自动获取时长 | 使用音频原始时长 |
| 视频 | MP4, AVI, MOV | 自动获取属性 | 固定时长5秒 |
| 图片 | JPEG, PNG, GIF | 自动获取尺寸 | 默认时长3秒 |
| 文字 | UTF-8文本 | 支持样式设置 | 默认时长5秒 |
## 请求示例
### 添加所有类型素材
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"audio_url": "https://assets.jcaigc.cn/audio.mp3",
"text": "Hello World",
"img_url": "https://s.coze.cn/t/JTa5Ne6_liY/",
"video_url": "https://assets.jcaigc.cn/video.mp4",
"text_color": "#ff0000",
"font_size": 20,
"text_transform_y": 100
}
```
### 仅添加音频和文字
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"audio_url": "https://assets.jcaigc.cn/background_music.mp3",
"text": "欢迎观看",
"text_color": "#0066ff",
"font_size": 18
}
```
### 最简请求(仅音频)
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"audio_url": "https://assets.jcaigc.cn/audio.wav"
}
```
## 响应格式
### 成功响应
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}
```
### 错误响应
#### 400 Bad Request - 参数验证失败
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "请求参数验证失败",
"details": "audio_url 不能为空"
}
}
```
#### 404 Not Found - 草稿不存在
```json
{
"error": {
"code": "DRAFT_NOT_FOUND",
"message": "草稿文件不存在",
"details": "无法找到指定的草稿文件"
}
}
```
#### 500 Internal Server Error - 素材创建失败
```json
{
"error": {
"code": "MATERIAL_CREATE_FAILED",
"message": "素材创建失败",
"details": "添加音频素材时发生错误"
}
}
```
## 错误码说明
| 错误码 | HTTP状态码 | 描述 | 解决方案 |
|--------|------------|------|----------|
| VALIDATION_ERROR | 400 | 请求参数验证失败 | 检查必填参数是否提供,参数格式是否正确 |
| DRAFT_NOT_FOUND | 404 | 草稿文件不存在 | 确认草稿URL是否正确,草稿是否已被删除 |
| MATERIAL_CREATE_FAILED | 500 | 素材创建失败 | 检查素材URL是否有效,网络连接是否正常 |
| INVALID_URL | 400 | URL格式无效 | 确认提供的URL格式正确且可访问 |
## 使用说明
### 参数说明
1. **draft_url**:必须是有效的剪映草稿URL,格式为 `https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258
2. **audio_url**:必填参数,必须提供有效的音频文件URL,不接受空字符串或null值
3. **可选素材**text、img_url、video_url 都是可选参数,可以根据需要选择添加
4. **文字样式**:text_color支持十六进制颜色代码,font_size范围建议10-50
5. **位置偏移**text_transform_y用于调整文字在画面中的垂直位置
### 素材处理规则
1. **音频处理**
- 自动解析音频时长
- 添加到音频轨道
- 支持多种音频格式
2. **视频处理**
- 固定显示时长5秒
- 保持原始分辨率比例
- 添加到视频轨道
3. **图片处理**
- 默认显示时长3秒
- 自动获取图片尺寸
- 添加到图片轨道
4. **文字处理**
- 默认显示时长5秒
- 支持颜色和字体大小设置
- 可调整垂直位置
### 注意事项
- 音频是必填参数,其他素材类型都是可选的
- 素材URL必须可公开访问,建议使用HTTPS协议
- 文字颜色使用标准十六进制格式(如 #ffffff#000000
- 所有时长都以微秒为单位进行内部计算
- 建议在添加素材前确保网络连接稳定
## 应用场景
1. **快速创建多媒体内容**:一次性添加背景音乐、视频片段、图片和标题文字
2. **批量素材导入**:为新创建的草稿快速添加多种类型的基础素材
3. **模板化创作**:基于固定的素材类型模板快速生成视频草稿
4. **自动化流程**:在自动化视频制作流程中批量添加预设的素材内容
## 相关接口
- [create_draft](./create_draft.md) - 创建新的草稿文件
- [add_audios](./add_audios.md) - 单独添加音频素材
- [add_videos](./add_videos.md) - 单独添加视频素材
- [add_images](./add_images.md) - 单独添加图片素材
- [save_draft](./save_draft.md) - 保存草稿文件
## 技术实现
### 文件结构
```
src/
├── schemas/easy_create_material.py # 请求/响应数据模型
├── service/easy_create_material.py # 业务逻辑实现
└── router/v1.py # API路由定义
```
### 核心逻辑
1. **参数验证**:验证草稿URL和音频URL的有效性
2. **草稿加载**:从URL解析并加载草稿文件
3. **素材添加**:按类型分别添加音频、视频、图片、文字素材
4. **轨道管理**:自动管理不同类型素材的轨道分配
5. **文件保存**:保存更新后的草稿文件
### 日志记录
系统会记录以下关键操作的日志:
- 草稿加载成功/失败
- 各类型素材添加的详细过程
- 文件保存结果
- 错误异常信息
---
**版本信息**v1.0
**最后更新**2025-09-24
+585
View File
@@ -0,0 +1,585 @@
# gen_video 接口文档
## 接口概述
**接口名称**gen_video
**接口地址**`POST /openapi/capcut-mate/v1/gen_video`
**功能描述**:提交视频生成任务。该接口采用异步处理模式,立即返回任务ID,视频生成在后台进行。支持任务排队,确保系统稳定性。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### 请求体 (application/json)
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| draft_url | string | 是 | - | 草稿URL,格式如:https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}
```
## 响应格式
### 成功响应
```json
{
"message": "视频生成任务已提交,请使用draft_url查询进度"
}
```
### 响应字段说明
| 字段名 | 类型 | 描述 |
|--------|------|------|
| message | string | 响应消息 |
### 错误响应
#### 400 Bad Request - 参数验证失败
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "请求参数验证失败",
"details": "draft_url 参数不能为空"
}
}
```
#### 404 Not Found - 草稿不存在
```json
{
"error": {
"code": "INVALID_DRAFT_URL",
"message": "无效的草稿URL",
"details": "无法解析草稿ID或草稿不存在"
}
}
```
#### 500 Internal Server Error - 任务提交失败
```json
{
"error": {
"code": "VIDEO_GENERATION_SUBMIT_FAILED",
"message": "视频生成任务提交失败",
"details": "系统内部错误"
}
}
```
## 使用示例
### cURL 示例
#### 1. 基本视频生成
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/gen_video \
-H "Content-Type: application/json" \
-d '{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}'
```
#### 2. 带超时设置的请求
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/gen_video \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL"
}' \
--max-time 300
```
### JavaScript 示例
```javascript
const generateVideo = async (draftUrl) => {
const response = await fetch('/openapi/capcut-mate/v1/gen_video', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ draft_url: draftUrl })
});
return response.json();
};
// 基本使用
const draftUrl = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258";
const result = await generateVideo(draftUrl);
if (result.video_url) {
console.log('视频生成成功:', result.video_url);
// 创建下载链接
const downloadLink = document.createElement('a');
downloadLink.href = result.video_url;
downloadLink.download = 'generated_video.mp4';
downloadLink.click();
} else {
console.error('视频生成失败:', result.message);
}
```
### 高级JavaScript示例
```javascript
class VideoGenerator {
constructor(baseUrl = 'https://capcut-mate.jcaigc.cn') {
this.baseUrl = baseUrl;
}
async generateVideo(draftUrl, options = {}) {
const {
timeout = 300000, // 5分钟超时
onProgress = null
} = options;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(`${this.baseUrl}/openapi/capcut-mate/v1/gen_video`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ draft_url: draftUrl }),
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`视频生成失败: ${response.statusText}`);
}
return response.json();
} catch (error) {
clearTimeout(timeoutId);
if (error.name === 'AbortError') {
throw new Error('视频生成超时');
}
throw error;
}
}
// 轮询式视频生成(适用于长时间处理)
async generateVideoWithPolling(draftUrl, options = {}) {
const {
pollInterval = 5000, // 5秒轮询间隔
maxAttempts = 60, // 最大尝试次数(5分钟)
onProgress = null
} = options;
// 启动生成请求
let attempt = 0;
while (attempt < maxAttempts) {
try {
const result = await this.generateVideo(draftUrl, { timeout: 30000 });
if (result.video_url) {
if (onProgress) onProgress({ status: 'completed', result });
return result;
}
if (onProgress) {
onProgress({
status: 'processing',
attempt: attempt + 1,
maxAttempts,
message: result.message
});
}
// 等待下次轮询
await new Promise(resolve => setTimeout(resolve, pollInterval));
attempt++;
} catch (error) {
if (error.message.includes('超时')) {
// 超时不算失败,继续轮询
if (onProgress) {
onProgress({
status: 'processing',
attempt: attempt + 1,
maxAttempts,
message: '处理中...'
});
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
attempt++;
} else {
throw error;
}
}
}
throw new Error('视频生成超时,请稍后重试');
}
// 批量生成视频
async generateBatchVideos(draftUrls, options = {}) {
const {
concurrent = 2, // 并发数量
onProgress = null
} = options;
const results = {};
const entries = Object.entries(draftUrls);
// 分批处理
for (let i = 0; i < entries.length; i += concurrent) {
const batch = entries.slice(i, i + concurrent);
const batchPromises = batch.map(async ([name, url]) => {
try {
if (onProgress) {
onProgress({ name, status: 'starting', url });
}
const result = await this.generateVideoWithPolling(url, {
onProgress: (progress) => {
if (onProgress) {
onProgress({ name, ...progress, url });
}
}
});
results[name] = result;
if (onProgress) {
onProgress({ name, status: 'completed', result, url });
}
} catch (error) {
console.error(`生成视频失败 ${name}:`, error);
results[name] = { error: error.message };
if (onProgress) {
onProgress({ name, status: 'failed', error: error.message, url });
}
}
});
await Promise.all(batchPromises);
// 批次间添加延迟
if (i + concurrent < entries.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return results;
}
// 下载生成的视频
async downloadVideo(videoUrl, filename = 'generated_video.mp4') {
try {
const response = await fetch(videoUrl);
const blob = await response.blob();
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(downloadUrl);
return true;
} catch (error) {
console.error('下载视频失败:', error);
return false;
}
}
}
// 使用示例
const videoGenerator = new VideoGenerator();
// 单个视频生成
const draftUrl = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258";
try {
const result = await videoGenerator.generateVideoWithPolling(draftUrl, {
onProgress: (progress) => {
console.log(`生成进度: ${progress.status}`, progress);
if (progress.status === 'processing') {
console.log(`正在处理... (${progress.attempt}/${progress.maxAttempts})`);
}
}
});
console.log('视频生成成功:', result.video_url);
// 下载视频
await videoGenerator.downloadVideo(result.video_url, 'my_video.mp4');
} catch (error) {
console.error('生成失败:', error);
}
// 批量生成视频
const multipleDrafts = {
"video1": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"video2": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"video3": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
};
const batchResults = await videoGenerator.generateBatchVideos(multipleDrafts, {
concurrent: 2,
onProgress: (progress) => {
console.log(`${progress.name}: ${progress.status}`);
}
});
console.log('批量生成结果:', batchResults);
// 下载所有成功的视频
for (const [name, result] of Object.entries(batchResults)) {
if (result.video_url && !result.error) {
await videoGenerator.downloadVideo(result.video_url, `${name}.mp4`);
}
}
```
### Python 示例
```python
import requests
import time
import asyncio
import aiohttp
from typing import Dict, Optional, Callable
class VideoGenerator:
def __init__(self, base_url: str = "https://api.assets.jcaigc.cn"):
self.base_url = base_url
def generate_video(self, draft_url: str, timeout: int = 300) -> Dict:
"""生成视频"""
response = requests.post(
f'{self.base_url}/openapi/capcut-mate/v1/gen_video',
headers={'Content-Type': 'application/json'},
json={"draft_url": draft_url},
timeout=timeout
)
response.raise_for_status()
return response.json()
def generate_video_with_polling(self, draft_url: str,
poll_interval: int = 5,
max_attempts: int = 60,
on_progress: Optional[Callable] = None) -> Dict:
"""轮询式视频生成"""
attempt = 0
while attempt < max_attempts:
try:
result = self.generate_video(draft_url, timeout=30)
if result.get('video_url'):
if on_progress:
on_progress({'status': 'completed', 'result': result})
return result
if on_progress:
on_progress({
'status': 'processing',
'attempt': attempt + 1,
'max_attempts': max_attempts,
'message': result.get('message', '处理中...')
})
time.sleep(poll_interval)
attempt += 1
except requests.exceptions.Timeout:
if on_progress:
on_progress({
'status': 'processing',
'attempt': attempt + 1,
'max_attempts': max_attempts,
'message': '处理中...'
})
time.sleep(poll_interval)
attempt += 1
except Exception as e:
raise e
raise Exception('视频生成超时,请稍后重试')
def generate_batch_videos(self, draft_urls: Dict[str, str],
concurrent: int = 2,
on_progress: Optional[Callable] = None) -> Dict:
"""批量生成视频"""
results = {}
entries = list(draft_urls.items())
# 分批处理
for i in range(0, len(entries), concurrent):
batch = entries[i:i + concurrent]
batch_results = {}
for name, url in batch:
try:
if on_progress:
on_progress({'name': name, 'status': 'starting', 'url': url})
def progress_callback(progress):
if on_progress:
on_progress({'name': name, **progress, 'url': url})
result = self.generate_video_with_polling(
url,
on_progress=progress_callback
)
batch_results[name] = result
if on_progress:
on_progress({'name': name, 'status': 'completed', 'result': result, 'url': url})
except Exception as e:
print(f"生成视频失败 {name}: {e}")
batch_results[name] = {'error': str(e)}
if on_progress:
on_progress({'name': name, 'status': 'failed', 'error': str(e), 'url': url})
results.update(batch_results)
# 批次间延迟
if i + concurrent < len(entries):
time.sleep(1)
return results
def download_video(self, video_url: str, filename: str = "generated_video.mp4") -> bool:
"""下载视频"""
try:
response = requests.get(video_url, stream=True)
response.raise_for_status()
with open(filename, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
print(f"视频已下载到: {filename}")
return True
except Exception as e:
print(f"下载视频失败: {e}")
return False
# 使用示例
generator = VideoGenerator()
# 单个视频生成
draft_url = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
def on_progress(progress):
print(f"生成进度: {progress['status']}")
if progress['status'] == 'processing':
print(f"正在处理... ({progress['attempt']}/{progress['max_attempts']})")
try:
result = generator.generate_video_with_polling(
draft_url,
on_progress=on_progress
)
print(f"视频生成成功: {result['video_url']}")
# 下载视频
generator.download_video(result['video_url'], 'my_video.mp4')
except Exception as e:
print(f"生成失败: {e}")
# 批量生成
multiple_drafts = {
"video1": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"video2": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}
def batch_progress(progress):
print(f"{progress['name']}: {progress['status']}")
batch_results = generator.generate_batch_videos(
multiple_drafts,
concurrent=2,
on_progress=batch_progress
)
# 下载所有成功的视频
for name, result in batch_results.items():
if 'video_url' in result and 'error' not in result:
generator.download_video(result['video_url'], f'{name}.mp4')
```
## 错误码说明
| 错误码 | 错误信息 | 说明 | 解决方案 |
|--------|----------|------|----------|
| 400 | draft_url是必填项 | 缺少草稿URL参数 | 提供有效的draft_url |
| 400 | draft_url格式无效 | URL格式不正确 | 检查URL格式是否正确 |
| 404 | 草稿不存在 | 指定的草稿无法找到 | 确认草稿URL是否正确且存在 |
| 400 | 草稿内容为空 | 草稿中没有可导出的内容 | 确保草稿包含视频、音频或图片素材 |
| 400 | 素材无法访问 | 草稿中的素材文件无法下载 | 检查素材URL是否有效 |
| 500 | 视频渲染失败 | 视频处理过程中出错 | 检查草稿内容或联系技术支持 |
| 500 | 音频处理失败 | 音频混合过程中出错 | 检查音频格式或联系技术支持 |
| 500 | 编码失败 | 最终视频编码失败 | 联系技术支持 |
| 503 | 服务繁忙 | 渲染服务器负载过高 | 稍后重试 |
| 504 | 处理超时 | 视频生成超时 | 简化草稿内容或稍后重试 |
## 注意事项
1. **处理时间**: 视频生成是耗时操作,可能需要几分钟到几十分钟
2. **文件大小**: 草稿复杂度和素材数量会影响处理时间
3. **网络稳定**: 确保素材URL可以稳定访问
4. **超时设置**: 建议设置较长的超时时间或使用轮询机制
5. **并发限制**: 避免同时生成大量视频
6. **存储空间**: 生成的视频文件可能很大,注意存储空间
7. **URL有效期**: 生成的video_url可能有时效性限制
## 工作流程
1. 验证draft_url参数
2. 解析草稿配置文件
3. 下载所有必需的素材文件
4. 按时间轴排列和处理素材
5. 应用视觉效果和转场
6. 混合音频轨道
7. 渲染最终视频
8. 编码并上传视频文件
9. 返回视频URL
## 最佳实践
1. **轮询检查**: 对于长时间处理,使用轮询机制
2. **错误重试**: 实现自动重试机制
3. **进度反馈**: 向用户显示处理进度
4. **批量处理**: 合理控制并发数量
5. **资源清理**: 及时清理临时文件
6. **质量控制**: 生成前验证草稿内容的完整性
## 相关接口
- [创建草稿](./create_draft.md)
- [保存草稿](./save_draft.md)
- [添加视频](./add_videos.md)
- [添加音频](./add_audios.md)
- [添加图片](./add_images.md)
- [获取草稿](./get_draft.md)
+353
View File
@@ -0,0 +1,353 @@
# gen_video_status 接口文档
## 接口概述
**接口名称**gen_video_status
**接口地址**`POST /openapi/capcut-mate/v1/gen_video_status`
**功能描述**:查询视频生成任务的状态和进度。配合 gen_video 接口使用,用于实时跟踪视频生成任务的执行情况,包括任务状态、进度百分比、完成结果等信息。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### 请求体 (application/json)
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| draft_url | string | 是 | - | 草稿URL,与提交任务时使用的URL相同 |
## 请求示例
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}
```
## 响应格式
### 成功响应
#### 任务等待中
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"status": "pending",
"progress": 0,
"video_url": "",
"error_message": "",
"created_at": "2024-09-24T10:30:00.000Z",
"started_at": null,
"completed_at": null
}
```
#### 任务处理中
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"status": "processing",
"progress": 65,
"video_url": "",
"error_message": "",
"created_at": "2024-09-24T10:30:00.000Z",
"started_at": "2024-09-24T10:30:05.000Z",
"completed_at": null
}
```
#### 任务已完成
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"status": "completed",
"progress": 100,
"video_url": "https://video-output.assets.jcaigc.cn/generated/video_abc123def456ghi789.mp4",
"error_message": "",
"created_at": "2024-09-24T10:30:00.000Z",
"started_at": "2024-09-24T10:30:05.000Z",
"completed_at": "2024-09-24T10:35:30.000Z"
}
```
#### 任务失败
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"status": "failed",
"progress": 0,
"video_url": "",
"error_message": "导出草稿失败: 剪映导出结束但目标文件未生成,请检查磁盘空间或剪映版本",
"created_at": "2024-09-24T10:30:00.000Z",
"started_at": "2024-09-24T10:30:05.000Z",
"completed_at": "2024-09-24T10:32:15.000Z"
}
```
### 响应字段说明
| 字段名 | 类型 | 描述 |
|--------|------|------|
| draft_url | string | 草稿URL |
| status | string | 任务状态:pending/processing/completed/failed |
| progress | integer | 任务进度(0-100 |
| video_url | string | 生成的视频URL(仅在completed状态时有值) |
| error_message | string | 错误信息(仅在failed状态时有值) |
| created_at | string | 任务创建时间(ISO格式) |
| started_at | string\|null | 任务开始时间(ISO格式) |
| completed_at | string\|null | 任务完成时间(ISO格式) |
### 任务状态说明
| 状态值 | 状态名称 | 描述 | 进度范围 |
|--------|----------|------|----------|
| pending | 等待中 | 任务已提交,等待处理 | 0 |
| processing | 处理中 | 任务正在执行中 | 10-90 |
| completed | 已完成 | 任务成功完成 | 100 |
| failed | 失败 | 任务执行失败 | 0 |
### 进度说明
进度百分比对应的处理阶段:
| 进度范围 | 处理阶段 | 说明 |
|----------|----------|------|
| 0% | 等待中 | 任务在队列中等待 |
| 10% | 开始处理 | 任务开始执行 |
| 20% | 草稿解析 | 解析草稿配置 |
| 30% | 准备环境 | 初始化剪映环境 |
| 50% | 素材处理 | 处理素材和效果 |
| 70% | 导出控制 | 控制剪映导出 |
| 90% | 文件生成 | 生成视频文件 |
| 100% | 完成 | 任务完成 |
### 错误响应
#### 404 Not Found - 任务不存在
```json
{
"error": {
"code": "VIDEO_TASK_NOT_FOUND",
"message": "视频生成任务未找到",
"details": "指定的草稿URL没有对应的视频生成任务"
}
}
```
#### 500 Internal Server Error - 查询失败
```json
{
"error": {
"code": "VIDEO_STATUS_QUERY_FAILED",
"message": "视频任务状态查询失败",
"details": "系统内部错误"
}
}
```
## 错误码说明
| 错误码 | HTTP状态码 | 描述 | 解决方案 |
|--------|------------|------|----------|
| VALIDATION_ERROR | 400 | 请求参数验证失败 | 检查draft_url参数格式是否正确 |
| VIDEO_TASK_NOT_FOUND | 404 | 视频生成任务未找到 | 确认是否已通过gen_video接口提交任务 |
| VIDEO_STATUS_QUERY_FAILED | 500 | 状态查询失败 | 稍后重试或联系技术支持 |
## 使用说明
### 轮询查询
建议使用轮询方式查询任务状态:
1. **轮询间隔**:建议每5-10秒查询一次
2. **超时设置**:建议设置总超时时间(如10分钟)
3. **错误处理**:处理网络错误和任务失败情况
### 最佳实践
1. **及时查询**:任务提交后立即开始查询
2. **进度显示**:利用progress字段显示进度条
3. **状态处理**:根据不同状态提供不同的用户反馈
4. **错误处理**:妥善处理任务失败情况
## 示例代码
### JavaScript 轮询示例
```javascript
async function pollVideoStatus(draftUrl, maxAttempts = 120) {
let attempts = 0;
const pollInterval = 5000; // 5秒间隔
while (attempts < maxAttempts) {
try {
const response = await fetch('/openapi/capcut-mate/v1/gen_video_status', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ draft_url: draftUrl })
});
const status = await response.json();
console.log(`任务状态: ${status.status}, 进度: ${status.progress}%`);
if (status.status === 'completed') {
console.log('视频生成完成:', status.video_url);
return status;
}
if (status.status === 'failed') {
throw new Error(`任务失败: ${status.error_message}`);
}
// 等待后继续轮询
await new Promise(resolve => setTimeout(resolve, pollInterval));
attempts++;
} catch (error) {
console.error('查询状态失败:', error);
attempts++;
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
}
throw new Error('任务超时');
}
// 使用示例
const draftUrl = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258";
try {
const result = await pollVideoStatus(draftUrl);
console.log('视频生成成功:', result.video_url);
} catch (error) {
console.error('视频生成失败:', error);
}
```
### Python 轮询示例
```python
import requests
import time
import json
def poll_video_status(draft_url, max_attempts=120, poll_interval=5):
"""轮询查询视频生成状态"""
url = 'http://localhost:8000/v1/gen_video_status'
for attempt in range(max_attempts):
try:
response = requests.post(url, json={'draft_url': draft_url})
if response.status_code == 200:
status = response.json()
print(f"任务状态: {status['status']}, 进度: {status['progress']}%")
if status['status'] == 'completed':
print(f"视频生成完成: {status['video_url']}")
return status
if status['status'] == 'failed':
raise Exception(f"任务失败: {status['error_message']}")
else:
print(f"查询失败: {response.status_code}")
except requests.RequestException as e:
print(f"网络错误: {e}")
# 等待后继续轮询
time.sleep(poll_interval)
raise Exception("任务超时")
# 使用示例
if __name__ == "__main__":
draft_url = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
try:
result = poll_video_status(draft_url)
print(f"视频生成成功: {result['video_url']}")
except Exception as e:
print(f"视频生成失败: {e}")
```
### 完整工作流程
```javascript
// 完整的视频生成工作流程
async function generateVideoWorkflow(draftUrl) {
try {
// 1. 提交视频生成任务
console.log('提交视频生成任务...');
const submitResponse = await fetch('/v1/gen_video', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ draft_url: draftUrl })
});
const submitResult = await submitResponse.json();
console.log(`任务已提交: ${submitResult.message}`);
// 2. 轮询查询任务状态
console.log('开始查询任务状态...');
const finalResult = await pollVideoStatus(draftUrl);
// 3. 处理完成结果
if (finalResult.video_url) {
console.log('视频生成成功!');
// 可以进行后续操作,如下载视频
const downloadLink = document.createElement('a');
downloadLink.href = finalResult.video_url;
downloadLink.download = 'generated_video.mp4';
downloadLink.click();
return finalResult.video_url;
}
} catch (error) {
console.error('视频生成工作流程失败:', error);
throw error;
}
}
```
## 相关接口
- [gen_video](./gen_video.md) - 提交视频生成任务
- [create_draft](./create_draft.md) - 创建新的草稿文件
- [save_draft](./save_draft.md) - 保存草稿文件
## 技术实现
### 文件结构
```
src/
├── schemas/gen_video_status.py # 请求/响应数据模型
├── service/gen_video.py # 业务逻辑实现
├── utils/video_task_manager.py # 任务队列管理
└── router/v1.py # API路由定义
```
### 核心逻辑
1. **参数验证**:验证草稿URL的有效性
2. **任务查询**:从任务管理器中查询任务状态
3. **状态转换**:将内部状态转换为API响应格式
4. **错误处理**:处理任务不存在和查询失败的情况
---
**版本信息**v1.0
**最后更新**2024-09-24
+301
View File
@@ -0,0 +1,301 @@
# get_audio_duration 接口文档
## 接口概述
**接口名称**get_audio_duration
**接口地址**`POST /openapi/capcut-mate/v1/get_audio_duration`
**功能描述**:获取音频文件的时长,支持各种常见的音频格式。使用FFprobe工具进行精确的音频分析,返回音频文件的准确时长,单位为微秒。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### 请求体 (application/json)
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| mp3_url | string | 是 | - | 音频文件URL,支持mp3等常见音频格式 |
### 参数说明
- **mp3_url**: 音频文件的完整URL地址
- 支持格式:mp3、wav、aac、flac等常见音频格式
- 需要确保URL可访问且文件完整
- 建议文件大小不超过100MB
## 请求示例
### 获取MP3文件时长
```json
{
"mp3_url": "https://assets.jcaigc.cn/audio/sample.mp3"
}
```
### 获取WAV文件时长
```json
{
"mp3_url": "https://assets.jcaigc.cn/audio/music.wav"
}
```
## 响应格式
### 成功响应
```json
{
"duration": 120000000
}
```
### 响应字段说明
| 字段名 | 类型 | 描述 |
|--------|------|------|
| duration | integer | 音频时长,单位:微秒。例如:120000000表示120秒(2分钟) |
### 时长单位转换
- **微秒到秒**duration ÷ 1,000,000
- **微秒到毫秒**duration ÷ 1,000
- **示例**
- 120000000微秒 = 120秒 = 2分钟
- 30000000微秒 = 30秒
- 5000000微秒 = 5秒
### 错误响应
#### 400 Bad Request - 参数验证失败
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "请求参数验证失败",
"details": "mp3_url 参数不能为空"
}
}
```
#### 500 Internal Server Error - 获取音频时长失败
```json
{
"error": {
"code": "AUDIO_DURATION_GET_FAILED",
"message": "获取音频时长失败",
"details": "下载音频文件失败或文件格式不支持"
}
}
```
## 错误码说明
| 错误码 | HTTP状态码 | 描述 | 解决方案 |
|--------|------------|------|----------|
| VALIDATION_ERROR | 400 | 请求参数验证失败 | 检查mp3_url参数是否正确提供 |
| AUDIO_DURATION_GET_FAILED | 500 | 获取音频时长失败 | 检查音频URL是否可访问,文件格式是否支持 |
## 使用说明
### 参数要求
1. **mp3_url参数**:必填参数,需要提供完整的音频文件URL
2. **文件格式**:虽然参数名为mp3_url,但实际支持多种音频格式
3. **文件大小**:建议控制在合理范围内,过大的文件可能导致处理超时
### 使用场景
1. **视频编辑预处理**
- 在添加音频到视频项目前,先获取音频时长
- 用于计算音频片段的合理切分
2. **音频素材管理**
- 批量获取音频库中文件的时长信息
- 用于音频素材的分类和筛选
3. **同步处理**
- 确保音频和视频的时长匹配
- 计算音频淡入淡出效果的时长
### 技术说明
- **时长计算**:使用FFprobe工具进行精确的音频分析
- **精度**:返回的时长为高精度的实际值,支持小数点后6位精度
- **性能**:接口会下载音频文件进行分析,处理时间取决于文件大小和网络速度
## 示例代码
### JavaScript示例
```javascript
// 获取音频时长
const getAudioDuration = async (audioUrl) => {
const response = await fetch('/openapi/capcut-mate/v1/get_audio_duration', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
mp3_url: audioUrl
})
});
const result = await response.json();
if (response.ok) {
const durationSeconds = result.duration / 1000000;
console.log(`音频时长: ${durationSeconds}`);
return result.duration;
} else {
console.error('获取音频时长失败:', result.error);
throw new Error(result.error.message);
}
};
// 使用示例
getAudioDuration('https://assets.jcaigc.cn/audio/sample.mp3')
.then(duration => {
console.log(`音频时长(微秒): ${duration}`);
console.log(`音频时长(秒): ${duration / 1000000}`);
})
.catch(error => {
console.error('错误:', error.message);
});
```
### Python示例
```python
import requests
def get_audio_duration(mp3_url):
"""获取音频文件时长"""
url = 'https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_audio_duration'
data = {
'mp3_url': mp3_url
}
response = requests.post(url, json=data)
if response.status_code == 200:
result = response.json()
duration_microseconds = result['duration']
duration_seconds = duration_microseconds / 1_000_000
return duration_microseconds, duration_seconds
else:
print(f"请求失败: {response.status_code}")
print(response.json())
return None
# 使用示例
audio_url = "https://assets.jcaigc.cn/audio/sample.mp3"
duration_info = get_audio_duration(audio_url)
if duration_info:
duration_microseconds, duration_seconds = duration_info
print(f"音频时长: {duration_seconds:.2f}秒 ({duration_microseconds}微秒)")
# 时长格式化
minutes = int(duration_seconds // 60)
seconds = int(duration_seconds % 60)
print(f"格式化时长: {minutes}{seconds}")
```
### 批量处理示例
```python
import requests
import json
from concurrent.futures import ThreadPoolExecutor
import time
def get_audio_duration_batch(audio_urls):
"""批量获取音频时长"""
def get_single_duration(url):
try:
response = requests.post(
'http://localhost:8000/v1/get_audio_duration',
json={'mp3_url': url},
timeout=30
)
if response.status_code == 200:
duration = response.json()['duration']
return {'url': url, 'duration': duration, 'success': True}
else:
return {'url': url, 'error': response.json(), 'success': False}
except Exception as e:
return {'url': url, 'error': str(e), 'success': False}
# 并发处理
with ThreadPoolExecutor(max_workers=5) as executor:
results = list(executor.map(get_single_duration, audio_urls))
return results
# 使用示例
audio_urls = [
"https://assets.jcaigc.cn/audio1.mp3",
"https://assets.jcaigc.cn/audio2.wav",
"https://assets.jcaigc.cn/audio3.aac"
]
results = get_audio_duration_batch(audio_urls)
for result in results:
if result['success']:
duration_seconds = result['duration'] / 1_000_000
print(f"{result['url']}: {duration_seconds:.2f}")
else:
print(f"{result['url']}: {result['error']}")
```
## 相关接口
- [add_audios](./add_audios.md) - 批量添加音频到剪映草稿
- [add_videos](./add_videos.md) - 批量添加视频到剪映草稿
- [easy_create_material](./easy_create_material.md) - 快速创建多媒体素材
## 技术实现
### 文件结构
```
src/
├── schemas/get_audio_duration.py # 请求/响应数据模型
├── service/get_audio_duration.py # 业务逻辑实现
└── router/v1.py # API路由定义
```
### 核心逻辑
1. **参数验证**:验证mp3_url参数的有效性
2. **文件下载**:从URL下载音频文件到临时目录
3. **FFprobe分析**:使用FFprobe工具获取精确的音频元数据
4. **时长提取**:从格式信息或流信息中提取时长数据
5. **资源清理**:清理临时下载的文件
6. **响应返回**:返回符合规范的API响应
### 当前实现特点
- 使用FFmpeg项目的FFprobe工具进行音频分析
- 支持多种音频格式(MP3、WAV、AAC、FLAC等)
- 提供高精度的时长数据(微秒级别)
- 完善的错误处理和资源清理机制
- 支持超时控制,防止长时间阻塞
### 优势说明
相比于之前基于文件大小的估算方法,新的FFprobe实现提供了:
- **更高的精度**:直接从音频元数据中读取时长
- **更广泛的支持**:支持所有FFprobe可识别的音频格式
- **更可靠的结果**:不依赖于比特率估算,直接读取实际数据
---
**版本信息**v1.0
**最后更新**2024-09-24
+574
View File
@@ -0,0 +1,574 @@
# GET_DRAFT API 接口文档
## 接口信息
```
GET /openapi/capcut-mate/v1/get_draft
```
## 功能描述
获取草稿文件列表。该接口用于获取指定草稿ID对应的所有文件列表,可以查看草稿中包含的素材文件、配置文件等信息。通常用于草稿内容的预览、文件管理或状态检查。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### Query参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| draft_id | string | ✅ | - | 草稿ID,长度为20-32位字符 |
### 参数详解
#### draft_id
- **类型**: 字符串
- **必填**: 是
- **长度**: 20-32位字符
- **格式**: 通常为UUID格式或类似的唯一标识符
- **示例**: `2f52a63b-8c6a-4417-8b01-1b2a569ccb6c`
- **获取方式**: 通常从draft_url中提取或由create_draft接口返回
#### draft_id提取方法
从draft_url中提取draft_id
```javascript
// 示例draft_url:
// https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"2f52a63b-8c6a-4417-8b01-1b2a569ccb6c"
```
## 响应格式
### 成功响应 (200)
```json
{
"files": [
"2f52a63b-8c6a-4417-8b01-1b2a569ccb6c.json",
"video_123456789.mp4",
"audio_987654321.mp3",
"image_555666777.jpg",
"thumbnail_888999000.png"
]
}
```
### 响应字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| files | array | 草稿相关的文件列表 |
### 文件类型说明
返回的文件列表可能包含以下类型:
| 文件类型 | 扩展名 | 说明 |
|----------|--------|------|
| 草稿配置文件 | .json | 草稿的主要配置文件,包含所有编辑信息 |
| 视频文件 | .mp4, .avi, .mov | 草稿中使用的视频素材 |
| 音频文件 | .mp3, .wav, .aac | 草稿中使用的音频素材 |
| 图片文件 | .jpg, .png, .gif | 草稿中使用的图片素材 |
| 缩略图文件 | .png, .jpg | 素材的缩略图文件 |
| 临时文件 | .tmp | 处理过程中的临时文件 |
### 错误响应 (4xx/5xx)
```json
{
"detail": "错误信息描述"
}
```
## 使用示例
### cURL 示例
#### 1. 基本获取草稿文件列表
```bash
curl -X GET "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2f52a63b-8c6a-4417-8b01-1b2a569ccb6c" \
-H "Content-Type: application/json"
```
#### 2. 使用完整的draft_id
```bash
curl -X GET "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=7e8f9a0b-1c2d-3e4f-5g6h-7i8j9k0l1m2n" \
-H "Content-Type: application/json"
```
### JavaScript 示例
```javascript
const getDraft = async (draftId) => {
const response = await fetch(`/v1/get_draft?draft_id=${draftId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
});
return response.json();
};
// 使用示例
const draftId = "2f52a63b-8c6a-4417-8b01-1b2a569ccb6c";
const result = await getDraft(draftId);
console.log('草稿文件列表:', result.files);
// 从draft_url提取draft_id
function extractDraftId(draftUrl) {
const match = draftUrl.match(/\/([^\/]+)\.json$/);
return match ? match[1] : null;
}
const draftUrl = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258";
const extractedId = extractDraftId(draftUrl);
if (extractedId) {
const files = await getDraft(extractedId);
console.log('文件列表:', files);
}
```
### 高级JavaScript示例
```javascript
class DraftManager {
constructor(baseUrl = 'https://capcut-mate.jcaigc.cn') {
this.baseUrl = baseUrl;
}
async getDraft(draftId) {
const response = await fetch(`${this.baseUrl}/v1/get_draft?draft_id=${draftId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
});
if (!response.ok) {
throw new Error(`获取草稿失败: ${response.statusText}`);
}
return response.json();
}
// 从draft_url提取draft_id
extractDraftId(draftUrl) {
try {
const url = new URL(draftUrl);
const draftIdParam = url.searchParams.get('drafId');
if (draftIdParam) {
const match = draftIdParam.match(/\/([^\/]+)\.json$/);
return match ? match[1] : null;
}
return null;
} catch (error) {
console.error('URL解析失败:', error);
return null;
}
}
// 分析文件类型
analyzeFiles(files) {
const analysis = {
total: files.length,
types: {
config: [],
video: [],
audio: [],
image: [],
thumbnail: [],
other: []
}
};
files.forEach(file => {
const ext = file.split('.').pop()?.toLowerCase();
switch (ext) {
case 'json':
analysis.types.config.push(file);
break;
case 'mp4':
case 'avi':
case 'mov':
case 'mkv':
analysis.types.video.push(file);
break;
case 'mp3':
case 'wav':
case 'aac':
case 'flac':
analysis.types.audio.push(file);
break;
case 'jpg':
case 'jpeg':
case 'png':
case 'gif':
case 'bmp':
if (file.includes('thumbnail')) {
analysis.types.thumbnail.push(file);
} else {
analysis.types.image.push(file);
}
break;
default:
analysis.types.other.push(file);
}
});
return analysis;
}
// 获取草稿详细信息
async getDraftDetails(draftUrl) {
const draftId = this.extractDraftId(draftUrl);
if (!draftId) {
throw new Error('无法从URL中提取草稿ID');
}
const result = await this.getDraft(draftId);
const analysis = this.analyzeFiles(result.files);
return {
draftId,
draftUrl,
files: result.files,
analysis
};
}
// 批量获取多个草稿信息
async getBatchDrafts(draftUrls) {
const results = {};
for (const [name, url] of Object.entries(draftUrls)) {
try {
const details = await this.getDraftDetails(url);
results[name] = details;
// 添加延迟避免请求过快
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
console.error(`获取草稿失败 ${name}:`, error);
results[name] = { error: error.message };
}
}
return results;
}
// 监控草稿文件变化
async monitorDraftChanges(draftId, callback, intervalMs = 5000) {
let lastFileList = [];
const checkChanges = async () => {
try {
const result = await this.getDraft(draftId);
const currentFiles = result.files.sort();
// 检查文件列表是否发生变化
if (JSON.stringify(currentFiles) !== JSON.stringify(lastFileList)) {
const changes = {
added: currentFiles.filter(f => !lastFileList.includes(f)),
removed: lastFileList.filter(f => !currentFiles.includes(f)),
current: currentFiles
};
callback(changes);
lastFileList = currentFiles;
}
} catch (error) {
console.error('监控草稿变化失败:', error);
}
};
// 初始检查
await checkChanges();
// 定期检查
const interval = setInterval(checkChanges, intervalMs);
// 返回停止监控的函数
return () => clearInterval(interval);
}
}
// 使用示例
const draftManager = new DraftManager();
// 获取单个草稿详情
const draftUrl = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258";
const details = await draftManager.getDraftDetails(draftUrl);
console.log('草稿详情:', {
id: details.draftId,
totalFiles: details.analysis.total,
videoCount: details.analysis.types.video.length,
audioCount: details.analysis.types.audio.length,
imageCount: details.analysis.types.image.length
});
// 批量获取草稿信息
const multipleDrafts = {
"project1": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"project2": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
};
const batchResults = await draftManager.getBatchDrafts(multipleDrafts);
console.log('批量草稿信息:', batchResults);
// 监控草稿文件变化
const draftId = "2f52a63b-8c6a-4417-8b01-1b2a569ccb6c";
const stopMonitoring = await draftManager.monitorDraftChanges(draftId, (changes) => {
console.log('草稿文件发生变化:', changes);
if (changes.added.length > 0) {
console.log('新增文件:', changes.added);
}
if (changes.removed.length > 0) {
console.log('删除文件:', changes.removed);
}
});
// 30秒后停止监控
setTimeout(() => {
stopMonitoring();
console.log('停止监控草稿变化');
}, 30000);
```
### Python 示例
```python
import requests
import re
import time
import threading
from urllib.parse import urlparse, parse_qs
from typing import Dict, List, Optional, Callable
class DraftManager:
def __init__(self, base_url: str = "https://api.assets.jcaigc.cn"):
self.base_url = base_url
def get_draft(self, draft_id: str) -> Dict:
"""获取草稿文件列表"""
response = requests.get(
f'{self.base_url}/openapi/capcut-mate/v1/get_draft',
params={'draft_id': draft_id},
headers={'Content-Type': 'application/json'}
)
response.raise_for_status()
return response.json()
def extract_draft_id(self, draft_url: str) -> Optional[str]:
"""从draft_url提取draft_id"""
try:
parsed_url = urlparse(draft_url)
query_params = parse_qs(parsed_url.fragment.split('?')[1] if '?' in parsed_url.fragment else '')
draft_id_param = query_params.get('drafId', [None])[0]
if draft_id_param:
match = re.search(r'/([^/]+)\.json$', draft_id_param)
return match.group(1) if match else None
return None
except Exception as e:
print(f"URL解析失败: {e}")
return None
def analyze_files(self, files: List[str]) -> Dict:
"""分析文件类型"""
analysis = {
'total': len(files),
'types': {
'config': [],
'video': [],
'audio': [],
'image': [],
'thumbnail': [],
'other': []
}
}
for file in files:
ext = file.split('.')[-1].lower() if '.' in file else ''
if ext == 'json':
analysis['types']['config'].append(file)
elif ext in ['mp4', 'avi', 'mov', 'mkv']:
analysis['types']['video'].append(file)
elif ext in ['mp3', 'wav', 'aac', 'flac']:
analysis['types']['audio'].append(file)
elif ext in ['jpg', 'jpeg', 'png', 'gif', 'bmp']:
if 'thumbnail' in file:
analysis['types']['thumbnail'].append(file)
else:
analysis['types']['image'].append(file)
else:
analysis['types']['other'].append(file)
return analysis
def get_draft_details(self, draft_url: str) -> Dict:
"""获取草稿详细信息"""
draft_id = self.extract_draft_id(draft_url)
if not draft_id:
raise ValueError('无法从URL中提取草稿ID')
result = self.get_draft(draft_id)
analysis = self.analyze_files(result['files'])
return {
'draft_id': draft_id,
'draft_url': draft_url,
'files': result['files'],
'analysis': analysis
}
def get_batch_drafts(self, draft_urls: Dict[str, str]) -> Dict:
"""批量获取草稿信息"""
results = {}
for name, url in draft_urls.items():
try:
details = self.get_draft_details(url)
results[name] = details
time.sleep(0.1) # 避免请求过快
except Exception as e:
print(f"获取草稿失败 {name}: {e}")
results[name] = {'error': str(e)}
return results
def monitor_draft_changes(self, draft_id: str, callback: Callable, interval_seconds: int = 5) -> str:
"""监控草稿文件变化"""
last_file_list = []
stop_event = threading.Event()
def check_changes():
nonlocal last_file_list
while not stop_event.is_set():
try:
result = self.get_draft(draft_id)
current_files = sorted(result['files'])
if current_files != last_file_list:
changes = {
'added': [f for f in current_files if f not in last_file_list],
'removed': [f for f in last_file_list if f not in current_files],
'current': current_files
}
callback(changes)
last_file_list = current_files
except Exception as e:
print(f"监控草稿变化失败: {e}")
stop_event.wait(interval_seconds)
# 初始检查
try:
result = self.get_draft(draft_id)
last_file_list = sorted(result['files'])
except Exception as e:
print(f"初始检查失败: {e}")
# 启动监控线程
thread = threading.Thread(target=check_changes, daemon=True)
thread.start()
# 返回停止函数
def stop_monitoring():
stop_event.set()
thread.join(timeout=1)
return stop_monitoring
# 使用示例
manager = DraftManager()
# 获取单个草稿
draft_url = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
details = manager.get_draft_details(draft_url)
print(f"草稿ID: {details['draft_id']}")
print(f"文件总数: {details['analysis']['total']}")
print(f"视频文件: {len(details['analysis']['types']['video'])}")
print(f"音频文件: {len(details['analysis']['types']['audio'])}")
print(f"图片文件: {len(details['analysis']['types']['image'])}")
# 批量获取草稿
multiple_drafts = {
"project1": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"project2": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}
batch_results = manager.get_batch_drafts(multiple_drafts)
for name, result in batch_results.items():
if 'error' not in result:
print(f"{name}: {result['analysis']['total']} 个文件")
# 监控草稿变化
def on_change(changes):
print(f"草稿文件发生变化:")
if changes['added']:
print(f"新增: {changes['added']}")
if changes['removed']:
print(f"删除: {changes['removed']}")
draft_id = "2f52a63b-8c6a-4417-8b01-1b2a569ccb6c"
stop_monitoring = manager.monitor_draft_changes(draft_id, on_change)
# 30秒后停止监控
time.sleep(30)
stop_monitoring()
print("停止监控")
```
## 错误码说明
| 错误码 | 错误信息 | 说明 | 解决方案 |
|--------|----------|------|----------|
| 400 | draft_id是必填项 | 缺少draft_id参数 | 提供有效的draft_id |
| 400 | draft_id长度无效 | draft_id长度不在20-32位范围内 | 检查draft_id格式是否正确 |
| 400 | draft_id格式无效 | draft_id格式不正确 | 确保使用正确的草稿ID格式 |
| 404 | 草稿不存在 | 指定的草稿ID无法找到 | 确认草稿ID是否正确且存在 |
| 500 | 获取文件列表失败 | 内部服务错误 | 联系技术支持或稍后重试 |
| 503 | 服务不可用 | 系统维护中 | 稍后重试 |
## 注意事项
1. **参数格式**: 确保draft_id格式正确且长度在20-32位之间
2. **ID提取**: 从draft_url正确提取draft_id
3. **文件类型**: 返回的文件列表包含多种类型的文件
4. **权限验证**: 确保有权限访问指定的草稿
5. **实时性**: 文件列表可能不是实时更新的,存在一定延迟
6. **文件状态**: 列表中的文件可能处于不同的处理状态
## 工作流程
1. 验证draft_id参数
2. 检查draft_id格式和长度
3. 查找指定的草稿
4. 获取草稿关联的所有文件
5. 返回文件列表
## 最佳实践
1. **ID验证**: 在调用前验证draft_id的有效性
2. **错误处理**: 妥善处理草稿不存在的情况
3. **文件分析**: 对返回的文件列表进行分类分析
4. **缓存策略**: 对于频繁查询的草稿,考虑适当缓存
5. **监控变化**: 对于需要实时更新的场景,实现变化监控
## 相关接口
- [创建草稿](./create_draft.md)
- [保存草稿](./save_draft.md)
- [添加视频](./add_videos.md)
- [添加音频](./add_audios.md)
- [添加图片](./add_images.md)
- [生成视频](./gen_video.md)
+272
View File
@@ -0,0 +1,272 @@
# get_image_animations 接口文档
## 接口概述
**接口名称**get_image_animations
**接口地址**`POST /openapi/capcut-mate/v1/get_image_animations`
**功能描述**:获取图片出入场动画列表,返回所有支持的且满足条件的图片出入场动画。支持根据动画类型(入场、出场、循环)和会员模式(所有、VIP、免费)进行筛选。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### 请求体 (application/json)
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| mode | integer | 否 | 0 | 动画模式:0=所有,1=VIP2=免费 |
| type | string | 是 | - | 动画类型:in=入场,out=出场,loop=循环 |
### 动画模式说明
| 模式值 | 模式名称 | 描述 |
|--------|----------|------|
| 0 | 所有 | 返回所有动画(包括VIP和免费) |
| 1 | VIP | 仅返回VIP动画 |
| 2 | 免费 | 仅返回免费动画 |
### 动画类型说明
| 类型值 | 类型名称 | 描述 |
|--------|----------|------|
| in | 入场动画 | 图片出现时的动画效果 |
| out | 出场动画 | 图片消失时的动画效果 |
| loop | 循环动画 | 图片持续播放的循环动画效果 |
## 请求示例
### 获取所有入场动画
```json
{
"mode": 0,
"type": "in"
}
```
### 获取VIP出场动画
```json
{
"mode": 1,
"type": "out"
}
```
### 获取免费循环动画
```json
{
"mode": 2,
"type": "loop"
}
```
## 响应格式
### 成功响应
```json
{
"effects": "[{\"resource_id\":\"7314291622525538843\",\"type\":\"in\",\"category_id\":\"ruchang\",\"category_name\":\"入场\",\"duration\":500000,\"id\":\"35395178\",\"name\":\"冰雪飘动\",\"request_id\":\"\",\"start\":0,\"icon_url\":\"https://lf5-hl-hw-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/459c196951cadbd024456a63db89481f\",\"material_type\":\"sticker\",\"panel\":\"\",\"path\":\"\",\"platform\":\"all\"},{\"resource_id\":\"7397306443147252233\",\"type\":\"in\",\"category_id\":\"ruchang\",\"category_name\":\"入场\",\"duration\":500000,\"id\":\"77035159\",\"name\":\"变色输入\",\"request_id\":\"\",\"start\":0,\"icon_url\":\"https://lf5-hl-hw-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c15f5c313f8170c558043abf300a0692\",\"material_type\":\"sticker\",\"panel\":\"\",\"path\":\"\",\"platform\":\"all\"}]"
}
```
### 动画对象结构
每个动画对象包含以下字段:
| 字段名 | 类型 | 描述 |
|--------|------|------|
| resource_id | string | 动画资源ID |
| type | string | 动画类型(in/out/loop |
| category_id | string | 动画分类ID |
| category_name | string | 动画分类名称 |
| duration | integer | 动画时长(微秒) |
| id | string | 动画唯一标识ID |
| name | string | 动画名称 |
| request_id | string | 请求ID(通常为空) |
| start | integer | 动画开始时间 |
| icon_url | string | 动画图标URL |
| material_type | string | 素材类型(通常为"sticker" |
| panel | string | 面板信息 |
| path | string | 路径信息 |
| platform | string | 支持平台(通常为"all" |
### 错误响应
#### 400 Bad Request - 参数验证失败
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "请求参数验证失败",
"details": "type 参数必须为 in、out 或 loop"
}
}
```
#### 500 Internal Server Error - 获取动画失败
```json
{
"error": {
"code": "IMAGE_ANIMATION_GET_FAILED",
"message": "获取图片动画失败",
"details": "动画数据获取失败"
}
}
```
## 错误码说明
| 错误码 | HTTP状态码 | 描述 | 解决方案 |
|--------|------------|------|----------|
| VALIDATION_ERROR | 400 | 请求参数验证失败 | 检查type参数是否为in/out/loopmode参数是否为0/1/2 |
| IMAGE_ANIMATION_GET_FAILED | 500 | 获取图片动画失败 | 检查服务状态,稍后重试 |
## 使用说明
### 参数说明
1. **type参数**:必填参数,只能选择 "in"、"out"、"loop" 中的一个
2. **mode参数**:可选参数,默认为0(所有动画)
3. **响应数据**effects字段是JSON字符串格式,需要解析后使用
### 动画应用场景
1. **入场动画(in**
- 适用于图片出现的场景
- 如淡入效果、缩放入场、滑动入场等
- 通常时长在0.5-1秒之间
2. **出场动画(out**
- 适用于图片消失的场景
- 如淡出效果、缩放消失、旋转出场等
- 通常时长在0.6-0.8秒之间
3. **循环动画(loop**
- 适用于需要持续吸引注意力的图片
- 如轻微摇摆、缩放呼吸效果等
- 通常时长在1-1.2秒之间,可无限循环
### 使用建议
- 根据视频内容风格选择合适的动画类型
- VIP动画通常效果更佳,但需要会员权限
- 建议先获取所有动画,再根据需要进行筛选
- 可以结合动画预览图(icon_url)让用户选择
- 图片动画相比文字动画应更加自然流畅
## 示例代码
### JavaScript示例
```javascript
// 获取所有入场动画
const getImageInAnimations = async () => {
const response = await fetch('/openapi/capcut-mate/v1/get_image_animations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
mode: 0,
type: 'in'
})
});
const result = await response.json();
const animations = JSON.parse(result.effects);
console.log('图片入场动画列表:', animations);
};
// 获取免费循环动画
const getFreeImageLoopAnimations = async () => {
const response = await fetch('/openapi/capcut-mate/v1/get_image_animations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
mode: 2,
type: 'loop'
})
});
const result = await response.json();
const animations = JSON.parse(result.effects);
console.log('免费图片循环动画列表:', animations);
};
```
### Python示例
```python
import requests
import json
def get_image_animations(mode=0, animation_type='in'):
"""获取图片动画列表"""
url = 'http://localhost:8000/v1/get_image_animations'
data = {
'mode': mode,
'type': animation_type
}
response = requests.post(url, json=data)
if response.status_code == 200:
result = response.json()
animations = json.loads(result['effects'])
return animations
else:
print(f"请求失败: {response.status_code}")
return []
# 使用示例
in_animations = get_image_animations(mode=0, animation_type='in')
print(f"获取到 {len(in_animations)} 个图片入场动画")
vip_out_animations = get_image_animations(mode=1, animation_type='out')
print(f"获取到 {len(vip_out_animations)} 个VIP图片出场动画")
```
## 相关接口
- [add_images](./add_images.md) - 批量添加图片(可使用动画效果)
- [add_effects](./add_effects.md) - 添加视频特效
- [get_text_animations](./get_text_animations.md) - 获取文字出入场动画
## 技术实现
### 文件结构
```
src/
├── schemas/get_image_animations.py # 请求/响应数据模型
├── service/get_image_animations.py # 业务逻辑实现
└── router/v1.py # API路由定义
```
### 核心逻辑
1. **参数验证**:验证type和mode参数的有效性
2. **数据筛选**:根据type和mode参数筛选图片动画数据
3. **数据格式化**:将动画数据转换为JSON字符串格式
4. **响应返回**:返回符合规范的API响应
### 数据来源
目前使用模拟数据,实际项目中应该:
- 从数据库获取图片动画数据
- 或从第三方API获取动画资源
- 支持动画资源的动态更新
- 区分图片动画和文字动画的不同特性
---
**版本信息**v1.0
**最后更新**2024-09-24
-280
View File
@@ -1,280 +0,0 @@
# get_mask_types 接口文档
## 接口概述
获取所有支持的蒙版类型列表,用于视频和图片的蒙版效果。
---
## 接口信息
### RESTful API 端点
```
GET /get_mask_types
```
### Content-Type
```
application/json
```
---
## 请求参数
### 无需请求参数
此接口不需要任何请求参数。
---
## 响应参数
### 响应体 (JSON)
| 参数名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 请求是否成功 |
| output | array | 蒙版类型列表 |
| error | string | 失败时的错误信息 |
### output 数组中每个元素的结构
| 参数名 | 类型 | 说明 |
|--------|------|------|
| name | string | 蒙版类型名称 |
---
## 请求示例
### 示例 1: 获取蒙版类型列表
```bash
curl -X GET http://localhost:9001/get_mask_types
```
### 示例 2: Python 请求示例
```python
import requests
url = "http://localhost:9001/get_mask_types"
response = requests.get(url)
result = response.json()
print(f"Success: {result['success']}")
if result['success']:
print(f"Total mask types: {len(result['output'])}")
for mask in result['output']:
print(f" - {mask['name']}")
else:
print(f"Error: {result['error']}")
```
### 示例 3: JavaScript 请求示例
```javascript
fetch('http://localhost:9001/get_mask_types')
.then(response => response.json())
.then(result => {
if (result.success) {
console.log('Mask types:', result.output);
result.output.forEach(type => {
console.log(`- ${type.name}`);
});
} else {
console.error('Error:', result.error);
}
});
```
---
## 响应示例
### 成功响应
**状态码:** 200 OK
```json
{
"success": true,
"output": [
{ "name": "circle" },
{ "name": "rectangle" },
{ "name": "heart" },
{ "name": "star" },
{ "name": "diamond" },
{ "name": "hexagon" },
{ "name": "oval" },
{ "name": "rounded_rectangle" },
{ "name": "triangle" },
{ "name": "mirror_split" },
{ "name": "horizontal_split" },
{ "name": "vertical_split" }
],
"error": ""
}
```
### 失败响应
**状态码:** 200 OK
```json
{
"success": false,
"output": "",
"error": "Error occurred while getting mask types: Internal error."
}
```
---
## 常见蒙版类型说明
| 蒙版名称 | 形状 | 说明 | 适用场景 |
|---------|------|------|---------|
| circle | 圆形 | 标准圆形蒙版 | 人物特写、聚焦效果 |
| rectangle | 矩形 | 标准矩形蒙版 | 画框效果、窗口视图 |
| heart | 心形 | 爱心形状蒙版 | 浪漫场景、情感表达 |
| star | 星形 | 五角星形蒙版 | 重点突出、装饰效果 |
| diamond | 菱形 | 菱形蒙版 | 时尚设计、几何美感 |
| hexagon | 六边形 | 正六边形蒙版 | 科技感、蜂窝效果 |
| oval | 椭圆形 | 椭圆形蒙版 | 柔和过渡、人物肖像 |
| rounded_rectangle | 圆角矩形 | 带圆角的矩形蒙版 | 现代设计、柔和边框 |
| triangle | 三角形 | 三角形蒙版 | 方向指示、动态设计 |
| mirror_split | 镜像分割 | 镜像对称分割 | 创意效果、对比展示 |
| horizontal_split | 水平分割 | 水平方向分割 | 上下对比、分屏效果 |
| vertical_split | 垂直分割 | 垂直方向分割 | 左右对比、双画面 |
---
## 使用场景
### 场景 1: 在添加视频时使用圆形蒙版
```python
import requests
# 首先获取蒙版类型
mask_types = requests.get('http://localhost:9001/get_mask_types').json()
print('Available masks:', [m['name'] for m in mask_types['output']])
# 然后在添加视频时使用圆形蒙版
requests.post('http://localhost:9001/add_video', json={
"video_url": "https://example.com/video.mp4",
"mask_type": "circle",
"mask_center_x": 0.5,
"mask_center_y": 0.5,
"mask_size": 0.8,
"mask_feather": 0.1
})
```
### 场景 2: 创建画中画效果
```python
import requests
# 添加背景视频(带模糊)
requests.post('http://localhost:9001/add_video', json={
"video_url": "https://example.com/background.mp4",
"track_name": "video_main",
"background_blur": 3
})
# 添加前景视频(圆形蒙版)
requests.post('http://localhost:9001/add_video', json={
"video_url": "https://example.com/foreground.mp4",
"track_name": "video_pip",
"mask_type": "circle",
"mask_size": 0.6,
"transform_x": 0.6,
"transform_y": -0.6,
"scale_x": 0.4,
"scale_y": 0.4,
"relative_index": 1
})
```
### 场景 3: 心形蒙版浪漫效果
```python
import requests
requests.post('http://localhost:9001/add_video', json={
"video_url": "https://example.com/romantic.mp4",
"mask_type": "heart",
"mask_center_x": 0.5,
"mask_center_y": 0.5,
"mask_size": 1.0,
"mask_feather": 0.05
})
```
---
## 蒙版参数配合使用
`add_video``add_image` 接口中使用蒙版时,可配合以下参数:
| 参数名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| mask_type | string | null | 蒙版类型(从此接口获取) |
| mask_center_x | number | 0.5 | 蒙版中心 X 坐标(0.0-1.0 |
| mask_center_y | number | 0.5 | 蒙版中心 Y 坐标(0.0-1.0 |
| mask_size | number | 1.0 | 蒙版大小(相对屏幕高度) |
| mask_rotation | number | 0.0 | 蒙版旋转角度(度) |
| mask_feather | number | 0.0 | 蒙版羽化程度(0.0-1.0 |
| mask_invert | boolean | false | 是否反转蒙版 |
| mask_rect_width | number | null | 矩形蒙版宽度 |
| mask_round_corner | number | null | 圆角半径 |
---
## 注意事项
1. **环境差异**: 返回的蒙版类型根据环境(剪映/CapCut)可能不同
2. **形状适配**: 某些蒙版可能需要额外的参数(如矩形需要 mask_rect_width
3. **羽化效果**: mask_feather 参数可以创建柔和的边缘
4. **性能影响**: 使用蒙版会增加渲染时间
5. **反转效果**: mask_invert 可以反转蒙版区域
6. **旋转角度**: 某些非对称蒙版支持旋转
---
## 环境变量
接口返回的蒙版类型取决于以下环境配置:
- **IS_CAPCUT_ENV = True**: 返回 CapCut 国际版的蒙版类型
- **IS_CAPCUT_ENV = False**: 返回剪映的蒙版类型
---
## 相关接口
- `POST /add_video` - 添加视频(支持蒙版参数)
- `POST /add_image` - 添加图片(支持蒙版参数)
- `GET /get_transition_types` - 获取转场类型
- `GET /get_intro_animation_types` - 获取入场动画类型
---
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2025-10-21 | 初始版本 |
---
## 技术支持
如有问题,请联系:
- Email: sguann2023@gmail.com
- GitHub Issues: https://github.com/sun-guannan/CapCutAPI/issues
+270
View File
@@ -0,0 +1,270 @@
# get_text_animations 接口文档
## 接口概述
**接口名称**get_text_animations
**接口地址**`POST /openapi/capcut-mate/v1/get_text_animations`
**功能描述**:获取文字出入场动画列表,返回所有支持的且满足条件的文字出入场动画。支持根据动画类型(入场、出场、循环)和会员模式(所有、VIP、免费)进行筛选。
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### 请求体 (application/json)
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|--------|------|------|--------|------|
| mode | integer | 否 | 0 | 动画模式:0=所有,1=VIP2=免费 |
| type | string | 是 | - | 动画类型:in=入场,out=出场,loop=循环 |
### 动画模式说明
| 模式值 | 模式名称 | 描述 |
|--------|----------|------|
| 0 | 所有 | 返回所有动画(包括VIP和免费) |
| 1 | VIP | 仅返回VIP动画 |
| 2 | 免费 | 仅返回免费动画 |
### 动画类型说明
| 类型值 | 类型名称 | 描述 |
|--------|----------|------|
| in | 入场动画 | 文字出现时的动画效果 |
| out | 出场动画 | 文字消失时的动画效果 |
| loop | 循环动画 | 文字持续播放的循环动画效果 |
## 请求示例
### 获取所有入场动画
```json
{
"mode": 0,
"type": "in"
}
```
### 获取VIP出场动画
```json
{
"mode": 1,
"type": "out"
}
```
### 获取免费循环动画
```json
{
"mode": 2,
"type": "loop"
}
```
## 响应格式
### 成功响应
```json
{
"effects": "[{\"resource_id\":\"7314291622525538843\",\"type\":\"in\",\"category_id\":\"ruchang\",\"category_name\":\"入场\",\"duration\":500000,\"id\":\"35395178\",\"name\":\"冰雪飘动\",\"request_id\":\"\",\"start\":0,\"icon_url\":\"https://lf5-hl-hw-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/459c196951cadbd024456a63db89481f\",\"material_type\":\"sticker\",\"panel\":\"\",\"path\":\"\",\"platform\":\"all\"},{\"resource_id\":\"7397306443147252233\",\"type\":\"in\",\"category_id\":\"ruchang\",\"category_name\":\"入场\",\"duration\":500000,\"id\":\"77035159\",\"name\":\"变色输入\",\"request_id\":\"\",\"start\":0,\"icon_url\":\"https://lf5-hl-hw-effectcdn-tos.byteeffecttos.com/obj/ies.fe.effect/c15f5c313f8170c558043abf300a0692\",\"material_type\":\"sticker\",\"panel\":\"\",\"path\":\"\",\"platform\":\"all\"}]"
}
```
### 动画对象结构
每个动画对象包含以下字段:
| 字段名 | 类型 | 描述 |
|--------|------|------|
| resource_id | string | 动画资源ID |
| type | string | 动画类型(in/out/loop |
| category_id | string | 动画分类ID |
| category_name | string | 动画分类名称 |
| duration | integer | 动画时长(微秒) |
| id | string | 动画唯一标识ID |
| name | string | 动画名称 |
| request_id | string | 请求ID(通常为空) |
| start | integer | 动画开始时间 |
| icon_url | string | 动画图标URL |
| material_type | string | 素材类型(通常为"sticker" |
| panel | string | 面板信息 |
| path | string | 路径信息 |
| platform | string | 支持平台(通常为"all" |
### 错误响应
#### 400 Bad Request - 参数验证失败
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "请求参数验证失败",
"details": "type 参数必须为 in、out 或 loop"
}
}
```
#### 500 Internal Server Error - 获取动画失败
```json
{
"error": {
"code": "TEXT_ANIMATION_GET_FAILED",
"message": "获取文字动画失败",
"details": "动画数据获取失败"
}
}
```
## 错误码说明
| 错误码 | HTTP状态码 | 描述 | 解决方案 |
|--------|------------|------|----------|
| VALIDATION_ERROR | 400 | 请求参数验证失败 | 检查type参数是否为in/out/loopmode参数是否为0/1/2 |
| TEXT_ANIMATION_GET_FAILED | 500 | 获取文字动画失败 | 检查服务状态,稍后重试 |
## 使用说明
### 参数说明
1. **type参数**:必填参数,只能选择 "in"、"out"、"loop" 中的一个
2. **mode参数**:可选参数,默认为0(所有动画)
3. **响应数据**effects字段是JSON字符串格式,需要解析后使用
### 动画应用场景
1. **入场动画(in**
- 适用于文字出现的场景
- 如渐显入场、冰雪飘动、变色输入等
- 通常时长在0.5-1秒之间
2. **出场动画(out**
- 适用于文字消失的场景
- 如渐隐出场、旋转消失等
- 通常时长在0.6-0.8秒之间
3. **循环动画(loop**
- 适用于需要持续吸引注意力的文字
- 如心跳跳动、闪烁效果等
- 通常时长在1-1.2秒之间,可无限循环
### 使用建议
- 根据视频内容风格选择合适的动画类型
- VIP动画通常效果更佳,但需要会员权限
- 建议先获取所有动画,再根据需要进行筛选
- 可以结合动画预览图(icon_url)让用户选择
## 示例代码
### JavaScript示例
```javascript
// 获取所有入场动画
const getInAnimations = async () => {
const response = await fetch('/openapi/capcut-mate/v1/get_text_animations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
mode: 0,
type: 'in'
})
});
const result = await response.json();
const animations = JSON.parse(result.effects);
console.log('入场动画列表:', animations);
};
// 获取免费循环动画
const getFreeLoopAnimations = async () => {
const response = await fetch('/openapi/capcut-mate/v1/get_text_animations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
mode: 2,
type: 'loop'
})
});
const result = await response.json();
const animations = JSON.parse(result.effects);
console.log('免费循环动画列表:', animations);
};
```
### Python示例
```python
import requests
import json
def get_text_animations(mode=0, animation_type='in'):
"""获取文字动画列表"""
url = 'http://localhost:8000/v1/get_text_animations'
data = {
'mode': mode,
'type': animation_type
}
response = requests.post(url, json=data)
if response.status_code == 200:
result = response.json()
animations = json.loads(result['effects'])
return animations
else:
print(f"请求失败: {response.status_code}")
return []
# 使用示例
in_animations = get_text_animations(mode=0, animation_type='in')
print(f"获取到 {len(in_animations)} 个入场动画")
vip_out_animations = get_text_animations(mode=1, animation_type='out')
print(f"获取到 {len(vip_out_animations)} 个VIP出场动画")
```
## 相关接口
- [add_captions](./add_captions.md) - 批量添加字幕(可使用动画效果)
- [add_text_style](./add_text_style.md) - 创建文本富文本样式
- [add_effects](./add_effects.md) - 添加视频特效
## 技术实现
### 文件结构
```
src/
├── schemas/get_text_animations.py # 请求/响应数据模型
├── service/get_text_animations.py # 业务逻辑实现
└── router/v1.py # API路由定义
```
### 核心逻辑
1. **参数验证**:验证type和mode参数的有效性
2. **数据筛选**:根据type和mode参数筛选动画数据
3. **数据格式化**:将动画数据转换为JSON字符串格式
4. **响应返回**:返回符合规范的API响应
### 数据来源
目前使用模拟数据,实际项目中应该:
- 从数据库获取动画数据
- 或从第三方API获取动画资源
- 支持动画资源的动态更新
---
**版本信息**v1.0
**最后更新**2024-09-24
-243
View File
@@ -1,243 +0,0 @@
# get_transition_types 接口文档
## 接口概述
获取所有支持的转场动画类型列表,用于视频和图片的转场效果。
---
## 接口信息
### RESTful API 端点
```
GET /get_transition_types
```
### Content-Type
```
application/json
```
---
## 请求参数
### 无需请求参数
此接口不需要任何请求参数。
---
## 响应参数
### 响应体 (JSON)
| 参数名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 请求是否成功 |
| output | array | 转场类型列表 |
| error | string | 失败时的错误信息 |
### output 数组中每个元素的结构
| 参数名 | 类型 | 说明 |
|--------|------|------|
| name | string | 转场类型名称 |
---
## 请求示例
### 示例 1: 获取转场类型列表
```bash
curl -X GET http://localhost:9001/get_transition_types
```
### 示例 2: Python 请求示例
```python
import requests
url = "http://localhost:9001/get_transition_types"
response = requests.get(url)
result = response.json()
print(f"Success: {result['success']}")
if result['success']:
print(f"Total transition types: {len(result['output'])}")
for transition in result['output']:
print(f" - {transition['name']}")
else:
print(f"Error: {result['error']}")
```
### 示例 3: JavaScript 请求示例
```javascript
fetch('http://localhost:9001/get_transition_types')
.then(response => response.json())
.then(result => {
if (result.success) {
console.log('Transition types:', result.output);
result.output.forEach(type => {
console.log(`- ${type.name}`);
});
} else {
console.error('Error:', result.error);
}
});
```
---
## 响应示例
### 成功响应
**状态码:** 200 OK
```json
{
"success": true,
"output": [
{ "name": "fade" },
{ "name": "dissolve" },
{ "name": "wipe_left" },
{ "name": "wipe_right" },
{ "name": "wipe_up" },
{ "name": "wipe_down" },
{ "name": "slide_left" },
{ "name": "slide_right" },
{ "name": "zoom_in" },
{ "name": "zoom_out" },
{ "name": "circle_in" },
{ "name": "circle_out" },
{ "name": "blur" },
{ "name": "pixelate" }
],
"error": ""
}
```
### 失败响应
**状态码:** 200 OK
```json
{
"success": false,
"output": "",
"error": "Error occurred while getting transition animation types: Internal error."
}
```
---
## 常见转场类型说明
| 转场名称 | 类型 | 说明 | 适用场景 |
|---------|------|------|---------|
| fade | 淡入淡出 | 前一画面淡出,后一画面淡入 | 温和过渡,适合大部分场景 |
| dissolve | 溶解 | 两个画面交叉溶解 | 时间流逝、场景切换 |
| wipe_left | 左滑擦除 | 从右向左擦除 | 动感场景切换 |
| wipe_right | 右滑擦除 | 从左向右擦除 | 动感场景切换 |
| wipe_up | 上滑擦除 | 从下向上擦除 | 揭示效果 |
| wipe_down | 下滑擦除 | 从上向下擦除 | 覆盖效果 |
| slide_left | 左滑动 | 画面向左滑动切换 | 连续场景切换 |
| slide_right | 右滑动 | 画面向右滑动切换 | 连续场景切换 |
| zoom_in | 放大 | 新画面放大进入 | 强调重点 |
| zoom_out | 缩小 | 旧画面缩小退出 | 视野拉远 |
| circle_in | 圆形收缩 | 圆形区域收缩 | 聚焦效果 |
| circle_out | 圆形扩展 | 圆形区域扩展 | 展开效果 |
| blur | 模糊 | 前画面模糊后切换 | 梦幻效果 |
| pixelate | 像素化 | 像素化过渡 | 数字、科技感 |
---
## 使用场景
### 场景 1: 在添加视频时使用转场
```python
import requests
# 首先获取转场类型
transition_types = requests.get('http://localhost:9001/get_transition_types').json()
print('Available transitions:', [t['name'] for t in transition_types['output']])
# 然后在添加视频时使用
requests.post('http://localhost:9001/add_video', json={
"video_url": "https://example.com/video.mp4",
"transition": "fade",
"transition_duration": 1.0
})
```
### 场景 2: 动态选择转场效果
```python
import requests
import random
# 获取所有转场类型
response = requests.get('http://localhost:9001/get_transition_types')
transitions = response.json()['output']
# 随机选择一个转场效果
random_transition = random.choice(transitions)['name']
# 应用到视频
requests.post('http://localhost:9001/add_video', json={
"video_url": "https://example.com/video.mp4",
"transition": random_transition,
"transition_duration": 0.8
})
```
---
## 注意事项
1. **环境差异**: 返回的转场类型根据环境(剪映/CapCut)可能不同
2. **可用性**: 某些转场效果可能在特定版本中不可用
3. **性能**: 复杂的转场效果(如模糊、像素化)可能影响渲染性能
4. **时长建议**: 转场时长一般在 0.3-1.5 秒之间效果最佳
5. **搭配使用**: 可与 `add_video``add_image` 接口配合使用
---
## 环境变量
接口返回的转场类型取决于以下环境配置:
- **IS_CAPCUT_ENV = True**: 返回 CapCut 国际版的转场类型
- **IS_CAPCUT_ENV = False**: 返回剪映的转场类型
---
## 相关接口
- `POST /add_video` - 添加视频(支持转场参数)
- `POST /add_image` - 添加图片(支持转场参数)
- `GET /get_intro_animation_types` - 获取入场动画类型
- `GET /get_outro_animation_types` - 获取出场动画类型
- `GET /get_combo_animation_types` - 获取组合动画类型
---
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2025-10-21 | 初始版本 |
---
## 技术支持
如有问题,请联系:
- Email: sguann2023@gmail.com
- GitHub Issues: https://github.com/sun-guannan/CapCutAPI/issues
+249
View File
@@ -0,0 +1,249 @@
# CapCut Mate API 文档
## 📖 项目简介
CapCut Mate API 是一个基于 FastAPI 构建的剪映小助手,为开发者提供强大的视频编辑自动化能力。通过 RESTful API 接口,您可以轻松创建、编辑和渲染视频内容,无需手动操作剪映软件。
## ✨ 核心功能
### 🎬 视频制作流程
- **草稿管理**:创建、保存、获取草稿信息
- **素材添加**:支持视频、音频、图片、贴纸等多种素材
- **文本处理**:添加字幕、文本样式、关键词高亮
- **特效应用**:视觉特效、动画、转场、遮罩效果
- **视频渲染**:云端生成最终视频文件
### 🔧 技术特性
- **高性能**:基于 FastAPI 构建,支持异步处理
- **类型安全**:使用 Pydantic 进行数据验证
- **标准化**:符合 RESTful API 设计规范
- **自动文档**:集成 Swagger UI 交互式文档
- **容器化**:支持 Docker 部署
## 🚀 快速开始
### 环境要求
- Python 3.11+
- 剪映软件(用于视频渲染)
- uv 包管理器
### 安装部署
```bash
# 1. 克隆项目
git clone https://github.com/Hommy-master/capcut-mate.git
cd capcut-mate
# 2. 安装依赖
uv sync
# 3. 启动服务
uv run main.py
# 4. 或使用 Docker
docker pull gogoshine/capcut-mate:latest
```
### 基础使用
```bash
# 创建草稿
curl -X POST "http://localhost:60000/openapi/capcut-mate/v1/create_draft" \
-H "Content-Type: application/json" \
-d '{"width": 1920, "height": 1080}'
# 添加视频素材
curl -X POST "http://localhost:60000/openapi/capcut-mate/v1/add_videos" \
-H "Content-Type: application/json" \
-d '{
"draft_url": "YOUR_DRAFT_URL",
"video_infos": "[{\"video_url\":\"https://assets.jcaigc.cn/video.mp4\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":5000000,\"duration\":10000000}]"
}'
# 生成视频
curl -X POST "http://localhost:60000/openapi/capcut-mate/v1/gen_video" \
-H "Content-Type: application/json" \
-d '{"draft_url": "YOUR_DRAFT_URL"}'
```
## 📚 API 接口文档
### 🏗️ 草稿管理
| 接口 | 功能 | 描述 |
|------|------|------|
| [create_draft](./create_draft.md) | 创建草稿 | 创建新的剪映草稿项目,设置画布尺寸 |
| [save_draft](./save_draft.md) | 保存草稿 | 保存当前草稿状态,确保编辑内容持久化 |
| [get_draft](./get_draft.md) | 获取草稿 | 获取草稿文件列表和详细信息 |
### 🎥 视频素材
| 接口 | 功能 | 描述 |
|------|------|------|
| [add_videos](./add_videos.md) | 添加视频 | 批量添加视频素材,支持裁剪、缩放、特效 |
| [add_images](./add_images.md) | 添加图片 | 批量添加图片素材,支持动画和转场效果 |
| [add_sticker](./add_sticker.md) | 添加贴纸 | 添加装饰贴纸,支持位置和大小调整 |
### 🎵 音频处理
| 接口 | 功能 | 描述 |
|------|------|------|
| [add_audios](./add_audios.md) | 添加音频 | 批量添加音频素材,支持音量和淡入淡出 |
| [get_audio_duration](./get_audio_duration.md) | 获取音频时长 | 获取音频文件的精确时长信息 |
### 📝 文本字幕
| 接口 | 功能 | 描述 |
|------|------|------|
| [add_captions](./add_captions.md) | 添加字幕 | 批量添加字幕,支持关键词高亮和样式设置 |
| [add_text_style](./add_text_style.md) | 文本样式 | 创建富文本样式,支持关键词颜色和字体 |
### ✨ 特效动画
| 接口 | 功能 | 描述 |
|------|------|------|
| [add_effects](./add_effects.md) | 添加特效 | 添加视觉特效,如滤镜、边框、动态效果 |
| [add_keyframes](./add_keyframes.md) | 关键帧动画 | 创建位置、缩放、旋转等属性动画 |
| [add_masks](./add_masks.md) | 遮罩效果 | 添加各种形状遮罩,控制画面可见区域 |
### 🎨 动画资源
| 接口 | 功能 | 描述 |
|------|------|------|
| [get_text_animations](./get_text_animations.md) | 文本动画 | 获取可用的文本入场、出场、循环动画 |
| [get_image_animations](./get_image_animations.md) | 图片动画 | 获取可用的图片动画效果列表 |
### 🎬 视频生成
| 接口 | 功能 | 描述 |
|------|------|------|
| [gen_video](./gen_video.md) | 生成视频 | 提交视频渲染任务,异步处理 |
| [gen_video_status](./gen_video_status.md) | 查询状态 | 查询视频生成任务的进度和状态 |
### 🚀 快速工具
| 接口 | 功能 | 描述 |
|------|------|------|
| [easy_create_material](./easy_create_material.md) | 快速创建 | 一次性添加多种类型素材,简化创建流程 |
## 🏗️ 系统架构
### 分层设计
```
┌─────────────────┐
│ FastAPI App │ HTTP API 层
├─────────────────┤
│ Middlewares │ 中间件层(请求预处理、响应格式化)
├─────────────────┤
│ Router (v1) │ 路由层(接口定义、参数验证)
├─────────────────┤
│ Service │ 业务逻辑层(核心功能实现)
├─────────────────┤
│ pyJianYingDraft │ 剪映草稿处理层(草稿文件操作)
├─────────────────┤
│ Utils │ 工具层(缓存、日志、任务管理)
└─────────────────┘
```
### 核心模块
- **Router**: API 路由定义和请求处理
- **Service**: 业务逻辑实现和数据处理
- **pyJianYingDraft**: 剪映草稿文件的创建和编辑
- **Schemas**: 数据模型定义和验证
- **Utils**: 缓存管理、日志记录、任务调度
## 🔄 典型工作流程
### 基础视频制作流程
```mermaid
graph LR
A[创建草稿] --> B[添加视频素材]
B --> C[添加音频背景]
C --> D[添加字幕文本]
D --> E[应用特效动画]
E --> F[保存草稿]
F --> G[生成视频]
G --> H[查询状态]
H --> I[获取结果]
```
### 进阶制作流程
```mermaid
graph TB
A[创建草稿] --> B[批量添加素材]
B --> C[easy_create_material]
C --> D[精细调整]
D --> E[添加关键帧动画]
E --> F[应用遮罩效果]
F --> G[添加转场特效]
G --> H[保存并渲染]
```
## 📊 API 使用统计
### 接口分类
- **草稿管理**: 3 个接口
- **素材添加**: 6 个接口
- **特效动画**: 5 个接口
- **视频生成**: 2 个接口
- **辅助工具**: 2 个接口
### 常用组合
1. **快速制作**: `create_draft``easy_create_material``gen_video`
2. **精细编辑**: `create_draft``add_videos``add_audios``add_captions``add_effects``gen_video`
3. **动画制作**: `create_draft``add_images``add_keyframes``add_masks``gen_video`
## ⚡ 性能优化
### 建议实践
- **批量操作**: 尽量使用批量接口减少请求次数
- **异步处理**: 视频生成使用异步任务,避免长时间等待
- **缓存机制**: 草稿信息支持缓存,提高访问速度
- **错误重试**: 网络请求失败时自动重试
- **资源预检**: 使用 `get_audio_duration` 等接口预检资源
### 限制说明
- **并发限制**: 避免同时处理过多视频生成任务
- **文件大小**: 建议单个素材文件不超过 100MB
- **时长限制**: 建议单个视频时长不超过 10 分钟
- **请求频率**: 建议控制请求频率,避免服务器过载
## 🔧 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 💬 技术支持
### 获取帮助
- **交互式文档**: 访问 `http://localhost:60000/docs` 查看 Swagger UI
- **问题反馈**: 提交 GitHub Issues
- **商业合作**: 联系邮箱 taohongmin51@gmail.com
### 贡献指南
欢迎提交 Pull Request 来改进项目:
1. Fork 项目
2. 创建功能分支
3. 提交更改
4. 创建 Pull Request
## 📄 许可证
本项目采用 MIT 许可证,详情请查看 LICENSE 文件。
---
**CapCut Mate API** - 让视频创作更简单、更高效!
+270 -239
View File
@@ -1,287 +1,318 @@
# save_draft 接口文档
## 接口概述
保存草稿项目到本地文件,生成可导入剪映的草稿文件夹。
---
# SAVE_DRAFT API 接口文档
## 接口信息
### RESTful API 端点
```
POST /save_draft
POST /openapi/capcut-mate/v1/save_draft
```
### Content-Type
## 功能描述
```
application/json
```
保存剪映草稿。该接口用于保存当前的草稿状态,确保编辑的内容得到持久化存储。通常在完成一系列编辑操作后调用此接口,以防止编辑内容丢失。
---
## 更多文档
📖 更多详细文档和教程请访问:[https://docs.jcaigc.cn](https://docs.jcaigc.cn)
## 请求参数
### 请求体 (JSON)
```json
{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}
```
### 参数说明
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| **draft_id** | string | **是** | - | 草稿唯一标识符(必需参数) |
| draft_folder | string | 否 | null | 草稿保存的文件夹路径 |
| draft_url | string | ✅ | - | 要保存的草稿URL |
---
### 参数详解
## 响应参数
#### draft_url
### 响应体 (JSON)
| 参数名 | 类型 | 说明 |
|--------|------|------|
| success | boolean | 请求是否成功 |
| output | object/string | 成功时返回任务信息 |
| error | string | 失败时的错误信息 |
### 成功响应的 output 字段
| 参数名 | 类型 | 说明 |
|--------|------|------|
| task_id | string | 保存任务的唯一标识符 |
| status | string | 任务状态(pending/processing/completed/failed |
| draft_folder | string | 草稿保存的文件夹路径 |
---
## 请求示例
### 示例 1: 基础保存草稿
```bash
curl -X POST http://localhost:9001/save_draft \
-H "Content-Type: application/json" \
-d '{
"draft_id": "dfd_1234567890abcdef"
}'
```
**请求体 (JSON):**
```json
{
"draft_id": "dfd_1234567890abcdef"
- **类型**: 字符串
- **必填**: 是
- **格式**: 完整的草稿URL,通常由create_draft接口返回
- **示例**: `https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}
```
### 示例 2: 指定保存路径
### 响应字段说明
```bash
curl -X POST http://localhost:9001/save_draft \
-H "Content-Type: application/json" \
-d '{
"draft_id": "dfd_1234567890abcdef",
"draft_folder": "/path/to/save/folder"
}'
```
| 字段名 | 类型 | 说明 |
|--------|------|------|
| draft_url | string | 保存后的草稿URL,通常与请求中的URL相同 |
**请求体 (JSON):**
### 错误响应 (4xx/5xx)
```json
{
"draft_id": "dfd_1234567890abcdef",
"draft_folder": "/path/to/save/folder"
"detail": "错误信息描述"
}
```
### 示例 3: Python 请求示例
## 使用示例
### cURL 示例
#### 1. 基本保存草稿
```bash
curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/save_draft \
-H "Content-Type: application/json" \
-d '{
"draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}'
```
### JavaScript 示例
```javascript
const saveDraft = async (draftUrl) => {
const response = await fetch('/openapi/capcut-mate/v1/save_draft', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ draft_url: draftUrl })
});
return response.json();
};
// 保存草稿
const draftUrl = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258";
const result = await saveDraft(draftUrl);
console.log('草稿保存成功:', result.draft_url);
```
### 高级JavaScript示例
```javascript
class DraftManager {
constructor(baseUrl = 'https://capcut-mate.jcaigc.cn') {
this.baseUrl = baseUrl;
}
async saveDraft(draftUrl) {
const response = await fetch(`${this.baseUrl}/openapi/capcut-mate/v1/save_draft`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ draft_url: draftUrl })
});
if (!response.ok) {
throw new Error(`保存草稿失败: ${response.statusText}`);
}
return response.json();
}
// 自动保存功能
async autoSave(draftUrl, intervalMs = 30000) {
const saveInterval = setInterval(async () => {
try {
await this.saveDraft(draftUrl);
console.log(`自动保存成功: ${new Date().toLocaleTimeString()}`);
} catch (error) {
console.error('自动保存失败:', error);
}
}, intervalMs);
// 返回停止自动保存的函数
return () => clearInterval(saveInterval);
}
// 编辑流程中的保存
async editWorkflow(draftUrl, operations) {
const results = [];
for (const operation of operations) {
try {
// 执行编辑操作(这里是示例)
const editResult = await operation();
results.push(editResult);
// 每次操作后自动保存
await this.saveDraft(draftUrl);
console.log(`操作完成并保存: ${operation.name}`);
} catch (error) {
console.error(`操作失败: ${operation.name}`, error);
results.push({ error: error.message });
}
}
return results;
}
// 批量保存多个草稿
async saveMutipleDrafts(draftUrls) {
const results = {};
for (const [name, url] of Object.entries(draftUrls)) {
try {
const result = await this.saveDraft(url);
results[name] = result;
// 添加延迟避免请求过快
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
console.error(`保存草稿失败 ${name}:`, error);
results[name] = { error: error.message };
}
}
return results;
}
}
// 使用示例
const draftManager = new DraftManager();
// 基本保存
const draftUrl = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258";
await draftManager.saveDraft(draftUrl);
// 启动自动保存(每30秒保存一次)
const stopAutoSave = await draftManager.autoSave(draftUrl, 30000);
// 编辑完成后停止自动保存
setTimeout(() => {
stopAutoSave();
console.log('自动保存已停止');
}, 300000); // 5分钟后停止
// 批量保存多个草稿
const multipleDrafts = {
"project1": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
"project2": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
};
const saveResults = await draftManager.saveMutipleDrafts(multipleDrafts);
```
### Python 示例
```python
import requests
import time
import threading
from typing import Dict, List, Callable
url = "http://localhost:9001/save_draft"
headers = {
"Content-Type": "application/json"
}
data = {
"draft_id": "dfd_1234567890abcdef"
}
class DraftSaver:
def __init__(self, base_url: str = "https://assets.jcaigc.cn"):
self.base_url = base_url
self._auto_save_threads = {}
response = requests.post(url, json=data, headers=headers)
result = response.json()
def save_draft(self, draft_url: str) -> Dict:
"""保存草稿"""
response = requests.post(
f'{self.base_url}/openapi/capcut-mate/v1/save_draft',
headers={'Content-Type': 'application/json'},
json={"draft_url": draft_url}
)
response.raise_for_status()
return response.json()
print(f"Success: {result['success']}")
if result['success']:
print(f"Task ID: {result['output']['task_id']}")
print(f"Status: {result['output']['status']}")
print(f"Draft Folder: {result['output']['draft_folder']}")
else:
print(f"Error: {result['error']}")
def auto_save(self, draft_url: str, interval_seconds: int = 30) -> str:
"""启动自动保存,返回线程ID用于停止"""
def save_loop():
while True:
try:
self.save_draft(draft_url)
print(f"自动保存成功: {time.strftime('%H:%M:%S')}")
time.sleep(interval_seconds)
except Exception as e:
print(f"自动保存失败: {e}")
time.sleep(5) # 出错后等待5秒再重试
thread_id = f"auto_save_{int(time.time())}"
thread = threading.Thread(target=save_loop, daemon=True)
thread.start()
self._auto_save_threads[thread_id] = thread
return thread_id
def stop_auto_save(self, thread_id: str):
"""停止自动保存"""
if thread_id in self._auto_save_threads:
# 线程设为daemon,程序结束时会自动停止
del self._auto_save_threads[thread_id]
print(f"自动保存线程 {thread_id} 已标记停止")
def save_with_retry(self, draft_url: str, max_retries: int = 3) -> Dict:
"""带重试机制的保存"""
for attempt in range(max_retries):
try:
return self.save_draft(draft_url)
except Exception as e:
if attempt == max_retries - 1:
raise e
print(f"保存失败,第{attempt + 1}次重试: {e}")
time.sleep(2 ** attempt) # 指数退避
# 使用示例
saver = DraftSaver()
# 基本保存
draft_url = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
result = saver.save_draft(draft_url)
print(f"草稿保存成功: {result['draft_url']}")
# 带重试的保存
try:
result = saver.save_with_retry(draft_url, max_retries=3)
print("保存成功(带重试机制)")
except Exception as e:
print(f"保存最终失败: {e}")
# 启动自动保存
auto_save_id = saver.auto_save(draft_url, interval_seconds=30)
print(f"自动保存已启动,ID: {auto_save_id}")
# 10分钟后停止自动保存
time.sleep(600)
saver.stop_auto_save(auto_save_id)
```
---
## 响应示例
### 成功响应
**状态码:** 200 OK
```json
{
"success": true,
"output": {
"task_id": "task_abc123",
"status": "processing",
"draft_folder": "/output/draft/dfd_1234567890abcdef"
},
"error": ""
}
```
### 失败响应 - 缺少必需参数
**状态码:** 200 OK
```json
{
"success": false,
"output": "",
"error": "Hi, the required parameter 'draft_id' is missing. Please add it and try again."
}
```
### 失败响应 - 保存错误
**状态码:** 200 OK
```json
{
"success": false,
"output": "",
"error": "Error occurred while saving draft: Draft not found."
}
```
---
## 错误码说明
| 错误信息 | 说明 | 解决方案 |
|---------|------|---------|
| "Hi, the required parameter 'draft_id' is missing." | 缺少必需的 draft_id 参数 | 请在请求体中提供 draft_id 参数 |
| "Error occurred while saving draft: Draft not found." | 草稿不存在 | 检查 draft_id 是否正确,或先创建草稿 |
| "Error occurred while saving draft: ..." | 保存过程中出错 | 检查错误详情,确认权限和磁盘空间 |
---
## 使用场景
### 场景 1: 保存草稿到默认位置
```json
{
"draft_id": "dfd_abc123"
}
```
### 场景 2: 查询保存状态
首先保存草稿获取 task_id
```json
{
"draft_id": "dfd_abc123"
}
```
然后使用 `/query_draft_status` 查询进度:
```json
{
"task_id": "task_abc123"
}
```
---
## 保存后的文件结构
保存成功后,会在指定位置或默认位置生成以下文件结构:
```
dfd_1234567890abcdef/
├── draft_content.json # 草稿内容
├── draft_info.json # 草稿信息
├── draft_meta_info.json # 草稿元信息
└── assets/ # 资源文件夹
├── video/ # 视频文件
├── audio/ # 音频文件
└── image/ # 图片文件
```
---
## 导入剪映
保存后的草稿可以直接导入剪映:
1. **Windows 剪映**
- 复制草稿文件夹到:`C:\Users\[用户名]\AppData\Local\JianyingPro\User Data\Projects\com.lveditor.draft\`
2. **macOS 剪映**
- 复制草稿文件夹到:`~/Library/Containers/com.lveditor.LveDitor/Data/Movies/JianyingPro/User Data/Projects/com.lveditor.draft/`
3. **剪映国际版 (CapCut)**
- 复制草稿文件夹到对应的 CapCut 草稿目录
---
| 错误码 | 错误信息 | 说明 | 解决方案 |
|--------|----------|------|----------|
| 400 | draft_url是必填项 | 缺少草稿URL参数 | 提供有效的draft_url |
| 400 | draft_url格式无效 | URL格式不正确 | 检查URL格式是否正确 |
| 404 | 草稿不存在 | 指定的草稿无法找到 | 确认草稿URL是否正确且存在 |
| 500 | 保存失败 | 内部服务错误 | 联系技术支持或稍后重试 |
| 503 | 服务不可用 | 系统维护中 | 稍后重试 |
## 注意事项
1. **必需参数**: draft_id 是必需
2. **异步处理**: 保存操作是异步的,返回 task_id 后可以查询状态
3. **文件夹权限**: 确保有写入权限到指定的 draft_folder
4. **草稿存在性**: 保存前确保草稿已创建并添加了内容
5. **覆盖警告**: 如果目标位置已存在同名草稿,可能会被覆盖
6. **资源文件**: 会自动下载和保存所有引用的远程资源
---
1. **URL有效性**: 确保传入的draft_url是有效且存在
2. **网络稳定性**: 保存操作需要稳定的网络连接
3. **频率控制**: 避免过于频繁的保存操作
4. **自动保存**: 建议在长时间编辑时启用自动保存功能
5. **错误处理**: 保存失败时应该有重试机制
6. **并发安全**: 同一草稿的并发保存可能导致冲突
## 工作流程
```
1. 创建草稿 (create_draft)
2. 添加各种素材 (add_video/audio/text/image)
3. 保存草稿 (save_draft) ← 当前接口
4. 查询保存状态 (query_draft_status)
5. 导入剪映进行编辑
```
1. 验证draft_url参数
2. 检查草稿是否存在
3. 获取当前草稿状态
4. 持久化保存草稿数据
5. 返回保存结果
---
## 最佳实践
1. **定期保存**: 在重要操作后及时保存
2. **自动保存**: 为长时间编辑设置自动保存
3. **错误恢复**: 保存失败时提供重试机制
4. **状态提示**: 向用户显示保存状态
5. **备份策略**: 考虑多版本备份机制
## 相关接口
- `POST /create_draft` - 创建新草稿
- `POST /query_draft_status` - 查询保存状态
- `POST /query_script` - 查询草稿脚本
- `POST /generate_draft_url` - 生成草稿预览 URL
---
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0 | 2025-10-21 | 初始版本 |
---
## 技术支持
如有问题,请联系:
- Email: sguann2023@gmail.com
- GitHub Issues: https://github.com/sun-guannan/CapCutAPI/issues
- [创建草稿](./create_draft.md)
- [添加视频](./add_videos.md)
- [添加音频](./add_audios.md)
- [添加图片](./add_images.md)
- [生成视频](./gen_video.md)
-200
View File
@@ -1,200 +0,0 @@
import os
import subprocess
import time
import requests
import shutil
from requests.exceptions import RequestException, Timeout
from urllib.parse import urlparse, unquote
def download_video(video_url, draft_name, material_name):
"""
Download video to specified directory
:param video_url: Video URL
:param draft_name: Draft name
:param material_name: Material name
:return: Local video path
"""
# Ensure directory exists
video_dir = f"{draft_name}/assets/video"
os.makedirs(video_dir, exist_ok=True)
# Generate local filename
local_path = f"{video_dir}/{material_name}"
# Check if file already exists
if os.path.exists(local_path):
print(f"Video file already exists: {local_path}")
return local_path
try:
# Use ffmpeg to download video
command = [
'ffmpeg',
'-i', video_url,
'-c', 'copy', # Direct copy, no re-encoding
local_path
]
subprocess.run(command, check=True, capture_output=True)
return local_path
except subprocess.CalledProcessError as e:
raise Exception(f"Failed to download video: {e.stderr.decode('utf-8')}")
def download_image(image_url, draft_name, material_name):
"""
Download image to specified directory, and convert to PNG format
:param image_url: Image URL
:param draft_name: Draft name
:param material_name: Material name
:return: Local image path
"""
# Ensure directory exists
image_dir = f"{draft_name}/assets/image"
os.makedirs(image_dir, exist_ok=True)
# Uniformly use png format
local_path = f"{image_dir}/{material_name}"
# Check if file already exists
if os.path.exists(local_path):
print(f"Image file already exists: {local_path}")
return local_path
try:
# Use ffmpeg to download and convert image to PNG format
command = [
'ffmpeg',
'-headers', 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36\r\nReferer: https://www.163.com/\r\n',
'-i', image_url,
'-vf', 'format=rgba', # Convert to RGBA format to support transparency
'-frames:v', '1', # Ensure only one frame is processed
'-y', # Overwrite existing files
local_path
]
subprocess.run(command, check=True, capture_output=True)
return local_path
except subprocess.CalledProcessError as e:
raise Exception(f"Failed to download image: {e.stderr.decode('utf-8')}")
def download_audio(audio_url, draft_name, material_name):
"""
Download audio and transcode to MP3 format to specified directory
:param audio_url: Audio URL
:param draft_name: Draft name
:param material_name: Material name
:return: Local audio path
"""
# Ensure directory exists
audio_dir = f"{draft_name}/assets/audio"
os.makedirs(audio_dir, exist_ok=True)
# Generate local filename (keep .mp3 extension)
local_path = f"{audio_dir}/{material_name}"
# Check if file already exists
if os.path.exists(local_path):
print(f"Audio file already exists: {local_path}")
return local_path
try:
# Use ffmpeg to download and transcode to MP3 (key modification: specify MP3 encoder)
command = [
'ffmpeg',
'-i', audio_url, # Input URL
'-c:a', 'libmp3lame', # Force encode audio stream to MP3
'-q:a', '2', # Set audio quality (0-9, 0 is best, 2 balances quality and file size)
'-y', # Overwrite existing files (optional)
local_path # Output path
]
subprocess.run(command, check=True, capture_output=True, text=True)
return local_path
except subprocess.CalledProcessError as e:
raise Exception(f"Failed to download audio:\n{e.stderr}")
def download_file(url:str, local_filename, max_retries=3, timeout=180):
# 检查是否是本地文件路径
if os.path.exists(url) and os.path.isfile(url):
# 是本地文件,直接复制
directory = os.path.dirname(local_filename)
# 创建目标目录(如果不存在)
if directory and not os.path.exists(directory):
os.makedirs(directory, exist_ok=True)
print(f"Created directory: {directory}")
print(f"Copying local file: {url} to {local_filename}")
start_time = time.time()
# 复制文件
shutil.copy2(url, local_filename)
print(f"Copy completed in {time.time()-start_time:.2f} seconds")
print(f"File saved as: {os.path.abspath(local_filename)}")
return True
# 原有的下载逻辑
# Extract directory part
directory = os.path.dirname(local_filename)
retries = 0
while retries < max_retries:
try:
if retries > 0:
wait_time = 2 ** retries # Exponential backoff strategy
print(f"Retrying in {wait_time} seconds... (Attempt {retries+1}/{max_retries})")
time.sleep(wait_time)
print(f"Downloading file: {local_filename}")
start_time = time.time()
# Create directory (if it doesn't exist)
if directory and not os.path.exists(directory):
os.makedirs(directory, exist_ok=True)
print(f"Created directory: {directory}")
# Add headers
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
'Referer': 'https://www.163.com/', # 网易的Referer
'Accept': 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8'
}
with requests.get(url, stream=True, timeout=timeout, headers=headers) as response:
response.raise_for_status()
total_size = int(response.headers.get('content-length', 0))
block_size = 1024
with open(local_filename, 'wb') as file:
bytes_written = 0
for chunk in response.iter_content(block_size):
if chunk:
file.write(chunk)
bytes_written += len(chunk)
if total_size > 0:
progress = bytes_written / total_size * 100
# For frequently updated progress, consider using logger.debug or more granular control to avoid large log files
# Or only output progress to console, not write to file
print(f"\r[PROGRESS] {progress:.2f}% ({bytes_written/1024:.2f}KB/{total_size/1024:.2f}KB)", end='')
pass # Avoid printing too much progress information in log files
if total_size > 0:
# print() # Original newline
pass
print(f"Download completed in {time.time()-start_time:.2f} seconds")
print(f"File saved as: {os.path.abspath(local_filename)}")
return True
except Timeout:
print(f"Download timed out after {timeout} seconds")
except RequestException as e:
print(f"Request failed: {e}")
except Exception as e:
print(f"Unexpected error during download: {e}")
retries += 1
print(f"Download failed after {max_retries} attempts for URL: {url}")
return False
-2376
View File
File diff suppressed because it is too large Load Diff
-66
View File
@@ -1,66 +0,0 @@
import os
import shutil
import sys
# 添加父目录到系统路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# 从example.py中导入必要的函数
from example import add_video_impl, add_effect, save_draft_impl
def example_capcut_effect():
"""Test service for adding effects"""
# draft_folder = "/Users/sunguannan/Movies/JianyingPro/User Data/Projects/com.lveditor.draft"
draft_folder = "/Users/sunguannan/Movies/CapCut/User Data/Projects/com.lveditor.draft"
print("\nTest: Adding effects")
# First add video track
image_result = add_video_impl(
video_url="https://pan.superbed.cn/share/1nbrg1fl/jimeng_daweidai.mp4",
start=0,
end=3.0,
target_start=0,
width=1080,
height=1920
)
print(f"Video added successfully! {image_result['output']['draft_id']}")
image_result = add_video_impl(
video_url="https://pan.superbed.cn/share/1nbrg1fl/jimeng_daweidai.mp4",
draft_id=image_result['output']['draft_id'],
start=0,
end=3.0,
target_start=3,
)
print(f"Video added successfully! {image_result['output']['draft_id']}")
# Then add effect
effect_result = add_effect(
effect_type="Like",
effect_category="character", # Explicitly specify as character effect
start=3,
end=6,
draft_id=image_result['output']['draft_id'],
track_name="effect_01"
)
print(f"Effect adding result: {effect_result}")
print(save_draft_impl(effect_result['output']['draft_id'], draft_folder))
source_folder = os.path.join(os.getcwd(), effect_result['output']['draft_id'])
destination_folder = os.path.join(draft_folder, effect_result['output']['draft_id'])
if os.path.exists(source_folder):
print(f"Moving {effect_result['output']['draft_id']} to {draft_folder}")
shutil.move(source_folder, destination_folder)
print("Folder moved successfully!")
else:
print(f"Source folder {source_folder} does not exist")
# Add log to prompt user to find the draft in CapCut
print(f"\n===== IMPORTANT =====\nPlease open CapCut and find the draft named '{effect_result['output']['draft_id']}'\n=======================")
# Return the first test result for subsequent operations (if any)
return effect_result
if __name__ == "__main__":
example_capcut_effect()
+73
View File
@@ -0,0 +1,73 @@
from enum import Enum
# 自定义错误码
class CustomError(Enum):
"""错误码枚举类(支持中英文)"""
# ===== 基础错误码 (1000-1999) =====
SUCCESS = (0, "成功", "Success")
PARAM_VALIDATION_FAILED = (1001, "参数校验失败", "Parameter validation failed")
RESOURCE_NOT_FOUND = (1002, "资源不存在", "Resource not found")
PERMISSION_DENIED = (1003, "权限不足", "Permission denied")
AUTHENTICATION_FAILED = (1004, "认证失败", "Authentication failed")
# ===== 业务错误码 (2000-2999) =====
INVALID_DRAFT_URL = (2001, "无效的草稿URL", "Invalid draft URL")
DRAFT_CREATE_FAILED = (2002, "草稿创建失败", "Draft creation failed")
INVALID_VIDEO_INFO = (2003, "无效的视频信息,请检查video_infos字段值是否正确", "Invalid video information, please check if the value of the video_infos field is correct.")
FILE_SIZE_LIMIT_EXCEEDED = (2004, "文件大小超出限制", "File size exceeds the limit")
DOWNLOAD_FILE_FAILED = (2005, "下载文件失败", "Download file failed")
VIDEO_ADD_FAILED = (2006, "视频添加失败", "Video addition failed")
INVALID_AUDIO_INFO = (2007, "无效的音频信息,请检查audio_infos字段值是否正确", "Invalid audio information, please check if the value of the audio_infos field is correct.")
AUDIO_ADD_FAILED = (2008, "音频添加失败", "Audio addition failed")
INVALID_IMAGE_INFO = (2009, "无效的图片信息,请检查image_infos字段值是否正确", "Invalid image information, please check if the value of the image_infos field is correct.")
IMAGE_ADD_FAILED = (2010, "图片添加失败", "Image addition failed")
INVALID_STICKER_INFO = (2011, "无效的贴纸信息,请检查贴纸参数是否正确", "Invalid sticker information, please check if sticker parameters are correct.")
STICKER_ADD_FAILED = (2012, "贴纸添加失败", "Sticker addition failed")
INVALID_KEYFRAME_INFO = (2013, "无效的关键帧信息,请检查keyframes字段值是否正确", "Invalid keyframe information, please check if the value of the keyframes field is correct.")
KEYFRAME_ADD_FAILED = (2014, "关键帧添加失败", "Keyframe addition failed")
SEGMENT_NOT_FOUND = (2015, "片段未找到,请检查segment_id是否正确", "Segment not found, please check if the segment_id is correct.")
INVALID_SEGMENT_TYPE = (2016, "无效的片段类型,该片段不支持关键帧", "Invalid segment type, this segment does not support keyframes.")
INVALID_KEYFRAME_PROPERTY = (2017, "无效的关键帧属性类型", "Invalid keyframe property type.")
INVALID_CAPTION_INFO = (2018, "无效的字幕信息,请检查captions字段值是否正确", "Invalid caption information, please check if the value of the captions field is correct.")
CAPTION_ADD_FAILED = (2019, "字幕添加失败", "Caption addition failed")
INVALID_EFFECT_INFO = (2020, "无效的特效信息,请检查effect_infos字段值是否正确", "Invalid effect information, please check if the value of the effect_infos field is correct.")
EFFECT_ADD_FAILED = (2021, "特效添加失败", "Effect addition failed")
EFFECT_NOT_FOUND = (2022, "特效未找到,请检查特效名称是否正确", "Effect not found, please check if the effect name is correct.")
INVALID_MASK_INFO = (2023, "无效的遮罩信息,请检查遮罩参数是否正确", "Invalid mask information, please check if mask parameters are correct.")
MASK_ADD_FAILED = (2024, "遮罩添加失败", "Mask addition failed")
MASK_NOT_FOUND = (2025, "遮罩类型未找到,请检查遮罩名称是否正确", "Mask type not found, please check if the mask name is correct.")
INVALID_TEXT_STYLE_INFO = (2026, "无效的文本样式信息,请检查文本或关键词参数", "Invalid text style information, please check text or keyword parameters.")
TEXT_STYLE_CREATE_FAILED = (2027, "文本样式创建失败", "Text style creation failed")
MATERIAL_CREATE_FAILED = (2028, "素材创建失败", "Material creation failed")
TEXT_ANIMATION_GET_FAILED = (2029, "获取文字动画失败", "Get text animation failed")
VIDEO_GENERATION_SUBMIT_FAILED = (2030, "视频生成任务提交失败", "Video generation task submit failed")
VIDEO_TASK_NOT_FOUND = (2031, "视频生成任务未找到", "Video generation task not found")
VIDEO_STATUS_QUERY_FAILED = (2032, "视频任务状态查询失败", "Video task status query failed")
IMAGE_ANIMATION_GET_FAILED = (2033, "获取图片动画失败", "Get image animation failed")
AUDIO_DURATION_GET_FAILED = (2034, "获取音频时长失败", "Get audio duration failed")
# ===== 系统错误码 (9000-9999) =====
INTERNAL_SERVER_ERROR = (9998, "系统内部错误", "Internal server error")
UNKNOWN_ERROR = (9999, "未知异常", "Unknown error")
def __init__(self, code: int, cn_message: str, en_message: str) -> None:
self.code = code
self.cn_message = cn_message
self.en_message = en_message
def as_dict(self, detail: str = "", lang: str = 'zh') -> dict:
"""转换为API响应格式,支持中英文"""
message = self.cn_message if lang == 'zh' else self.en_message
if detail:
message += f"({detail})"
return {"code": self.code, "message": message}
# 自定义异常类
class CustomException(Exception):
"""自定义业务异常类"""
def __init__(self, err: CustomError, detail: str = "") -> None:
self.err = err
self.detail = detail
super().__init__(err.cn_message)
-100
View File
@@ -1,100 +0,0 @@
import subprocess
import json
import time
def get_video_duration(video_url):
"""
Get video duration with timeout retry support.
:param video_url: Video URL
:return: Video duration (seconds)
"""
# Define retry count and wait time for each retry
max_retries = 3
retry_delay_seconds = 1 # 1 second interval between retries
timeout_seconds = 10 # Set timeout for each attempt
for attempt in range(max_retries):
print(f"Attempting to get video duration (Attempt {attempt + 1}/{max_retries}) ...")
result = {"success": False, "output": 0, "error": None} # Reset result before each retry
try:
command = [
'ffprobe',
'-v', 'error',
'-show_entries', 'stream=duration',
'-show_entries', 'format=duration',
'-print_format', 'json',
video_url
]
# Use subprocess.run for more flexible handling of timeout and output
process = subprocess.run(command,
capture_output=True,
text=True, # Auto decode to text
timeout=timeout_seconds, # Use variable to set timeout
check=True) # Raise CalledProcessError if non-zero exit code
info = json.loads(process.stdout)
# Prioritize getting duration from streams because it's more accurate
media_streams = [s for s in info.get('streams', []) if 'duration' in s]
if media_streams:
duration = float(media_streams[0]['duration'])
result["output"] = duration
result["success"] = True
# Otherwise get duration from format information
elif 'format' in info and 'duration' in info['format']:
duration = float(info['format']['duration'])
result["output"] = duration
result["success"] = True
else:
result["error"] = "Audio/video duration information not found."
# If duration is successfully obtained, return result directly without retrying
if result["success"]:
print(f"Successfully obtained duration: {result['output']:.2f} seconds")
return result
except subprocess.TimeoutExpired:
result["error"] = f"Getting video duration timed out (exceeded {timeout_seconds} seconds)."
print(f"Attempt {attempt + 1} timed out.")
except subprocess.CalledProcessError as e:
result["error"] = f"Error executing ffprobe command (exit code {e.returncode}): {e.stderr.strip()}"
print(f"Attempt {attempt + 1} failed. Error: {e.stderr.strip()}")
except json.JSONDecodeError as e:
result["error"] = f"Error parsing JSON data: {e}"
print(f"Attempt {attempt + 1} failed. JSON parsing error: {e}")
except FileNotFoundError:
result["error"] = "ffprobe command not found. Please ensure FFmpeg is installed and in system PATH."
print("Error: ffprobe command not found, please check installation.")
return result # No need to retry if ffprobe itself is not found
except Exception as e:
result["error"] = f"Unknown error occurred: {e}"
print(f"Attempt {attempt + 1} failed. Unknown error: {e}")
# Try using remote service to get duration after each local failure
if not result["success"]:
print(f"Local retrieval failed")
# try:
# remote_duration = get_duration(video_url)
# if remote_duration is not None:
# result["success"] = True
# result["output"] = remote_duration
# result["error"] = None
# print(f"Remote service successfully obtained duration: {remote_duration:.2f} seconds")
# return result # Remote service succeeded, return directly
# else:
# print(f"Remote service also unable to get duration (Attempt {attempt + 1})")
# except Exception as e:
# print(f"Remote service failed to get duration (Attempt {attempt + 1}): {e}")
# If current attempt failed and max retries not reached, wait and prepare for next retry
if not result["success"] and attempt < max_retries - 1:
print(f"Waiting {retry_delay_seconds} seconds before retrying...")
time.sleep(retry_delay_seconds)
elif not result["success"] and attempt == max_retries - 1:
print(f"Maximum retry count {max_retries} reached, both local and remote services unable to get duration.")
return result # Return the last failure result after all retries fail
+24 -487
View File
@@ -1,496 +1,33 @@
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
import uvicorn
from src.router import v1_router
from src.utils.logger import logger
from src.middlewares import PrepareMiddleware, ResponseMiddleware
import pyJianYingDraft as draft
from pyJianYingDraft.metadata.animation_meta import Intro_type, Outro_type, Group_animation_type
from pyJianYingDraft.metadata.capcut_animation_meta import CapCut_Intro_type, CapCut_Outro_type, CapCut_Group_animation_type
from pyJianYingDraft.metadata.transition_meta import Transition_type
from pyJianYingDraft.metadata.capcut_transition_meta import CapCut_Transition_type
from pyJianYingDraft.metadata.mask_meta import Mask_type
from pyJianYingDraft.metadata.capcut_mask_meta import CapCut_Mask_type
from pyJianYingDraft.metadata.audio_effect_meta import Tone_effect_type, Audio_scene_effect_type, Speech_to_song_type
from pyJianYingDraft.metadata.capcut_audio_effect_meta import CapCut_Voice_filters_effect_type, CapCut_Voice_characters_effect_type, CapCut_Speech_to_song_effect_type
from pyJianYingDraft.metadata.font_meta import Font_type
from pyJianYingDraft.metadata.animation_meta import Text_intro, Text_outro, Text_loop_anim
from pyJianYingDraft.metadata.capcut_text_animation_meta import CapCut_Text_intro, CapCut_Text_outro, CapCut_Text_loop_anim
from pyJianYingDraft.metadata.video_effect_meta import Video_scene_effect_type, Video_character_effect_type
from pyJianYingDraft.metadata.capcut_effect_meta import CapCut_Video_scene_effect_type, CapCut_Video_character_effect_type
from add_audio_track import add_audio_track
from add_video_track import add_video_track
from add_text_impl import add_text_impl
from add_subtitle_impl import add_subtitle_impl
from add_image_impl import add_image_impl
from add_video_keyframe_impl import add_video_keyframe_impl
from save_draft_impl import save_draft_impl, query_task_status, query_script_impl
from add_effect_impl import add_effect_impl
from add_sticker_impl import add_sticker_impl
from create_draft import create_draft
from util import generate_draft_url as utilgenerate_draft_url, hex_to_rgb
from pyJianYingDraft.text_segment import TextStyleRange, Text_style, Text_border
from settings.local import IS_CAPCUT_ENV, DRAFT_DOMAIN, PREVIEW_ROUTER, PORT
# 1. 创建 FastAPI 应用
app: FastAPI = FastAPI(title="CapCut Mate API", version="1.0")
# 请求模型定义在 schemas 中
from schemas import (
AddVideoRequest, AddAudioRequest, CreateDraftRequest, AddSubtitleRequest,
AddTextRequest, AddImageRequest, AddVideoKeyframeRequest, AddEffectRequest,
QueryScriptRequest, SaveDraftRequest, QueryDraftStatusRequest,
GenerateDraftURLRequest, AddStickerRequest
)
# 2. 注册路由
app.include_router(router=v1_router, prefix="/openapi/capcut-mate", tags=["capcut-mate"])
# 创建 FastAPI 应用
app = FastAPI(
title="CapCut Mate API",
description="剪映辅助工具 API - 支持视频、音频、文字、图片等素材编辑",
version="2.0.0",
docs_url="/apidocs",
redoc_url="/redoc"
)
# 3. 添加中间件
app.add_middleware(middleware_class=PrepareMiddleware)
# 注册统一响应处理中间件(注意顺序,应该在其他中间件之后注册)
app.add_middleware(middleware_class=ResponseMiddleware)
# 添加 CORS 中间件
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 4. 打印所有路由
for r in app.routes:
# 1. 取 HTTP 方法列表
methods = getattr(r, "methods", None) or [getattr(r, "method", "WS")]
# 2. 安全地取路径
path = getattr(r, "path", "<unknown>")
# 3. 安全地取函数名
name = getattr(r, "name", "<unnamed>")
logger.info("Route: %s %s -> %s", ",".join(sorted(methods)), path, name)
# ==================== Pydantic 模型定义 ====================
# 统一响应模型
class StandardResponse(BaseModel):
success: bool = Field(description="请求是否成功")
output: Any = Field(default="", description="返回数据")
error: str = Field(default="", description="错误信息")
# ==================== API 路由 ====================
@app.post("/add_video", response_model=StandardResponse, tags=["媒体素材"])
async def add_video_endpoint(request: AddVideoRequest):
"""添加视频到草稿"""
try:
draft_result = add_video_track(
draft_folder=request.draft_folder, video_url=request.video_url, width=request.width,
height=request.height, start=request.start, end=request.end, target_start=request.target_start,
draft_id=request.draft_id, transform_y=request.transform_y, scale_x=request.scale_x,
scale_y=request.scale_y, transform_x=request.transform_x, speed=request.speed,
track_name=request.track_name, relative_index=request.relative_index, duration=request.duration,
transition=request.transition, transition_duration=request.transition_duration, volume=request.volume,
mask_type=request.mask_type, mask_center_x=request.mask_center_x, mask_center_y=request.mask_center_y,
mask_size=request.mask_size, mask_rotation=request.mask_rotation, mask_feather=request.mask_feather,
mask_invert=request.mask_invert, mask_rect_width=request.mask_rect_width,
mask_round_corner=request.mask_round_corner, background_blur=request.background_blur
)
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while processing video: {str(e)}.")
@app.post("/add_audio", response_model=StandardResponse, tags=["媒体素材"])
async def add_audio_endpoint(request: AddAudioRequest):
"""添加音频到草稿"""
try:
sound_effects = [(request.effect_type, request.effect_params)] if request.effect_type else None
draft_result = add_audio_track(
draft_folder=request.draft_folder, audio_url=request.audio_url, start=request.start,
end=request.end, target_start=request.target_start, draft_id=request.draft_id,
volume=request.volume, track_name=request.track_name, speed=request.speed,
sound_effects=sound_effects, width=request.width, height=request.height, duration=request.duration
)
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while processing audio: {str(e)}.")
@app.post("/create_draft", response_model=StandardResponse, tags=["草稿管理"])
async def create_draft_endpoint(request: CreateDraftRequest):
"""创建新草稿"""
try:
script, draft_id = create_draft(width=request.width, height=request.height)
return StandardResponse(success=True, output={"draft_id": draft_id, "draft_url": utilgenerate_draft_url(draft_id)})
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while creating draft: {str(e)}.")
@app.post("/add_subtitle", response_model=StandardResponse, tags=["媒体素材"])
async def add_subtitle_endpoint(request: AddSubtitleRequest):
"""添加字幕到草稿"""
try:
draft_result = add_subtitle_impl(
srt_path=request.srt, draft_id=request.draft_id, track_name=request.track_name, # type: ignore
time_offset=request.time_offset, font=request.font, font_size=request.font_size,
bold=request.bold, italic=request.italic, underline=request.underline,
font_color=request.font_color, vertical=request.vertical, alpha=request.alpha,
border_alpha=request.border_alpha, border_color=request.border_color,
border_width=request.border_width, background_color=request.background_color,
background_style=request.background_style, background_alpha=request.background_alpha,
transform_x=request.transform_x, transform_y=request.transform_y,
scale_x=request.scale_x, scale_y=request.scale_y, rotation=request.rotation,
width=request.width, height=request.height
)
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while processing subtitle: {str(e)}.")
@app.post("/add_text", response_model=StandardResponse, tags=["媒体素材"])
async def add_text_endpoint(request: AddTextRequest):
"""添加文字到草稿"""
try:
font_color = request.color if request.color else request.font_color
font_size = request.size if request.size else request.font_size
font_alpha = request.alpha if request.alpha is not None else request.font_alpha
text_styles = None
if request.text_styles:
text_styles = []
for style_data in request.text_styles:
style_dict = style_data.style or {}
style = Text_style(
size=style_dict.get('size', font_size), bold=style_dict.get('bold', False),
italic=style_dict.get('italic', False), underline=style_dict.get('underline', False),
color=hex_to_rgb(style_dict.get('color', font_color)), alpha=style_dict.get('alpha', font_alpha),
align=style_dict.get('align', 1), vertical=style_dict.get('vertical', request.vertical),
letter_spacing=style_dict.get('letter_spacing', 0), line_spacing=style_dict.get('line_spacing', 0)
)
border = None
border_dict = style_data.border or {}
if border_dict.get('width', 0) > 0:
border = Text_border(
alpha=border_dict.get('alpha', request.border_alpha),
color=hex_to_rgb(border_dict.get('color', request.border_color)),
width=border_dict.get('width', request.border_width)
)
style_range = TextStyleRange(
start=style_data.start, end=style_data.end, style=style,
border=border, font_str=style_data.font or request.font
)
text_styles.append(style_range)
draft_result = add_text_impl(
text=request.text, start=request.start, end=request.end, draft_id=request.draft_id,
transform_y=request.transform_y, transform_x=request.transform_x, font=request.font,
font_color=font_color, font_size=font_size, track_name=request.track_name,
vertical=request.vertical, font_alpha=font_alpha, border_alpha=request.border_alpha,
border_color=request.border_color, border_width=request.border_width,
background_color=request.background_color, background_style=request.background_style,
background_alpha=request.background_alpha, background_round_radius=request.background_round_radius,
background_height=request.background_height, background_width=request.background_width,
background_horizontal_offset=request.background_horizontal_offset,
background_vertical_offset=request.background_vertical_offset,
shadow_enabled=request.shadow_enabled, shadow_alpha=request.shadow_alpha,
shadow_angle=request.shadow_angle, shadow_color=request.shadow_color,
shadow_distance=request.shadow_distance, shadow_smoothing=request.shadow_smoothing,
bubble_effect_id=request.bubble_effect_id, bubble_resource_id=request.bubble_resource_id,
effect_effect_id=request.effect_effect_id, intro_animation=request.intro_animation,
intro_duration=request.intro_duration, outro_animation=request.outro_animation,
outro_duration=request.outro_duration, width=request.width, height=request.height,
fixed_width=request.fixed_width, fixed_height=request.fixed_height, text_styles=text_styles
)
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while processing text: {str(e)}.")
@app.post("/add_image", response_model=StandardResponse, tags=["媒体素材"])
async def add_image_endpoint(request: AddImageRequest):
"""添加图片到草稿"""
try:
draft_result = add_image_impl(
draft_folder=request.draft_folder, image_url=request.image_url, width=request.width,
height=request.height, start=request.start, end=request.end, draft_id=request.draft_id,
transform_y=request.transform_y, scale_x=request.scale_x, scale_y=request.scale_y,
transform_x=request.transform_x, track_name=request.track_name, relative_index=request.relative_index,
animation=request.animation, animation_duration=request.animation_duration,
intro_animation=request.intro_animation, intro_animation_duration=request.intro_animation_duration,
outro_animation=request.outro_animation, outro_animation_duration=request.outro_animation_duration,
combo_animation=request.combo_animation, combo_animation_duration=request.combo_animation_duration,
transition=request.transition, transition_duration=request.transition_duration,
mask_type=request.mask_type, mask_center_x=request.mask_center_x, mask_center_y=request.mask_center_y,
mask_size=request.mask_size, mask_rotation=request.mask_rotation, mask_feather=request.mask_feather,
mask_invert=request.mask_invert, mask_rect_width=request.mask_rect_width,
mask_round_corner=request.mask_round_corner, background_blur=request.background_blur
)
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while processing image: {str(e)}.")
@app.post("/add_video_keyframe", response_model=StandardResponse, tags=["特效和动画"])
async def add_video_keyframe_endpoint(request: AddVideoKeyframeRequest):
"""添加视频关键帧"""
try:
draft_result = add_video_keyframe_impl(
draft_id=request.draft_id, track_name=request.track_name, property_type=request.property_type,
time=request.time, value=request.value, property_types=request.property_types,
times=request.times, values=request.values
)
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while adding keyframe: {str(e)}.")
@app.post("/add_effect", response_model=StandardResponse, tags=["特效和动画"])
async def add_effect_endpoint(request: AddEffectRequest):
"""添加特效"""
try:
# 验证 effect_category 参数
if request.effect_category not in ["scene", "character"]:
return StandardResponse(success=False, error="effect_category must be 'scene' or 'character'")
draft_result = add_effect_impl(
effect_type=request.effect_type, effect_category=request.effect_category, # type: ignore
start=request.start, end=request.end, draft_id=request.draft_id,
track_name=request.track_name, params=request.params,
width=request.width, height=request.height
)
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while adding effect: {str(e)}.")
@app.post("/query_script", response_model=StandardResponse, tags=["草稿管理"])
async def query_script_endpoint(request: QueryScriptRequest):
"""查询草稿脚本"""
try:
script = query_script_impl(draft_id=request.draft_id, force_update=request.force_update)
if script is None:
return StandardResponse(success=False, error=f"Draft {request.draft_id} does not exist in cache.")
return StandardResponse(success=True, output=script.dumps())
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while querying script: {str(e)}.")
@app.post("/save_draft", response_model=StandardResponse, tags=["草稿管理"])
async def save_draft_endpoint(request: SaveDraftRequest):
"""保存草稿"""
try:
draft_result = save_draft_impl(request.draft_id, request.draft_folder) # type: ignore
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while saving draft: {str(e)}.")
@app.post("/query_draft_status", response_model=StandardResponse, tags=["任务查询"])
async def query_draft_status_endpoint(request: QueryDraftStatusRequest):
"""查询草稿保存状态"""
try:
task_status = query_task_status(request.task_id)
if task_status["status"] == "not_found":
return StandardResponse(success=False, error=f"Task with ID {request.task_id} not found.")
return StandardResponse(success=True, output=task_status)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while querying task status: {str(e)}.")
@app.post("/generate_draft_url", response_model=StandardResponse, tags=["草稿管理"])
async def generate_draft_url_endpoint(request: GenerateDraftURLRequest):
"""生成草稿预览 URL"""
try:
draft_result = {"draft_url": f"{DRAFT_DOMAIN}{PREVIEW_ROUTER}?={request.draft_id}"}
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while generating draft URL: {str(e)}.")
@app.post("/add_sticker", response_model=StandardResponse, tags=["媒体素材"])
async def add_sticker_endpoint(request: AddStickerRequest):
"""添加贴纸"""
try:
draft_result = add_sticker_impl(
resource_id=request.sticker_id, start=request.start, end=request.end,
draft_id=request.draft_id, transform_y=request.transform_y, transform_x=request.transform_x, # type: ignore
alpha=request.alpha, flip_horizontal=request.flip_horizontal, flip_vertical=request.flip_vertical,
rotation=request.rotation, scale_x=request.scale_x, scale_y=request.scale_y,
track_name=request.track_name, relative_index=request.relative_index,
width=request.width, height=request.height
)
return StandardResponse(success=True, output=draft_result)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred while adding sticker: {str(e)}.")
# ==================== 资源查询接口 ====================
@app.get("/get_intro_animation_types", response_model=StandardResponse, tags=["资源查询"])
async def get_intro_animation_types():
"""获取入场动画类型列表"""
try:
animation_types = []
enum_type = CapCut_Intro_type if IS_CAPCUT_ENV else Intro_type
for name, member in enum_type.__members__.items():
animation_types.append({"name": name})
return StandardResponse(success=True, output=animation_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_outro_animation_types", response_model=StandardResponse, tags=["资源查询"])
async def get_outro_animation_types():
"""获取出场动画类型列表"""
try:
animation_types = []
enum_type = CapCut_Outro_type if IS_CAPCUT_ENV else Outro_type
for name, member in enum_type.__members__.items():
animation_types.append({"name": name})
return StandardResponse(success=True, output=animation_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_combo_animation_types", response_model=StandardResponse, tags=["资源查询"])
async def get_combo_animation_types():
"""获取组合动画类型列表"""
try:
animation_types = []
enum_type = CapCut_Group_animation_type if IS_CAPCUT_ENV else Group_animation_type
for name, member in enum_type.__members__.items():
animation_types.append({"name": name})
return StandardResponse(success=True, output=animation_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_transition_types", response_model=StandardResponse, tags=["资源查询"])
async def get_transition_types():
"""获取转场类型列表"""
try:
transition_types = []
enum_type = CapCut_Transition_type if IS_CAPCUT_ENV else Transition_type
for name, member in enum_type.__members__.items():
transition_types.append({"name": name})
return StandardResponse(success=True, output=transition_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_mask_types", response_model=StandardResponse, tags=["资源查询"])
async def get_mask_types():
"""获取蒙版类型列表"""
try:
mask_types = []
enum_type = CapCut_Mask_type if IS_CAPCUT_ENV else Mask_type
for name, member in enum_type.__members__.items():
mask_types.append({"name": name})
return StandardResponse(success=True, output=mask_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_audio_effect_types", response_model=StandardResponse, tags=["资源查询"])
async def get_audio_effect_types():
"""获取音效类型列表"""
try:
effect_types = []
if IS_CAPCUT_ENV:
for name, member in CapCut_Voice_filters_effect_type.__members__.items():
effect_types.append({"name": name, "type": "voice_filter"})
for name, member in CapCut_Voice_characters_effect_type.__members__.items():
effect_types.append({"name": name, "type": "voice_character"})
else:
for name, member in Tone_effect_type.__members__.items():
effect_types.append({"name": name, "type": "tone"})
for name, member in Audio_scene_effect_type.__members__.items():
effect_types.append({"name": name, "type": "scene"})
return StandardResponse(success=True, output=effect_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_font_types", response_model=StandardResponse, tags=["资源查询"])
async def get_font_types():
"""获取字体类型列表"""
try:
font_types = [{"name": name} for name, member in Font_type.__members__.items()]
return StandardResponse(success=True, output=font_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_text_intro_types", response_model=StandardResponse, tags=["资源查询"])
async def get_text_intro_types():
"""获取文字入场动画类型列表"""
try:
animation_types = []
enum_type = CapCut_Text_intro if IS_CAPCUT_ENV else Text_intro
for name, member in enum_type.__members__.items():
animation_types.append({"name": name})
return StandardResponse(success=True, output=animation_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_text_outro_types", response_model=StandardResponse, tags=["资源查询"])
async def get_text_outro_types():
"""获取文字出场动画类型列表"""
try:
animation_types = []
enum_type = CapCut_Text_outro if IS_CAPCUT_ENV else Text_outro
for name, member in enum_type.__members__.items():
animation_types.append({"name": name})
return StandardResponse(success=True, output=animation_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_text_loop_anim_types", response_model=StandardResponse, tags=["资源查询"])
async def get_text_loop_anim_types():
"""获取文字循环动画类型列表"""
try:
animation_types = []
enum_type = CapCut_Text_loop_anim if IS_CAPCUT_ENV else Text_loop_anim
for name, member in enum_type.__members__.items():
animation_types.append({"name": name})
return StandardResponse(success=True, output=animation_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_video_scene_effect_types", response_model=StandardResponse, tags=["资源查询"])
async def get_video_scene_effect_types():
"""获取场景特效类型列表"""
try:
effect_types = []
enum_type = CapCut_Video_scene_effect_type if IS_CAPCUT_ENV else Video_scene_effect_type
for name, member in enum_type.__members__.items():
effect_types.append({"name": name})
return StandardResponse(success=True, output=effect_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
@app.get("/get_video_character_effect_types", response_model=StandardResponse, tags=["资源查询"])
async def get_video_character_effect_types():
"""获取人物特效类型列表"""
try:
effect_types = []
enum_type = CapCut_Video_character_effect_type if IS_CAPCUT_ENV else Video_character_effect_type
for name, member in enum_type.__members__.items():
effect_types.append({"name": name})
return StandardResponse(success=True, output=effect_types)
except Exception as e:
return StandardResponse(success=False, error=f"Error occurred: {str(e)}")
# ==================== 启动事件 ====================
@app.on_event("startup")
async def startup_event():
"""应用启动时执行"""
print("\n" + "=" * 80)
print("📋 已注册的路由信息 / Registered Routes:")
print("=" * 80)
routes_info = []
for route in app.routes:
if hasattr(route, 'methods') and hasattr(route, 'path'):
methods = ','.join(sorted(route.methods - {'HEAD', 'OPTIONS'})) if route.methods else 'N/A'
routes_info.append({
'endpoint': route.name,
'methods': methods,
'path': route.path
})
routes_info.sort(key=lambda x: x['path'])
print(f"\n{'序号':<6} {'方法':<12} {'路径':<40} {'端点'}")
print("-" * 80)
for idx, route in enumerate(routes_info, 1):
print(f"{idx:<6} {route['methods']:<12} {route['path']:<40} {route['endpoint']}")
print("\n" + "=" * 80)
print(f"✅ 总计: {len(routes_info)} 个路由")
print(f"🚀 服务启动于: http://0.0.0.0:{PORT}")
print(f"📖 API 文档: http://0.0.0.0:{PORT}/apidocs")
print("=" * 80 + "\n")
# ==================== 主程序入口 ====================
logger.info("CapCut Mate API")
# 5. 启动
if __name__ == "__main__":
uvicorn.run(
"main:app",
host="0.0.0.0",
port=PORT,
reload=False,
log_level="info"
)
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=60000, log_config=None, log_level="info")
-47
View File
@@ -1,47 +0,0 @@
import oss2
import os
from settings.local import OSS_CONFIG, MP4_OSS_CONFIG
def upload_to_oss(path):
# Create OSS client
auth = oss2.Auth(OSS_CONFIG['access_key_id'], OSS_CONFIG['access_key_secret'])
bucket = oss2.Bucket(auth, OSS_CONFIG['endpoint'], OSS_CONFIG['bucket_name'])
# Upload file
object_name = os.path.basename(path)
bucket.put_object_from_file(object_name, path)
# Generate signed URL (valid for 24 hours)
url = bucket.sign_url('GET', object_name, 24 * 60 * 60)
# Clean up temporary file
os.remove(path)
return url
def upload_mp4_to_oss(path):
"""Special method for uploading MP4 files, using custom domain and v4 signature"""
# Directly use credentials from the configuration file
auth = oss2.AuthV4(MP4_OSS_CONFIG['access_key_id'], MP4_OSS_CONFIG['access_key_secret'])
# Create OSS client with custom domain
bucket = oss2.Bucket(
auth,
MP4_OSS_CONFIG['endpoint'],
MP4_OSS_CONFIG['bucket_name'],
region=MP4_OSS_CONFIG['region'],
is_cname=True
)
# Upload file
object_name = os.path.basename(path)
bucket.put_object_from_file(object_name, path)
# Generate pre-signed URL (valid for 24 hours), set slash_safe to True to avoid path escaping
url = bucket.sign_url('GET', object_name, 24 * 60 * 60, slash_safe=True)
# Clean up temporary file
os.remove(path)
return url
File diff suppressed because one or more lines are too long
-626
View File
@@ -1,626 +0,0 @@
import requests
import json
from flask import Flask, request, jsonify, Response
import sys
import time
import json
sys.path.append('/Users/sunguannan/capcutapi')
from example import add_image_impl
PORT=9001 #端口
BASE_URL = f"http://localhost:{PORT}"
draft_folder = "/Users/sunguannan/Movies/JianyingPro/User Data/Projects/com.lveditor.draft"
def make_request(endpoint, data, method='POST'):
"""Send HTTP request to the server and handle the response"""
url = f"{BASE_URL}/{endpoint}"
headers = {'Content-Type': 'application/json'}
try:
if method == 'POST':
response = requests.post(url, data=json.dumps(data), headers=headers)
elif method == 'GET':
response = requests.get(url, params=data, headers=headers)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status() # Raise an exception if the request fails
return response.json()
except requests.exceptions.RequestException as e:
print(f"Request error: {e}")
sys.exit(1)
except json.JSONDecodeError:
print("Unable to parse server response")
sys.exit(1)
def save_draft_impl(draft_id, draft_folder):
"""API wrapper for save_draft service"""
data = {
"draft_id": draft_id,
"draft_folder": draft_folder
}
return make_request("save_draft", data)
def query_script_impl(draft_id):
"""API wrapper for query_script service"""
data = {
"draft_id": draft_id
}
return make_request("query_script", data)
def add_text_impl(text, start, end, font, font_color, font_size, track_name, draft_folder="123", draft_id=None,
vertical=False, transform_x=0, transform_y=0, font_alpha=1.0,
border_color=None, border_width=0.0, border_alpha=1.0,
background_color=None, background_alpha=1.0, background_style=None,
background_round_radius=0.0, background_height=0.14, background_width=0.14,
background_horizontal_offset=0.5, background_vertical_offset=0.5,
shadow_enabled=False, shadow_alpha=0.9, shadow_angle=-45.0,
shadow_color="#000000", shadow_distance=5.0, shadow_smoothing=0.15,
bubble_effect_id=None, bubble_resource_id=None,
effect_effect_id=None,
intro_animation=None, intro_duration=0.5,
outro_animation=None, outro_duration=0.5,
width=1080, height=1920,
fixed_width=-1, fixed_height=-1,
text_styles=None):
"""Add text with support for multiple styles, shadows, and backgrounds"""
data = {
"draft_folder": draft_folder,
"text": text,
"start": start,
"end": end,
"font": font,
"font_color": font_color,
"font_size": font_size,
"alpha": font_alpha,
"track_name": track_name,
"vertical": vertical,
"transform_x": transform_x,
"transform_y": transform_y
}
# Add border parameters
if border_color:
data["border_color"] = border_color
data["border_width"] = border_width
data["border_alpha"] = border_alpha
# Add background parameters
if background_color:
data["background_color"] = background_color
data["background_alpha"] = background_alpha
if background_style:
data["background_style"] = background_style
data["background_round_radius"] = background_round_radius
data["background_height"] = background_height
data["background_width"] = background_width
data["background_horizontal_offset"] = background_horizontal_offset
data["background_vertical_offset"] = background_vertical_offset
# Add shadow parameters
if shadow_enabled:
data["shadow_enabled"] = shadow_enabled
data["shadow_alpha"] = shadow_alpha
data["shadow_angle"] = shadow_angle
data["shadow_color"] = shadow_color
data["shadow_distance"] = shadow_distance
data["shadow_smoothing"] = shadow_smoothing
# Add bubble effect parameters
if bubble_effect_id:
data["bubble_effect_id"] = bubble_effect_id
if bubble_resource_id:
data["bubble_resource_id"] = bubble_resource_id
# Add text effect parameters
if effect_effect_id:
data["effect_effect_id"] = effect_effect_id
# Add intro animation parameters
if intro_animation:
data["intro_animation"] = intro_animation
data["intro_duration"] = intro_duration
# Add outro animation parameters
if outro_animation:
data["outro_animation"] = outro_animation
data["outro_duration"] = outro_duration
# Add size parameters
data["width"] = width
data["height"] = height
# Add fixed size parameters
if fixed_width > 0:
data["fixed_width"] = fixed_width
if fixed_height > 0:
data["fixed_height"] = fixed_height
if draft_id:
data["draft_id"] = draft_id
# Add text styles parameters
if text_styles:
data["text_styles"] = text_styles
if draft_id:
data["draft_id"] = draft_id
return make_request("add_text", data)
def group_sentences(corrected_srt, threshold=1.0):
"""按时间间隔分句"""
if not corrected_srt:
return []
sentences = []
current_sentence = [corrected_srt[0]]
for i in range(1, len(corrected_srt)):
prev_end = corrected_srt[i-1]["end"]
curr_start = corrected_srt[i]["start"]
if curr_start - prev_end > threshold:
sentences.append(current_sentence)
current_sentence = [corrected_srt[i]]
else:
current_sentence.append(corrected_srt[i])
sentences.append(current_sentence)
return sentences
def adjust_sentence_timing(sentences, gap_adjust=1, time_precision=3):
"""调整句子间的时间间隔,并保留原始时间"""
def round_time(t):
return round(t, time_precision) if time_precision is not None else t
adjusted_sentences = []
total_offset = 0.0
prev_end = sentences[0][-1]["end"]
# 第一句保持原时间
first_sentence = [
{
"word": w["word"],
"start": w["start"],
"end": w["end"],
"original_start": w["start"],
"original_end": w["end"]
}
for w in sentences[0]
]
adjusted_sentences.append(first_sentence)
for i in range(1, len(sentences)):
sentence = sentences[i]
curr_start = sentence[0]["start"]
natural_gap = curr_start - prev_end
adjusted_gap = natural_gap if gap_adjust == 0 else (1.0 if natural_gap > 1.0 else natural_gap)
move_amount = natural_gap - adjusted_gap
total_offset += move_amount
adjusted_sentence = []
for w in sentence:
adjusted_sentence.append({
"word": w["word"],
"start": round_time(w["start"] - total_offset),
"end": round_time(w["end"] - total_offset),
"original_start": w["start"],
"original_end": w["end"]
})
adjusted_sentences.append(adjusted_sentence)
prev_end = sentence[-1]["end"]
return adjusted_sentences
def split_into_paragraphs(sentence, max_words=5, max_chunk_duration=1.5):
"""把句子按词数和时长分段"""
paragraphs = []
i = 0
n = len(sentence)
while i < n:
paragraph = [sentence[i]]
current_start = sentence[i]["start"]
current_end = sentence[i]["end"]
i += 1
while i < n:
current_word = sentence[i]
is_continuous = abs(current_word["start"] - current_end) < 0.001
if (len(paragraph) >= max_words or
(current_word["end"] - current_start) >= max_chunk_duration or
not is_continuous):
break
paragraph.append(current_word)
current_end = current_word["end"]
i += 1
paragraphs.append(paragraph)
return paragraphs
def build_segments_by_mode(
mode,
paragraph,
track_name,
font,
font_size,
highlight_color,
normal_color,
transform_x,
transform_y,
fixed_width,
shadow_enabled,
shadow_color,
border_color,
border_width,
border_alpha,
background_color,
):
"""根据模式生成字幕片段"""
segments = []
#print("二级代码返回调试fx", fixed_width)
if mode == "word_pop":
# 单词跳出
for w in paragraph:
text_styles = []
word_count = len(w["word"].replace(" ", "")) #统计有多少个字
text_styles.append({
"start": 0,
"end": word_count,
"border": {
"alpha": border_alpha,
"color": border_color,
"width": border_width
}
})
segments.append({
"text": w["word"],
"start": w["start"],
"end": w["end"],
"font": font,
"track_name": track_name,
"font_color": normal_color,
"font_size": font_size,
"transform_x": transform_x,
"transform_y": transform_y,
"shadow_enabled": shadow_enabled,
"fixed_width": fixed_width,
"text_styles": text_styles,
"shadow_color": shadow_color,
"border_color": border_color,
"border_width": border_width,
"border_alpha": border_alpha,
"background_color": background_color,
})
elif mode == "word_highlight":
# 单词高亮:当前词亮,其他灰
paragraph_text = " ".join(w["word"] for w in paragraph)
offsets = []
ci = 0
for w in paragraph:
offsets.append((ci, ci + len(w["word"])))
ci += len(w["word"]) + 1
for idx, w in enumerate(paragraph):
text_styles = []
for k, (s, e) in enumerate(offsets):
color = highlight_color if k == idx else normal_color
text_styles.append({
"start": s,
"end": e,
"style": {
"color": color,
"size": font_size,
},
"border": {
"alpha": border_alpha,
"color": border_color,
"width": border_width
}
})
print("text_styles", text_styles)
segments.append({
"text": paragraph_text,
"start": w["start"],
"end": w["end"],
"font": font,
"track_name": track_name,
"font_color": normal_color,
"font_size": font_size,
"text_styles": text_styles,
"transform_x": transform_x,
"transform_y": transform_y,
"shadow_enabled": shadow_enabled,
"fixed_width": fixed_width,
"shadow_color": shadow_color,
"border_color": border_color,
"border_width": border_width,
"border_alpha": border_alpha,
"background_color": background_color,
})
elif mode == "sentence_fade":
# 句子渐显:已亮过的词继续保持亮
paragraph_text = " ".join(w["word"] for w in paragraph)
offsets = []
ci = 0
for w in paragraph:
offsets.append((ci, ci + len(w["word"])))
ci += len(w["word"]) + 1
for idx, w in enumerate(paragraph):
text_styles = []
for k, (s, e) in enumerate(offsets):
color = highlight_color if k <= idx else normal_color
text_styles.append({
"start": s,
"end": e,
"style": {"color": color, "size": font_size},
"border": {
"alpha": border_alpha,
"color": border_color,
"width": border_width
}
})
segments.append({
"text": paragraph_text,
"start": w["start"],
"end": w["end"],
"font": font,
"track_name": track_name,
"font_color": normal_color,
"font_size": font_size,
"text_styles": text_styles,
"transform_x": transform_x,
"transform_y": transform_y,
"shadow_enabled": shadow_enabled,
"fixed_width": fixed_width,
"shadow_color": shadow_color,
"border_color": border_color,
"border_width": border_width,
"border_alpha": border_alpha,
"background_color": background_color,
})
elif mode == "sentence_pop":
# 句子跳出
text = " ".join(w["word"] for w in paragraph)
start_time = paragraph[0]["start"]
end_time = paragraph[-1]["end"]
text_styles = []
word_count = len(text.replace(" ", "")) #统计有多少个字
text_styles.append({
"start": 0,
"end": word_count,
"border": {
"alpha": border_alpha,
"color": border_color,
"width": border_width
}
})
segments.append({
"text": text,
"start": start_time,
"end": end_time,
"font": font,
"track_name": track_name,
"font_color": normal_color,
"font_size": font_size,
"transform_x": transform_x,
"transform_y": transform_y,
"shadow_enabled": shadow_enabled,
"fixed_width": fixed_width,
"text_styles": text_styles,
"shadow_color": shadow_color,
"border_color": border_color,
"border_width": border_width,
"border_alpha": border_alpha,
"background_color": background_color,
})
else:
raise ValueError(f"未知模式: {mode}")
"""segments.append({
"file_name": file_name,
})"""
return segments
corrected_srt = [{
"word": "Hello",
"start": 0.0,
"end": 0.64,
"confidence": 0.93917525
},
{
"word": "I'm",
"start": 0.64,
"end": 0.79999995,
"confidence": 0.9976464
},
{
"word": "PAWA",
"start": 0.79999995,
"end": 1.36,
"confidence": 0.6848311
},
{
"word": "Nice",
"start": 1.36,
"end": 1.52,
"confidence": 0.9850389
},
{
"word": "To",
"start": 1.52,
"end": 1.68,
"confidence": 0.9926886
},
{
"word": "Meet",
"start": 1.68,
"end": 2.08,
"confidence": 0.9972697
},
{
"word": "You",
"start": 2.08,
"end": 2.72,
"confidence": 0.9845563
},
{
"word": "Enjoy",
"start": 2.72,
"end": 3.04,
"confidence": 0.99794894
},
{
"word": "My",
"start": 3.04,
"end": 3.1999998,
"confidence": 0.9970203
},
{
"word": "Parttern",
"start": 3.1999998,
"end": 3.36,
"confidence": 0.9970235
},
{
"word": "Thank",
"start": 3.36,
"end": 3.6799998,
"confidence": 0.98627764
},
{
"word": "You",
"start": 3.6799998,
"end": 4.0,
"confidence": 0.9939551
},
]
def add_koubo_from_srt(
corrected_srt,
track_name,
mode="word_pop",
font="ZY_Modern",
font_size=32,
highlight_color="#FFD700",
normal_color="#AAAAAA", max_chunk_duration=1.5, max_words=5,
gap_adjust=1,
time_precision=3,
transform_x=0.5,
transform_y=0.3,
fixed_width=-1,
shadow_enabled=True,
shadow_color="#000000",
border_color="#000000",
border_width=0.5,
border_alpha=1.0,
background_color="#000000",
):
"""统一入口:根据 mode 选择字幕效果"""
sentences = group_sentences(corrected_srt)
adjusted_sentences = adjust_sentence_timing(sentences, gap_adjust, time_precision)
all_paragraphs = [split_into_paragraphs(s, max_words, max_chunk_duration) for s in adjusted_sentences]
draft_id_ret = None
for sentence_paragraphs in all_paragraphs:
for paragraph in sentence_paragraphs:
segments = build_segments_by_mode(
mode,
paragraph,
track_name,
font,
font_size,
highlight_color,
normal_color,
transform_x,
transform_y,
fixed_width,
shadow_enabled,
shadow_color,
border_color,
border_width,
border_alpha,
background_color,
)
#print("segments", segments)
for seg in segments:
#print("二级代码返回调试fx", seg)
if draft_id_ret:
seg["draft_id"] = draft_id_ret
print("seg", seg)
res = add_text_impl(**seg)
if draft_id_ret is None and isinstance(res, dict):
try:
draft_id_ret = res["output"]["draft_id"]
except:
pass
return draft_id_ret
colors = {
"shadow_color": "#000000",
"border_color": "#FFD700",
"background_color": "#000000",
"normal_color": "#FFFFFF",
"highlight_color": "#DA70D6" # 紫色
}
draft_id = add_koubo_from_srt(
corrected_srt,
track_name="main_text",
font_size=15,
gap_adjust=0,
transform_x=0,
transform_y=-0.45,# 0=保持原间隔,1=调整>1s的间隔
fixed_width = 0.6,
mode="word_highlight",
shadow_enabled=True,
border_width=10,
border_alpha=1.0,
**colors,
font="ZY_Modern", #设置自己的字体,需要在字体库中添加
)
add_image_impl(image_url="https://pic1.imgdb.cn/item/689aff2758cb8da5c81e64a2.png", start = 0, end = 4, draft_id=draft_id)
save_result = save_draft_impl(draft_id, draft_folder)
print(save_result)
"""
# 单词高亮
mode="word_highlight"
# 单词跳出
mode="word_pop"
# 句子渐显
mode="sentence_fade"
# 句子跳出
mode="sentence_pop"
"""
-606
View File
@@ -1,606 +0,0 @@
import json
import random
import requests
# Set API keys
QWEN_API_KEY = "your qwen api key"
PEXELS_API_KEY = "your pexels api key"
CAPCUT_API_KEY = "your capcut api key"
LICENSE_KEY="your capcut license key",
def llm(query = ""):
"""
Call the Tongyi Qianwen large language model
Parameters:
Returns:
dict: Dictionary containing title and list of sentences
"""
# Build system prompt
system_prompt = """
* **Context:** You are an AI expert specializing in modern interpersonal relationships and emotional communication. Your knowledge base is built on a deep understanding of popular emotional content on social media, and you excel at interpreting the dynamics and perspectives of relationships in a relaxed, colloquial style.
* **Objective:** When the user inputs "Give me some random returns", your goal is to **randomly create** advice about male-female emotions, behavioral habits, or relationship guidance. Your content must strictly mimic the unique style shown in the examples below.
* **Style:** Your generated content should have the following characteristics:
* **Structure:** Use a list format, with each point being a short, independent sentence.
* **Wording:** Use colloquial language, often using the "When..." sentence pattern to describe a scenario.
* **Theme:** Content should revolve around "how to understand the other person", "which behaviors are attractive", or "advice for a specific gender".
* **Tone:** Your tone should be friendly, sincere, slightly teasing, like a friend sharing experiences on social media.
* **Audience:** Your audience is anyone interested in modern emotional relationships who wants to get advice in a relaxed way.
* **Response:** When you receive the instruction "Give me some random returns", please **randomly select one** from the following examples as your response. Or, you can **randomly generate** a new one with a completely consistent style, and return it in the same JSON format:
**Example 1 (How to understand girls):**
```json
{
"title": "How to understand girls",
"sentences": [
"Hands on her stomach (Insecure)",
"She leans on you (Feels safe)",
"Covers her smile (Thinks your going to judge)",
"Stops texting you (Feels like she is annoying you)",
"Says she is fine (She is everything but fine)",
"When she hugs you (You mean a lot to her)"
]
}
```
**Example 2 (Tips for girls):**
```json
{
"title": "Tips for the girls (From the guys)",
"sentences": [
"99/100 guys dont know what hip dips are and actually love your stretch marks",
"We can't tell that you like us by just viewing our story, just message us",
"When he's out with his boys, let him have this time (this is very important)",
"'I'm not ready for a relationship' - unless your the luckiest girl in the world your not getting cuffed",
"As Bruno mars said, 'your perfect just the way you are' so just be you, it'll work"
]
}
```
**Example 3 (Things guys find attractive in girls):**
```json
{
"title": "Things girls do that guys find attractive",
"sentences": [
"Bed hair when it's all messy >>>",
"When you come work out with us",
"Your sleepy voice in the morning or after a nap",
"When you wear our t-shirts as pyjamas",
"When you have a funny or really bad laugh",
"When you initiate ...",
"When your good with animals or animals like you"
]
}
```
"""
# Build user prompt
user_prompt = f"Randomly create advice about male-female emotions, behavioral habits, or relationship guidance, based on user input: {query}"
# Prepare request data
url = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
headers = {
"Authorization": f"Bearer {QWEN_API_KEY}",
"Content-Type": "application/json"
}
data = {
"model": "qwen-plus",
"messages": [
{
"role": "system",
"content": system_prompt
},
{
"role": "user",
"content": user_prompt
}
],
"temperature": 0.7,
"max_tokens": 16384,
"response_format": {"type": "json_object"}
}
try:
# Send HTTP request
response = requests.post(url, headers=headers, json=data, timeout=30)
# Check response status
if response.status_code == 200:
response_data = response.json()
# Extract content from response
if 'choices' in response_data and len(response_data['choices']) > 0:
content = response_data['choices'][0]['message']['content']
try:
# Parse JSON response
result = json.loads(content)
# Ensure result contains necessary fields
if "title" in result and "sentences" in result:
return result
except json.JSONDecodeError:
pass # If JSON parsing fails, will return predefined example
# If API call fails or parsing fails, print error message
print(f"Error: {response.status_code}, {response.text if hasattr(response, 'text') else 'No response text'}")
except Exception as e:
# Catch all possible exceptions
print(f"Exception occurred: {str(e)}")
def search_pexels_videos(query="twilight", min_duration=10, orientation="portrait", per_page=15):
"""
Call Pexels API to search for videos
Parameters:
query (str): Search keyword, default is "twilight"
min_duration (int): Minimum video duration (seconds), default is 10 seconds
orientation (str): Video orientation, default is "portrait"
per_page (int): Number of results per page, default is 15
Returns:
list: List containing video information
"""
url = "https://api.pexels.com/videos/search"
headers = {
"Authorization": PEXELS_API_KEY
}
params = {
"query": query,
"orientation": orientation,
"per_page": per_page,
"min_duration": min_duration
}
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
videos = []
for video in data.get("videos", []):
# Get video file information
video_files = video.get("video_files", [])
# Filter out 16:9 ratio video files
portrait_videos = [file for file in video_files
if file.get("width") and file.get("height") and
file.get("height") / file.get("width") > 1.7] # Close to 16:9 ratio
if portrait_videos:
# Select highest quality video file
best_quality = max(portrait_videos, key=lambda x: x.get("width", 0) * x.get("height", 0))
videos.append({
"id": video.get("id"),
"url": video.get("url"),
"image": video.get("image"),
"duration": video.get("duration"),
"user": video.get("user", {}).get("name"),
"video_url": best_quality.get("link"),
"width": best_quality.get("width"),
"height": best_quality.get("height"),
"file_type": best_quality.get("file_type")
})
if videos:
random_video = random.choice(videos)
return random_video['video_url']
return []
else:
print(f"Error: {response.status_code}, {response.text}")
return []
except Exception as e:
print(f"Exception occurred: {str(e)}")
return []
def create_capcut_draft(width=1080, height=1920):
"""
Call CapCut API to create a new draft
Parameters:
width (int): Video width, default is 1080
height (int): Video height, default is 1920
Returns:
dict: Dictionary containing draft ID and download URL, or error message if failed
"""
url = "https://open.capcutapi.top/cut_jianying/create_draft"
headers = {
"Authorization": f"Bearer {CAPCUT_API_KEY}",
"Content-Type": "application/json"
}
data = {
"width": width,
"height": height
}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
result = response.json()
if result.get("success"):
return {
"success": True,
"draft_id": result.get("output", {}).get("draft_id"),
"draft_url": result.get("output", {}).get("draft_url")
}
else:
return {
"success": False,
"error": result.get("error", "Unknown error")
}
else:
return {
"success": False,
"error": f"HTTP Error: {response.status_code}",
"response": response.text
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def add_video_to_draft(draft_id, video_url):
"""
Call CapCut API to add video to draft
Parameters:
draft_id (str): Draft ID
video_url (str): Video URL
Returns:
dict: Dictionary containing draft ID and download URL, or error message if failed
"""
url = "https://open.capcutapi.top/cut_jianying/add_video"
headers = {
"Authorization": f"Bearer {CAPCUT_API_KEY}",
"Content-Type": "application/json"
}
data = {
"video_url": video_url,
"draft_id": draft_id,
"end": 10 # Set video duration to 10 seconds
}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
result = response.json()
if result.get("success"):
return {
"success": True,
"draft_id": result.get("output", {}).get("draft_id"),
"draft_url": result.get("output", {}).get("draft_url")
}
else:
return {
"success": False,
"error": result.get("error", "Unknown error")
}
else:
return {
"success": False,
"error": f"HTTP Error: {response.status_code}",
"response": response.text
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def add_text_to_draft(draft_id, text, font="ZY_Starry",
font_color="#FFFFFF",
background_color="#000000",
background_alpha=0.5,
background_style=2,
background_round_radius=10,
transform_y=0,
transform_x=0,
font_size=10.0,
fixed_width=0.6,
track_name="text_main"):
"""
Call CapCut API to add text to draft
Parameters:
draft_id (str): Draft ID
text (str): Text content
start_time (float): Text start time on timeline (seconds), default is 0
end_time (float): Text end time on timeline (seconds), default is 5
font (str): Font, default is "ZY_Starry"
font_color (str): Font color, default is white
background_color (str): Background color, default is black
background_alpha (float): Background transparency, default is 0.5
transform_y (float): Y-axis position offset, default is 0
transform_x (float): X-axis position offset, default is 0
font_size (float): Font size, default is 10.0
Returns:
dict: Dictionary containing draft ID and download URL, or error message if failed
"""
url = "https://open.capcutapi.top/cut_jianying/add_text"
headers = {
"Authorization": f"Bearer {CAPCUT_API_KEY}",
"Content-Type": "application/json"
}
data = {
"text": text,
"start": 0,
"end": 10,
"draft_id": draft_id,
"font": font,
"font_color": font_color,
"font_size": font_size,
"transform_y": transform_y,
"transform_x": transform_x,
"fixed_width": fixed_width,
"background_color": background_color,
"background_alpha": background_alpha,
"background_style": background_style,
"background_round_radius": background_round_radius,
"track_name": track_name
}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
result = response.json()
if result.get("success"):
return {
"success": True,
"draft_id": result.get("output", {}).get("draft_id"),
"draft_url": result.get("output", {}).get("draft_url")
}
else:
return {
"success": False,
"error": result.get("error", "Unknown error")
}
else:
return {
"success": False,
"error": f"HTTP Error: {response.status_code}",
"response": response.text
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def generate_video(draft_id, resolution="720P", framerate="24"):
"""
Call CapCut API to render video
Parameters:
draft_id (str): Draft ID
license_key (str): License key
resolution (str): Video resolution, default is "720P"
framerate (str): Video frame rate, default is "24"
Returns:
dict: Dictionary containing task ID, or error message if failed
"""
url = "https://open.capcutapi.top/cut_jianying/generate_video"
headers = {
"Authorization": f"Bearer {CAPCUT_API_KEY}",
"Content-Type": "application/json"
}
data = {
"draft_id": draft_id,
"license_key": LICENSE_KEY,
"resolution": resolution,
"framerate": framerate
}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
result = response.json()
if result.get("success"):
return {
"success": True,
"task_id": result.get("output", {}).get("task_id")
}
else:
return {
"success": False,
"error": result.get("error", "Unknown error")
}
else:
return {
"success": False,
"error": f"HTTP Error: {response.status_code}",
"response": response.text
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def check_task_status(task_id):
"""
Call CapCut API to check task status
Parameters:
task_id (str): Task ID
Returns:
dict: Dictionary containing task status and results, or error message if failed
"""
url = "https://open.capcutapi.top/cut_jianying/task_status"
headers = {
"Authorization": f"Bearer {CAPCUT_API_KEY}",
"Content-Type": "application/json"
}
data = {
"task_id": task_id
}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
result = response.json()
if result.get("success"):
output = result.get("output", {})
return {
"success": True,
"status": output.get("status"),
"progress": output.get("progress"),
"result": output.get("result"), # Video URL
"error": output.get("error")
}
else:
return {
"success": False,
"error": result.get("error", "Unknown error")
}
else:
return {
"success": False,
"error": f"HTTP Error: {response.status_code}",
"response": response.text
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
# Example usage
if __name__ == "__main__":
# Call LLM function and print result
result = llm()
print(json.dumps(result, indent=2, ensure_ascii=False))
# 1. Create draft
draft_result = create_capcut_draft()
print("Draft creation result:", json.dumps(draft_result, indent=2, ensure_ascii=False))
if draft_result.get("success"):
draft_id = draft_result.get("draft_id")
# 2. Search Pexels videos
video_url = search_pexels_videos()
print("Pexels video URL:", video_url)
# 3. Add video to draft
if video_url:
add_result = add_video_to_draft(draft_result.get("draft_id"), video_url)
print("Add video result:", json.dumps(add_result, indent=2, ensure_ascii=False))
# 5. Add title text
title_result = add_text_to_draft(
draft_id=draft_id,
text=result["title"],
font="ZY_Starry", # Use starry font
font_color="#FFFFFF", # White font
background_color="#000000", # Black background
background_alpha=1, # Background transparency
background_style=1,
background_round_radius=10,
transform_y=0.7, # Located at the top of the screen (1 is top edge, -1 is bottom edge)
transform_x=0, # Horizontally centered
font_size=13.0, # Larger font
track_name = "title",
fixed_width=0.6
)
print("Add title result:", json.dumps(title_result, indent=2, ensure_ascii=False))
# 6. Add sentence text
sentence_count = len(result["sentences"])
for i, sentence in enumerate(result["sentences"]):
# Calculate vertical position - evenly distributed in the middle of the screen
transform_y = 0.5 - (1.1 * (i + 1) / (sentence_count + 1))
# Determine horizontal alignment - odd sentences left-aligned, even sentences right-aligned
if i % 2 == 0: # Odd sentences (counting from 0)
transform_x = -0.5 # Left-aligned
else: # Even sentences
transform_x = 0.5 # Right-aligned
sentence_result = add_text_to_draft(
draft_id=draft_id,
text=sentence,
font="ZY_Fantasy", # Use fantasy font
font_color="#FFFFFF", # White font
transform_y=transform_y, # Vertical position
transform_x=transform_x, # Horizontal position (left-right alignment)
background_alpha=0,
font_size=7.0, # Smaller font
fixed_width=0.3,
track_name=f"text_{i}"
)
print(f"Add sentence {i+1} result:", json.dumps(sentence_result, indent=2, ensure_ascii=False))
# 7. Render video
print("\nStarting video rendering...")
generate_result = generate_video(draft_id)
print("Video rendering request result:", json.dumps(generate_result, indent=2, ensure_ascii=False))
if generate_result.get("success"):
task_id = generate_result.get("task_id")
print(f"Task ID: {task_id}, starting to poll task status...")
# 8. Poll task status
import time
max_attempts = 30 # Maximum 30 polling attempts
attempt = 0
while attempt < max_attempts:
status_result = check_task_status(task_id)
print(f"Poll count {attempt+1}, status:", json.dumps(status_result, indent=2, ensure_ascii=False))
if not status_result.get("success"):
print("Failed to check task status:", status_result.get("error"))
break
status = status_result.get("status")
if status == "SUCCESS":
print("\nVideo rendering successful!")
print("Video URL:", status_result.get("result"))
break
elif status == "FAILED":
print("\nVideo rendering failed:", status_result.get("error"))
break
# Wait 5 seconds before checking again
print("Waiting 5 seconds before checking again...")
time.sleep(5)
attempt += 1
if attempt >= max_attempts:
print("\nPolling timeout, please check task status manually later")
-13
View File
@@ -1,13 +0,0 @@
# Pattern Gallery
## 001-words.py
[source](001-words.py)
[![Words](https://img.youtube.com/vi/HLSHaJuNtBw/hqdefault.jpg)](https://www.youtube.com/watch?v=HLSHaJuNtBw)
## 002-relationship.py
[source](002-relationship.py)
[![Relationship](https://img.youtube.com/vi/f2Q1OI_SQZo/hqdefault.jpg)](https://www.youtube.com/watch?v=f2Q1OI_SQZo)
-84
View File
@@ -1,84 +0,0 @@
from .local_materials import Crop_settings, Video_material, Audio_material
from .keyframe import Keyframe_property
from .time_util import Timerange
from .audio_segment import Audio_segment
from .video_segment import Video_segment, Sticker_segment, Clip_settings
from .effect_segment import Effect_segment, Filter_segment
from .text_segment import Text_segment, Text_style, Text_border, Text_background, Text_shadow
from .metadata import Font_type
from .metadata import Mask_type
from .metadata import CapCut_Mask_type
from .metadata import Transition_type, Filter_type
from .metadata import CapCut_Transition_type
from .metadata import Intro_type, Outro_type, Group_animation_type
from .metadata import CapCut_Intro_type, CapCut_Outro_type, CapCut_Group_animation_type
from .metadata import Text_intro, Text_outro, Text_loop_anim
from .metadata import CapCut_Text_intro, CapCut_Text_outro, CapCut_Text_loop_anim
from .metadata import Audio_scene_effect_type, Tone_effect_type, Speech_to_song_type
from .metadata import CapCut_Voice_filters_effect_type, CapCut_Voice_characters_effect_type, CapCut_Speech_to_song_effect_type
from .metadata import Video_scene_effect_type, Video_character_effect_type
from .metadata import CapCut_Video_scene_effect_type, CapCut_Video_character_effect_type
from .track import Track_type
from .template_mode import Shrink_mode, Extend_mode
from .script_file import Script_file
from .draft_folder import Draft_folder
from .time_util import SEC, tim, trange
__all__ = [
"Font_type",
"Mask_type",
"CapCut_Mask_type",
"Filter_type",
"Transition_type",
"CapCut_Transition_type",
"Intro_type",
"Outro_type",
"Group_animation_type",
"CapCut_Intro_type",
"CapCut_Outro_type",
"CapCut_Group_animation_type",
"Text_intro",
"Text_outro",
"Text_loop_anim",
"CapCut_Text_intro",
"CapCut_Text_outro",
"CapCut_Text_loop_anim",
"Audio_scene_effect_type",
"Tone_effect_type",
"Speech_to_song_type",
"Video_scene_effect_type",
"Video_character_effect_type",
"CapCut_Voice_filters_effect_type",
"CapCut_Voice_characters_effect_type",
"CapCut_Speech_to_song_effect_type",
"CapCut_Video_scene_effect_type",
"CapCut_Video_character_effect_type",
"Crop_settings",
"Video_material",
"Audio_material",
"Keyframe_property",
"Timerange",
"Audio_segment",
"Video_segment",
"Sticker_segment",
"Clip_settings",
"Effect_segment",
"Filter_segment",
"Text_segment",
"Text_style",
"Text_border",
"Text_background",
"Text_shadow",
"Track_type",
"Shrink_mode",
"Extend_mode",
"Script_file",
"Draft_folder",
"SEC",
"tim",
"trange"
]
-443
View File
@@ -1,443 +0,0 @@
"""剪映自动化控制,主要与自动导出有关"""
import time
import shutil
from process_controller import ProcessController
import uiautomation as uia
import re
import os
from logging.handlers import RotatingFileHandler
import logging # 引入 logging 模块
from enum import Enum
from typing import Optional, Literal, Callable
from . import exceptions
from .exceptions import AutomationError
# --- 配置日志记录器 ---
logger = logging.getLogger('flask_video_generator') # 为您的Flask应用定义一个特定的logger名称
logger.setLevel(logging.INFO) # 设置最低记录级别
# 创建一个格式化器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 创建一个控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# 创建一个文件处理器,并设置文件轮换
log_dir = 'logs' # 定义日志文件存放的目录
if not os.path.exists(log_dir):
os.makedirs(log_dir)
log_file_path = os.path.join(log_dir, 'flask_video_generator.log') # 日志文件名
file_handler = RotatingFileHandler(log_file_path, backupCount=5, encoding='utf-8') # 5MB per file, keep 5 backups
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.info("Flask 应用日志系统初始化完成。")
class Export_resolution(Enum):
"""导出分辨率"""
RES_4K = "4K"
RES_2K = "2K"
RES_1080P = "1080P"
RES_720P = "720P"
RES_480P = "480P"
class Export_framerate(Enum):
"""导出帧率"""
FR_24 = "24fps"
FR_25 = "25fps"
FR_30 = "30fps"
FR_50 = "50fps"
FR_60 = "60fps"
class ControlFinder:
"""控件查找器,封装部分与控件查找相关的逻辑"""
@staticmethod
def desc_matcher(target_desc: str, depth: int = 2, exact: bool = False) -> Callable[[uia.Control, int], bool]:
"""根据full_description查找控件的匹配器"""
target_desc = target_desc.lower()
def matcher(control: uia.Control, _depth: int) -> bool:
if _depth != depth:
return False
full_desc: str = control.GetPropertyValue(30159).lower()
return (target_desc == full_desc) if exact else (target_desc in full_desc)
return matcher
@staticmethod
def class_name_matcher(class_name: str, depth: int = 1, exact: bool = False) -> Callable[[uia.Control, int], bool]:
"""根据ClassName查找控件的匹配器"""
class_name = class_name.lower()
def matcher(control: uia.Control, _depth: int) -> bool:
if _depth != depth:
return False
curr_class_name: str = control.ClassName.lower()
return (class_name == curr_class_name) if exact else (class_name in curr_class_name)
return matcher
class Jianying_controller:
"""剪映控制器"""
app: uia.WindowControl
"""剪映窗口"""
app_status: Literal["home", "edit", "pre_export"]
export_progress: dict = {"status": "idle", "percent": 0.0, "message": "", "start_time": 0}
"""导出进度信息"""
def __init__(self):
"""初始化剪映控制器, 此时剪映应该处于目录页"""
logger.info("Initializing Jianying_controller...")
self.get_window()
self.export_progress = {"status": "idle", "percent": 0.0, "message": "", "start_time": 0}
logger.info("Jianying_controller initialized successfully.")
def get_export_progress(self) -> dict:
"""获取当前导出进度
Returns:
dict: 包含以下字段的字典
- status: 当前状态,可能的值有 "idle"(空闲), "exporting"(导出中), "finished"(已完成), "error"(出错)
- percent: 导出进度百分比,0-100的浮点数
- message: 进度消息
- start_time: 开始导出的时间戳
- elapsed: 已经过的时间(秒)
"""
if self.export_progress["status"] != "idle":
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
return self.export_progress
def export_draft(self, draft_name: str, output_path: Optional[str] = None, *,
resolution: Optional[Export_resolution] = None,
framerate: Optional[Export_framerate] = None,
timeout: float = 1200) -> None:
"""导出指定的剪映草稿, **目前仅支持剪映6及以下版本**
**注意: 需要确认有导出草稿的权限(不使用VIP功能或已开通VIP), 否则可能陷入死循环**
Args:
draft_name (`str`): 要导出的剪映草稿名称
output_path (`str`, optional): 导出路径, 支持指向文件夹或直接指向文件, 不指定则使用剪映默认路径.
resolution (`Export_resolution`, optional): 导出分辨率, 默认不改变剪映导出窗口中的设置.
framerate (`Export_framerate`, optional): 导出帧率, 默认不改变剪映导出窗口中的设置.
timeout (`float`, optional): 导出超时时间(秒), 默认为20分钟.
Raises:
`DraftNotFound`: 未找到指定名称的剪映草稿
`AutomationError`: 剪映操作失败
"""
logger.info(f"Starting export for draft: '{draft_name}' to '{output_path or 'default path'}' with resolution: {resolution}, framerate: {framerate}")
self.export_progress["status"] = "exporting"
self.export_progress["percent"] = 0.0
self.export_progress["message"] = "开始导出"
self.export_progress["start_time"] = time.time()
self.export_progress["elapsed"] = 0
logger.info("Attempting to switch to home page.")
self.get_window()
self.switch_to_home()
logger.info("Successfully switched to home page.")
self.export_progress["status"] = "exporting"
self.export_progress["percent"] = 5.0
self.export_progress["message"] = "正在导出"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
logger.info(f"Clicking draft: '{draft_name}'")
# 点击对应草稿
draft_name_text = self.app.TextControl(
searchDepth=2,
Compare=ControlFinder.desc_matcher(f"HomePageDraftTitle:{draft_name}", exact=True)
)
if not draft_name_text.Exists(0):
error_msg = f"DraftNotFound: No Jianying draft named '{draft_name}' found."
logger.error(error_msg)
self.export_progress["status"] = "error"
self.export_progress["percent"] = 100.0
self.export_progress["message"] = f"未找到名为{draft_name}的剪映草稿"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
raise exceptions.DraftNotFound(f"未找到名为{draft_name}的剪映草稿")
draft_btn = draft_name_text.GetParentControl()
if draft_btn is None:
error_msg = f"AutomationError: Could not find parent control for draft title '{draft_name}'."
logger.error(error_msg)
self.export_progress["status"] = "error"
self.export_progress["percent"] = 100.0
self.export_progress["message"] = f"自动化操作失败,无法点击草稿'{draft_name}'"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
raise AutomationError(error_msg)
draft_btn.Click(simulateMove=False)
logger.info(f"Clicked on draft: '{draft_name}'.")
self.export_progress["status"] = "exporting"
self.export_progress["percent"] = 10.0
self.export_progress["message"] = "正在导出"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
logger.info(f"Waiting for edit window for draft: '{draft_name}' (timeout: 180s)")
# 等待编辑窗口加载,最多等待180秒
wait_start_time = time.time()
while time.time() - wait_start_time < 180:
try:
self.get_window() # 尝试获取最新的窗口句柄和状态
except AutomationError as e:
logger.debug(f"Failed to get window during edit window wait: {e}. Retrying...")
time.sleep(1)
continue
# 检查是否出现显卡运行环境提示框,如果出现则点击"暂不启用"
try:
disable_btn = self.app.TextControl(searchDepth=3, Compare=ControlFinder.desc_matcher("暂不启用"))
if disable_btn.Exists(0):
disable_btn.Click(simulateMove=False)
logger.info("Clicked '暂不启用' for graphics environment prompt.")
time.sleep(1)
except Exception as e:
logger.debug(f"No '暂不启用' button found or error during click: {e}")
# 检查是否已进入编辑窗口
time.sleep(1)
export_btn = self.app.TextControl(searchDepth=2, Compare=ControlFinder.desc_matcher("MainWindowTitleBarExportBtn"))
if export_btn.Exists(0):
time.sleep(1)
break
time.sleep(1)
else:
error_msg = f"AutomationError: Waiting for edit window timed out (180 seconds) for draft '{draft_name}'."
logger.error(error_msg)
self.export_progress["status"] = "error"
self.export_progress["percent"] = 100.0
self.export_progress["message"] = "编辑超时(180秒)"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
raise AutomationError("等待进入编辑窗口超时(180秒)")
self.export_progress["status"] = "exporting"
self.export_progress["percent"] = 15.0
self.export_progress["message"] = "正在导出"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
# 点击导出按钮
export_btn.Click(simulateMove=False)
logger.info(f"Waiting for export settings window (timeout: 180s) for draft: '{draft_name}'")
# 等待导出窗口加载,最多等待180秒
wait_start_time = time.time()
while time.time() - wait_start_time < 180:
try:
self.get_window()
except:
time.sleep(1)
continue
# 检查是否已进入导出窗口
export_path_sib = self.app.TextControl(searchDepth=2, Compare=ControlFinder.desc_matcher("ExportPath"))
if export_path_sib.Exists(0):
time.sleep(1) # 额外等待确保UI稳定
break
time.sleep(1)
else:
self.export_progress["status"] = "error"
self.export_progress["percent"] = 100.0
self.export_progress["message"] = "导出超时(180秒)"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
raise AutomationError("等待进入导出窗口超时(180秒)")
self.export_progress["status"] = "exporting"
self.export_progress["percent"] = 20.0
self.export_progress["message"] = "正在导出"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
# 获取原始导出路径(带后缀名)
export_path_text = export_path_sib.GetSiblingControl(lambda ctrl: True)
assert export_path_text is not None
export_path = export_path_text.GetPropertyValue(30159)
logger.info(f"Attempting to set resolution: {resolution.value if resolution else 'unchanged'}, framerate: {framerate.value if framerate else 'unchanged'} for '{draft_name}'")
# 设置分辨率
if resolution is not None:
retry_count = 0
max_retries = 3
while retry_count < max_retries:
try:
setting_group = self.app.GroupControl(searchDepth=1,
Compare=ControlFinder.class_name_matcher("PanelSettingsGroup_QMLTYPE"))
if not setting_group.Exists(0):
raise AutomationError("未找到导出设置组")
resolution_btn = setting_group.TextControl(searchDepth=2, Compare=ControlFinder.desc_matcher("ExportSharpnessInput"))
if not resolution_btn.Exists(0.5):
raise AutomationError("未找到导出分辨率下拉框")
resolution_btn.Click(simulateMove=False)
time.sleep(0.5)
resolution_item = self.app.TextControl(
searchDepth=2, Compare=ControlFinder.desc_matcher(resolution.value)
)
if not resolution_item.Exists(0.5):
raise AutomationError(f"未找到{resolution.value}分辨率选项")
resolution_item.Click(simulateMove=False)
time.sleep(0.5)
break # 设置成功,跳出循环
except AutomationError as e:
retry_count += 1
if retry_count >= max_retries:
raise # 重试次数用完,抛出异常
time.sleep(1) # 延迟1秒后重试
# 设置帧率
if framerate is not None:
retry_count = 0
max_retries = 3
while retry_count < max_retries:
try:
setting_group = self.app.GroupControl(searchDepth=1,
Compare=ControlFinder.class_name_matcher("PanelSettingsGroup_QMLTYPE"))
if not setting_group.Exists(0):
raise AutomationError("未找到导出设置组")
framerate_btn = setting_group.TextControl(searchDepth=2, Compare=ControlFinder.desc_matcher("FrameRateInput"))
if not framerate_btn.Exists(0.5):
raise AutomationError("未找到导出帧率下拉框")
framerate_btn.Click(simulateMove=False)
time.sleep(0.5)
framerate_item = self.app.TextControl(
searchDepth=2, Compare=ControlFinder.desc_matcher(framerate.value)
)
if not framerate_item.Exists(0.5):
raise AutomationError(f"未找到{framerate.value}帧率选项")
framerate_item.Click(simulateMove=False)
time.sleep(0.5)
break # 设置成功,跳出循环
except AutomationError as e:
retry_count += 1
if retry_count >= max_retries:
raise # 重试次数用完,抛出异常
time.sleep(1) # 延迟1秒后重试
logger.info(f"Clicking final export button for draft: '{draft_name}'")
# 点击导出
export_btn = self.app.TextControl(searchDepth=2, Compare=ControlFinder.desc_matcher("ExportOkBtn", exact=True))
if not export_btn.Exists(0):
raise AutomationError("未在导出窗口中找到导出按钮")
export_btn.Click(simulateMove=False)
time.sleep(5)
# 等待导出完成
st = time.time()
while True:
# self.get_window()
if self.app_status != "pre_export": continue
# 查找导出成功按钮
succeed_close_btn = self.app.TextControl(searchDepth=2, Compare=ControlFinder.desc_matcher("ExportSucceedCloseBtn"))
if succeed_close_btn.Exists(0):
self.export_progress["status"] = "finished"
self.export_progress["percent"] = 100
self.export_progress["message"] = "导出完成"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
succeed_close_btn.Click(simulateMove=False)
break
# 查找并更新进度百分比
try:
# 尝试查找所有文本控件,寻找包含百分比的文本
text_controls = self.app.GetChildren()
for control in text_controls:
progress_text = ""
# 检查控件名称
if hasattr(control, "Name") and control.Name and "%" in control.Name:
progress_text = control.Name
# 检查控件描述
elif hasattr(control, "GetPropertyValue"):
desc = control.GetPropertyValue(30159) if hasattr(control, "GetPropertyValue") else ""
if desc and isinstance(desc, str) and "%" in desc:
progress_text = desc
if progress_text:
# 提取百分比数字,支持小数点
percent_match = re.search(r'(\d+\.?\d*)%', progress_text)
print("progress_text is " + progress_text)
print("percent_match is ", percent_match)
if percent_match:
percent = float(percent_match.group(1)) # 使用float而不是int
print("percent is ", percent)
self.export_progress["percent"] = percent * 0.8 + 20
self.export_progress["message"] = "正在导出"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
break
except Exception as e:
self.export_progress["message"] = f"获取进度时出错: {e}"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
if time.time() - st > timeout:
self.export_progress["status"] = "error"
self.export_progress["message"] = f"导出超时{timeout}"
self.export_progress["elapsed"] = time.time() - self.export_progress["start_time"]
raise AutomationError("导出超时, 时限为%d" % timeout)
time.sleep(1)
time.sleep(2)
# 复制导出的文件到指定目录
if output_path is not None:
shutil.move(export_path, output_path)
logger.info(f"导出 {draft_name}{output_path} 完成")
# 回到目录页
logger.info("back to home page")
try:
self.get_window()
self.switch_to_home()
except Exception as e:
logger.warning(f"back to home 失败: {str(e)}, 杀进程重启")
ProcessController.kill_jianying()
if not ProcessController.restart_jianying():
logger.critical("Failed to restart JianYing application. Aborting.")
raise Exception("无法重启剪映程序")
time.sleep(2) # 等待进程启动
ProcessController.kill_jianying_detector()
def switch_to_home(self) -> None:
"""切换到剪映主页"""
if self.app_status == "home":
return
if self.app_status != "edit":
raise AutomationError("仅支持从编辑模式切换到主页")
close_btn = self.app.GroupControl(searchDepth=1, ClassName="TitleBarButton", foundIndex=3)
close_btn.Click(simulateMove=False)
time.sleep(2)
self.get_window()
def get_window(self) -> None:
"""寻找剪映窗口并置顶"""
if hasattr(self, "app") and self.app.Exists(0):
self.app.SetTopmost(False)
self.app = uia.WindowControl(searchDepth=1, Compare=self.__jianying_window_cmp)
if not self.app.Exists(0):
raise AutomationError("剪映窗口未找到")
# 寻找可能存在的导出窗口
export_window = self.app.WindowControl(searchDepth=1, Name="导出")
if export_window.Exists(0):
self.app = export_window
self.app_status = "pre_export"
self.app.SetActive()
self.app.SetTopmost()
def __jianying_window_cmp(self, control: uia.WindowControl, depth: int) -> bool:
if control.Name != "剪映专业版":
return False
if "HomePage".lower() in control.ClassName.lower():
self.app_status = "home"
return True
if "MainWindow".lower() in control.ClassName.lower():
self.app_status = "edit"
return True
return False
-318
View File
@@ -1,318 +0,0 @@
import uiautomation as auto
import time
import json
from typing import Dict, List, Optional
class JianYingUIInspector:
def __init__(self):
self.jianying_window = None
def find_jianying_window(self) -> bool:
"""查找剪映窗口"""
# 尝试多种可能的窗口名称
window_names = [
"剪映",
"JianYing",
"CapCut",
"剪映专业版"
]
for name in window_names:
try:
# 按窗口标题查找
window = auto.WindowControl(searchDepth=1, Name=name)
if window.Exists(0, 0):
self.jianying_window = window
print(f"找到剪映窗口: {name}")
return True
# 按类名查找(如果知道的话)
window = auto.WindowControl(searchDepth=1, ClassName="Qt5QWindowIcon")
if window.Exists(0, 0) and name.lower() in window.Name.lower():
self.jianying_window = window
print(f"找到剪映窗口: {window.Name}")
return True
except Exception as e:
continue
# 如果按名称找不到,尝试遍历所有窗口
print("按名称未找到,正在遍历所有窗口...")
for window in auto.GetRootControl().GetChildren():
if window.ControlType == auto.ControlType.WindowControl:
window_title = window.Name
if any(keyword in window_title for keyword in ["剪映", "JianYing", "CapCut"]):
self.jianying_window = window
print(f"找到剪映窗口: {window_title}")
return True
print("未找到剪映窗口,请确保剪映正在运行")
return False
def get_control_info(self, control) -> Dict:
"""获取控件的详细信息"""
try:
info = {
"Name": control.Name,
"ControlType": control.ControlTypeName,
"ClassName": getattr(control, 'ClassName', ''),
"AutomationId": getattr(control, 'AutomationId', ''),
"BoundingRectangle": {
"left": control.BoundingRectangle.left,
"top": control.BoundingRectangle.top,
"right": control.BoundingRectangle.right,
"bottom": control.BoundingRectangle.bottom,
"width": control.BoundingRectangle.width(),
"height": control.BoundingRectangle.height()
},
"IsEnabled": control.IsEnabled,
"IsVisible": getattr(control, 'IsOffscreen', True) == False,
"ProcessId": getattr(control, 'ProcessId', 0)
}
# 获取FullDescription属性 (属性ID: 30159)
try:
if hasattr(control, 'GetCurrentPropertyValue'):
full_description = control.GetCurrentPropertyValue(30159)
info["FullDescription"] = full_description or ""
else:
info["FullDescription"] = ""
except Exception as e:
info["FullDescription"] = ""
info["FullDescriptionError"] = str(e)
# 获取文本内容的多种方式
text_content = ""
# 方式1: 通过Value属性获取
try:
if hasattr(control, 'GetValuePattern'):
value_pattern = control.GetValuePattern()
if value_pattern:
text_content = value_pattern.Value
except:
pass
# 方式2: 通过Text属性获取
try:
if hasattr(control, 'GetTextPattern'):
text_pattern = control.GetTextPattern()
if text_pattern:
text_content = text_pattern.DocumentRange.GetText(-1)
except:
pass
# 方式3: 直接通过属性获取
try:
if not text_content and hasattr(control, 'CurrentValue'):
text_content = str(control.CurrentValue)
except:
pass
# 方式4: 通过LegacyIAccessible获取
try:
if not text_content and hasattr(control, 'GetLegacyIAccessiblePattern'):
legacy_pattern = control.GetLegacyIAccessiblePattern()
if legacy_pattern:
text_content = legacy_pattern.CurrentValue or legacy_pattern.CurrentName
except:
pass
# 方式5: 对于QML控件,尝试获取特定属性
try:
if not text_content and "QQuickText" in info["ClassName"]:
# QML Text控件可能需要特殊处理
if hasattr(control, 'GetCurrentPropertyValue'):
# 尝试获取Text属性
text_content = control.GetCurrentPropertyValue(auto.PropertyId.ValueValueProperty)
except:
pass
info["TextContent"] = text_content or ""
info["HasText"] = bool(text_content)
# 原有的其他属性获取
try:
info["Value"] = control.GetValuePattern().Value if hasattr(control, 'GetValuePattern') else ""
except:
info["Value"] = ""
try:
info["IsSelected"] = control.GetSelectionItemPattern().IsSelected if hasattr(control, 'GetSelectionItemPattern') else False
except:
info["IsSelected"] = False
return info
except Exception as e:
return {"Error": str(e), "Name": "获取信息失败"}
def build_ui_tree(self, control, max_depth: int = 10, current_depth: int = 0) -> Dict:
"""递归构建UI元素树"""
if current_depth >= max_depth:
return {"MaxDepthReached": True}
node = self.get_control_info(control)
node["Depth"] = current_depth
node["Children"] = []
try:
children = control.GetChildren()
for child in children:
if child.Exists(0, 0): # 检查子控件是否存在
child_node = self.build_ui_tree(child, max_depth, current_depth + 1)
node["Children"].append(child_node)
except Exception as e:
node["ChildrenError"] = str(e)
return node
def print_ui_tree(self, node: Dict, indent: str = ""):
"""打印UI树结构"""
control_type = node.get("ControlType", "Unknown")
name = node.get("Name", "")
class_name = node.get("ClassName", "")
automation_id = node.get("AutomationId", "")
full_description = node.get("FullDescription", "")
# 构建显示文本
display_parts = [control_type]
if name:
display_parts.append(f'Name="{name}"')
if class_name:
display_parts.append(f'Class="{class_name}"')
if automation_id:
display_parts.append(f'Id="{automation_id}"')
if full_description:
# 限制FullDescription显示长度,避免输出过长
desc_display = full_description[:100] + "..." if len(full_description) > 100 else full_description
display_parts.append(f'FullDesc="{desc_display}"')
display_text = " ".join(display_parts)
# 添加位置信息
if "BoundingRectangle" in node:
rect = node["BoundingRectangle"]
display_text += f" [{rect['left']},{rect['top']},{rect['width']}x{rect['height']}]"
print(f"{indent}{display_text}")
# 递归打印子节点
for child in node.get("Children", []):
self.print_ui_tree(child, indent + " ")
def save_ui_tree_to_file(self, tree: Dict, filename: str = "jianying_ui_tree.json"):
"""保存UI树到文件"""
try:
with open(filename, 'w', encoding='utf-8') as f:
json.dump(tree, f, ensure_ascii=False, indent=2)
print(f"UI树已保存到: {filename}")
except Exception as e:
print(f"保存文件失败: {e}")
def find_elements_by_type(self, tree: Dict, control_type: str) -> List[Dict]:
"""按控件类型查找元素"""
results = []
if tree.get("ControlType") == control_type:
results.append(tree)
for child in tree.get("Children", []):
results.extend(self.find_elements_by_type(child, control_type))
return results
def find_elements_by_name(self, tree: Dict, name: str) -> List[Dict]:
"""按名称查找元素"""
results = []
if name.lower() in tree.get("Name", "").lower():
results.append(tree)
for child in tree.get("Children", []):
results.extend(self.find_elements_by_name(child, name))
return results
def find_text_controls(self, tree: Dict) -> List[Dict]:
"""查找所有包含文本的控件"""
results = []
if tree.get("HasText") and tree.get("TextContent"):
results.append({
"ControlType": tree.get("ControlType"),
"Name": tree.get("Name"),
"ClassName": tree.get("ClassName"),
"TextContent": tree.get("TextContent"),
"BoundingRectangle": tree.get("BoundingRectangle")
})
for child in tree.get("Children", []):
results.extend(self.find_text_controls(child))
return results
def inspect_jianying_ui(self, max_depth: int = 8, save_to_file: bool = True):
"""检查剪映UI并显示元素树"""
print("正在查找剪映窗口...")
if not self.find_jianying_window():
return None
print(f"窗口信息: {self.jianying_window.Name}")
print(f"窗口位置: {self.jianying_window.BoundingRectangle}")
print("\n正在构建UI元素树...")
# 构建UI树
ui_tree = self.build_ui_tree(self.jianying_window, max_depth)
print("\n=== 剪映UI元素树 ===")
self.print_ui_tree(ui_tree)
if save_to_file:
self.save_ui_tree_to_file(ui_tree)
return ui_tree
def list_all_windows(self):
"""列出所有窗口,帮助调试"""
print("当前所有窗口:")
for window in auto.GetRootControl().GetChildren():
if window.ControlType == auto.ControlType.WindowControl:
try:
print(f"- {window.Name} (PID: {getattr(window, 'ProcessId', 'Unknown')})")
except:
print(f"- 无法获取窗口信息")
def main():
"""主函数"""
inspector = JianYingUIInspector()
# 如果找不到剪映窗口,先列出所有窗口
if not inspector.find_jianying_window():
print("\n列出所有窗口以供参考:")
inspector.list_all_windows()
return
# 检查UI
ui_tree = inspector.inspect_jianying_ui(max_depth=6, save_to_file=True)
if ui_tree:
# 示例:查找所有按钮
buttons = inspector.find_elements_by_type(ui_tree, "ButtonControl")
print(f"\n找到 {len(buttons)} 个按钮控件")
# 示例:查找包含"导出"的元素
export_elements = inspector.find_elements_by_name(ui_tree, "导出")
if export_elements:
print(f"\n找到 {len(export_elements)} 个包含'导出'的元素:")
for elem in export_elements:
print(f" - {elem.get('ControlType')}: {elem.get('Name')}")
# 新增:查找所有包含文本的控件
text_controls = inspector.find_text_controls(ui_tree)
if text_controls:
print(f"\n找到 {len(text_controls)} 个包含文本的控件:")
for ctrl in text_controls:
print(f" - {ctrl['ControlType']}: '{ctrl['TextContent']}'")
if __name__ == "__main__":
main()
-450
View File
@@ -1,450 +0,0 @@
import os
import uuid
import subprocess
import json
from typing import Optional, Literal
from typing import Dict, Any
import imageio.v2 as imageio
class Crop_settings:
"""素材的裁剪设置, 各属性均在0-1之间, 注意素材的坐标原点在左上角"""
upper_left_x: float
upper_left_y: float
upper_right_x: float
upper_right_y: float
lower_left_x: float
lower_left_y: float
lower_right_x: float
lower_right_y: float
def __init__(self, *, upper_left_x: float = 0.0, upper_left_y: float = 0.0,
upper_right_x: float = 1.0, upper_right_y: float = 0.0,
lower_left_x: float = 0.0, lower_left_y: float = 1.0,
lower_right_x: float = 1.0, lower_right_y: float = 1.0):
"""初始化裁剪设置, 默认参数表示不裁剪"""
self.upper_left_x = upper_left_x
self.upper_left_y = upper_left_y
self.upper_right_x = upper_right_x
self.upper_right_y = upper_right_y
self.lower_left_x = lower_left_x
self.lower_left_y = lower_left_y
self.lower_right_x = lower_right_x
self.lower_right_y = lower_right_y
def export_json(self) -> Dict[str, Any]:
return {
"upper_left_x": self.upper_left_x,
"upper_left_y": self.upper_left_y,
"upper_right_x": self.upper_right_x,
"upper_right_y": self.upper_right_y,
"lower_left_x": self.lower_left_x,
"lower_left_y": self.lower_left_y,
"lower_right_x": self.lower_right_x,
"lower_right_y": self.lower_right_y
}
class Video_material:
"""本地视频素材(视频或图片), 一份素材可以在多个片段中使用"""
material_id: str
"""素材全局id, 自动生成"""
local_material_id: str
"""素材本地id, 意义暂不明确"""
material_name: str
"""素材名称"""
path: str
"""素材文件路径"""
remote_url: Optional[str] = None
"""远程URL地址"""
duration: int
"""素材时长, 单位为微秒"""
height: int
"""素材高度"""
width: int
"""素材宽度"""
crop_settings: Crop_settings
"""素材裁剪设置"""
material_type: Literal["video", "photo"]
"""素材类型: 视频或图片"""
replace_path: Optional[str] = None
"""替换路径, 如果设置了这个值, 在导出json时会用这个路径替代原始path"""
def __init__(self, material_type: Literal["video", "photo"],
path: Optional[str] = None,
replace_path: Optional[str] = None,
material_name: Optional[str] = None,
crop_settings: Crop_settings = Crop_settings(),
remote_url: Optional[str] = None,
duration: Optional[float] = None,
width: Optional[int] = None,
height: Optional[int] = None):
"""从指定位置加载视频(或图片)素材
Args:
path (`str`, optional): 素材文件路径, 支持mp4, mov, avi等常见视频文件及jpg, jpeg, png等图片文件.
replace_path (`str`, optional): 替换路径,用于导出JSON时替代原始path.
material_type (`Literal["video", "photo"]`, optional): 素材类型,如果指定则优先使用该值.
material_name (`str`, optional): 素材名称, 如果不指定, 默认使用文件名作为素材名称.
crop_settings (`Crop_settings`, optional): 素材裁剪设置, 默认不裁剪.
remote_url (`str`, optional): 远程URL地址.
duration (`float`, optional): 音频时长(秒),如果提供则跳过ffprobe检测.
width (`int`, optional): 素材宽度, 如果不指定, 则使用ffprobe获取.
height (`int`, optional): 素材高度, 如果不指定, 则使用ffprobe获取.
Raises:
`ValueError`: 不支持的素材文件类型或缺少必要参数.
`FileNotFoundError`: 素材文件不存在.
"""
# 确保至少提供了path或remote_url
if not path and not remote_url:
raise ValueError("必须提供 path 或 remote_url 中的至少一个参数")
# 处理远程URL情况
if remote_url:
if not material_name:
raise ValueError("使用 remote_url 参数时必须指定 material_name")
self.remote_url = remote_url
self.path = "" # 远程资源没有本地路径
else:
# 处理本地文件情况
path = os.path.abspath(path)
if not os.path.exists(path):
raise FileNotFoundError(f"找不到 {path}")
self.path = path
self.remote_url = None
# 设置素材名称
self.material_name = material_name if material_name else os.path.basename(path)
self.material_id = uuid.uuid3(uuid.NAMESPACE_DNS, self.material_name).hex
self.replace_path = replace_path
self.crop_settings = crop_settings
self.local_material_id = ""
self.material_type = material_type
# 如果是photo类型,跳过ffprobe获取媒体信息的逻辑
if material_type == "photo":
self.material_type = "photo"
self.duration = 10800000000 # 静态图片默认3小时
# 使用imageio获取图片宽高
try:
# img = imageio.imread(self.remote_url)
# self.height, self.width = img.shape[:2]
# 使用默认宽高,在下载的时候才会获取真实宽高
self.width = 0
self.height = 0
except Exception as e:
# 如果获取失败,使用默认值
self.width = 1920
self.height = 1080
return
# 如果外部提供了duration,直接使用,跳过ffprobe检测
if duration is not None and width is not None and height is not None:
self.duration = int(float(duration) * 1e6) # 转换为微秒
self.width = width
self.height = height
return # 直接返回,跳过后续的ffprobe检测
# 如果没有提供duration,则使用ffprobe获取
try:
# 使用ffprobe获取媒体信息
media_path = self.path if self.path else self.remote_url
command = [
'ffprobe',
'-v', 'error',
'-select_streams', 'v:0', # 选择第一个视频流
'-show_entries', 'stream=width,height,duration,codec_type', # 添加codec_type
'-show_entries', 'format=duration,format_name', # 添加format_name
'-of', 'json',
media_path
]
result = subprocess.check_output(command, stderr=subprocess.STDOUT)
result_str = result.decode('utf-8')
# 查找JSON开始位置(第一个'{'
json_start = result_str.find('{')
if json_start != -1:
json_str = result_str[json_start:]
info = json.loads(json_str)
else:
raise ValueError(f"无法在输出中找到JSON数据: {result_str}")
if 'streams' in info and len(info['streams']) > 0:
stream = info['streams'][0]
self.width = int(stream.get('width', 0))
self.height = int(stream.get('height', 0))
# 如果指定了material_type,则优先使用指定的类型
if material_type is not None:
self.material_type = material_type
else:
# 通过format_name和codec_type判断是否是动态视频
format_name = info.get('format', {}).get('format_name', '').lower()
codec_type = stream.get('codec_type', '').lower()
# 检查是否是GIF或其他动态视频
if 'gif' in format_name or (codec_type == 'video' and stream.get('duration') is not None):
self.material_type = "video"
else:
self.material_type = "photo"
# 设置持续时间
if self.material_type == "video":
# 优先使用流的duration,如果没有则使用格式的duration
duration = stream.get('duration') or info['format'].get('duration', '0')
self.duration = int(float(duration) * 1e6) # 转换为微秒
else:
self.duration = 10800000000 # 静态图片默认3小时
else:
raise ValueError(f"无法获取媒体文件 {media_path} 的流信息")
except subprocess.CalledProcessError as e:
raise ValueError(f"处理文件 {media_path} 时出错: {e.output.decode('utf-8')}")
except json.JSONDecodeError as e:
raise ValueError(f"解析媒体信息时出错: {e}")
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Video_material":
"""从字典创建视频素材对象
Args:
data (Dict[str, Any]): 包含素材信息的字典
Returns:
Video_material: 新创建的视频素材对象
"""
# 创建实例但不调用__init__
instance = cls.__new__(cls)
# 设置基本属性
instance.material_id = data["id"]
instance.local_material_id = data.get("local_material_id", "")
instance.material_name = data["material_name"]
instance.path = data["path"]
instance.duration = data["duration"]
instance.height = data["height"]
instance.width = data["width"]
instance.material_type = data["type"]
instance.replace_path = None # 默认不设置替换路径
# 设置裁剪设置
crop_data = data.get("crop", {})
instance.crop_settings = Crop_settings(
upper_left_x=crop_data.get("upper_left_x", 0.0),
upper_left_y=crop_data.get("upper_left_y", 0.0),
upper_right_x=crop_data.get("upper_right_x", 1.0),
upper_right_y=crop_data.get("upper_right_y", 0.0),
lower_left_x=crop_data.get("lower_left_x", 0.0),
lower_left_y=crop_data.get("lower_left_y", 1.0),
lower_right_x=crop_data.get("lower_right_x", 1.0),
lower_right_y=crop_data.get("lower_right_y", 1.0)
)
return instance
def export_json(self) -> Dict[str, Any]:
video_material_json = {
"audio_fade": None,
"category_id": "",
"category_name": "local",
"check_flag": 63487,
"crop": self.crop_settings.export_json(),
"crop_ratio": "free",
"crop_scale": 1.0,
"duration": self.duration,
"height": self.height,
"id": self.material_id,
"local_material_id": self.local_material_id,
"material_id": self.material_id,
"material_name": self.material_name,
"media_path": "",
"path": self.replace_path if self.replace_path is not None else self.path,
"remote_url": self.remote_url,
"type": self.material_type,
"width": self.width
}
return video_material_json
class Audio_material:
"""本地音频素材"""
material_id: str
"""素材全局id, 自动生成"""
material_name: str
"""素材名称"""
path: str
"""素材文件路径"""
remote_url: Optional[str] = None
"""远程URL地址"""
replace_path: Optional[str] = None
"""替换路径, 如果设置了这个值, 在导出json时会用这个路径替代原始path"""
has_audio_effect: bool = False
"""是否有音频效果"""
duration: int
"""素材时长, 单位为微秒"""
def __init__(self, path: Optional[str] = None, replace_path = None, material_name: Optional[str] = None,
remote_url: Optional[str] = None, duration: Optional[float] = None):
"""从指定位置加载音频素材, 注意视频文件不应该作为音频素材使用
Args:
path (`str`, optional): 素材文件路径, 支持mp3, wav等常见音频文件.
material_name (`str`, optional): 素材名称, 如果不指定, 默认使用URL中的文件名作为素材名称.
remote_url (`str`, optional): 远程URL地址.
duration (`float`, optional): 音频时长(秒),如果提供则跳过ffprobe检测.
Raises:
`ValueError`: 不支持的素材文件类型或缺少必要参数.
"""
if not path and not remote_url:
raise ValueError("必须提供 path 或 remote_url 中的至少一个参数")
if path:
path = os.path.abspath(path)
if not os.path.exists(path):
raise FileNotFoundError(f"找不到 {path}")
# 从URL中获取文件名作为material_name
if not material_name and remote_url:
original_filename = os.path.basename(remote_url.split('?')[0]) # 修复:使用remote_url而不是audio_url
name_without_ext = os.path.splitext(original_filename)[0] # 获取不带扩展名的文件名
material_name = f"{name_without_ext}.mp3" # 使用原始文件名+时间戳+固定mp3扩展名
self.material_name = material_name if material_name else (os.path.basename(path) if path else "unknown")
self.material_id = uuid.uuid3(uuid.NAMESPACE_DNS, self.material_name).hex
self.path = path if path else ""
self.replace_path = replace_path
self.remote_url = remote_url
# 如果外部提供了duration,直接使用,跳过ffprobe检测
if duration is not None:
self.duration = int(float(duration) * 1e6) # 转换为微秒
return # 直接返回,跳过后续的ffprobe检测
# 如果没有提供duration,则使用ffprobe获取
self.duration = 0 # 初始化为0,如果有path则后续会更新
try:
# 使用ffprobe获取音频信息
command = [
'ffprobe',
'-v', 'error',
'-select_streams', 'a:0', # 选择第一个音频流
'-show_entries', 'stream=duration',
'-show_entries', 'format=duration',
'-of', 'json',
path if path else remote_url
]
result = subprocess.check_output(command, stderr=subprocess.STDOUT)
result_str = result.decode('utf-8')
# 查找JSON开始位置(第一个'{'
json_start = result_str.find('{')
if json_start != -1:
json_str = result_str[json_start:]
info = json.loads(json_str)
else:
raise ValueError(f"无法在输出中找到JSON数据: {result_str}")
# 检查是否有视频流
video_command = [
'ffprobe',
'-v', 'error',
'-select_streams', 'v:0',
'-show_entries', 'stream=codec_type',
'-of', 'json',
path if path else remote_url
]
video_result = subprocess.check_output(video_command, stderr=subprocess.STDOUT)
video_result_str = video_result.decode('utf-8')
# 查找JSON开始位置(第一个'{'
video_json_start = video_result_str.find('{')
if video_json_start != -1:
video_json_str = video_result_str[video_json_start:]
video_info = json.loads(video_json_str)
else:
print(f"无法在输出中找到JSON数据: {video_result_str}")
if 'streams' in video_info and len(video_info['streams']) > 0:
raise ValueError("音频素材不应包含视频轨道")
# 检查音频流
if 'streams' in info and len(info['streams']) > 0:
stream = info['streams'][0]
# 优先使用流的duration,如果没有则使用格式的duration
duration_value = stream.get('duration') or info['format'].get('duration', '0')
self.duration = int(float(duration_value) * 1e6) # 转换为微秒
else:
raise ValueError(f"给定的素材文件 {path} 没有音频轨道")
except subprocess.CalledProcessError as e:
raise ValueError(f"处理文件 {path} 时出错: {e.output.decode('utf-8')}")
except json.JSONDecodeError as e:
raise ValueError(f"解析媒体信息时出错: {e}")
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Audio_material":
"""从字典创建音频素材对象
Args:
data (Dict[str, Any]): 包含素材信息的字典
Returns:
Audio_material: 新创建的音频素材对象
"""
# 创建实例但不调用__init__
instance = cls.__new__(cls)
# 设置基本属性
instance.material_id = data["id"]
instance.material_name = data["name"] # 注意这里是name而不是material_name
instance.path = data["path"]
instance.duration = data["duration"]
instance.replace_path = None # 默认不设置替换路径
instance.remote_url = data.get("remote_url")
return instance
def export_json(self) -> Dict[str, Any]:
return {
"app_id": 0,
"category_id": "",
"category_name": "local",
"check_flag": 3 if hasattr(self, 'has_audio_effect') and self.has_audio_effect else 1,
"copyright_limit_type": "none",
"duration": self.duration,
"effect_id": "",
"formula_id": "",
"id": self.material_id,
"intensifies_path": "",
"is_ai_clone_tone": False,
"is_text_edit_overdub": False,
"is_ugc": False,
"local_material_id": self.material_id,
"music_id": self.material_id,
"name": self.material_name,
"path": self.replace_path if self.replace_path is not None else self.path,
"remote_url": self.remote_url,
"query": "",
"request_id": "",
"resource_id": "",
"search_id": "",
"source_from": "",
"source_platform": 0,
"team_id": "",
"text_id": "",
"tone_category_id": "",
"tone_category_name": "",
"tone_effect_id": "",
"tone_effect_name": "",
"tone_platform": "",
"tone_second_category_id": "",
"tone_second_category_name": "",
"tone_speaker": "",
"tone_type": "",
"type": "extract_music",
"video_id": "",
"wave_points": []
}
-52
View File
@@ -1,52 +0,0 @@
"""记录各种特效/音效/滤镜等的元数据"""
from .effect_meta import Effect_meta, Effect_param_instance
from .font_meta import Font_type
from .mask_meta import Mask_type, Mask_meta
from .capcut_mask_meta import CapCut_Mask_type
from .filter_meta import Filter_type
from .transition_meta import Transition_type
from .capcut_transition_meta import CapCut_Transition_type
from .animation_meta import Intro_type, Outro_type, Group_animation_type
from .capcut_animation_meta import CapCut_Intro_type, CapCut_Outro_type, CapCut_Group_animation_type
from .animation_meta import Text_intro, Text_outro, Text_loop_anim
from .capcut_text_animation_meta import CapCut_Text_intro, CapCut_Text_outro, CapCut_Text_loop_anim
from .audio_effect_meta import Audio_scene_effect_type, Tone_effect_type, Speech_to_song_type
from .capcut_audio_effect_meta import CapCut_Voice_filters_effect_type, CapCut_Voice_characters_effect_type, CapCut_Speech_to_song_effect_type
from .video_effect_meta import Video_scene_effect_type, Video_character_effect_type
from .capcut_effect_meta import CapCut_Video_scene_effect_type, CapCut_Video_character_effect_type
__all__ = [
"Effect_meta",
"Effect_param_instance",
"Mask_type",
"Mask_meta",
"CapCut_Mask_type",
"Filter_type",
"Font_type",
"Transition_type",
"CapCut_Transition_type",
"Intro_type",
"Outro_type",
"Group_animation_type",
"CapCut_Intro_type",
"CapCut_Outro_type",
"CapCut_Group_animation_type",
"Text_intro",
"Text_outro",
"Text_loop_anim",
"CapCut_Text_intro",
"CapCut_Text_outro",
"CapCut_Text_loop_anim",
"Audio_scene_effect_type",
"Tone_effect_type",
"Speech_to_song_type",
"CapCut_Voice_filters_effect_type",
"CapCut_Voice_characters_effect_type",
"CapCut_Speech_to_song_effect_type",
"Video_scene_effect_type",
"Video_character_effect_type",
"CapCut_Video_scene_effect_type",
"CapCut_Video_character_effect_type"
]
-689
View File
@@ -1,689 +0,0 @@
from .effect_meta import Effect_enum
class Animation_meta:
title: str
is_vip: bool
duration: int
"""效果默认时长, 单位为微秒"""
resource_id: str
effect_id: str
md5: str
def __init__(self, title: str, is_vip: bool, duration: float, resource_id: str, effect_id: str, md5: str):
self.title = title
self.is_vip = is_vip
self.duration = int(round(duration * 1e6))
self.resource_id = resource_id
self.effect_id = effect_id
self.md5 = md5
class Intro_type(Effect_enum):
"""剪映自带的视频/图片入场动画类型"""
# 免费入场动画
缩小 = Animation_meta("缩小", False, 0.500, "6798332584276267527", "624755", "7e0e6b55704b7fc20588fee77058e95c")
渐显 = Animation_meta("渐显", False, 0.500, "6798320778182922760", "624705", "af863de1e359fd4f54bb78f2e2749e1f")
放大 = Animation_meta("放大", False, 0.500, "6798332733694153230", "624751", "028a77e121c22a4dd130a46a0ed90714")
旋转 = Animation_meta("旋转", False, 0.500, "6798334070653719054", "624731", "b3018b8ae12d4a9421d81a3b263b7e88")
Kira游动 = Animation_meta("Kira游动", False, 2.267, "7311984593387655731", "34176967", "05daa2cb2b53e1830a0e657ede749daf")
抖动下降 = Animation_meta("抖动下降", False, 0.500, "6991764455931515422", "1206320", "9b04ce5965c78218e918f043cf12a879")
镜像翻转 = Animation_meta("镜像翻转", False, 0.500, "6797338697625768455", "646003", "55ec076a5d62f7e80655e60c43f68f80")
旋转开幕 = Animation_meta("旋转开幕", False, 1.000, "7186944542409495099", "8295043", "407822a27a67612c3caa3e4223aa32d3")
折叠开幕 = Animation_meta("折叠开幕", False, 1.500, "7239273897491698232", "14506065", "17e0225f852c0798063d82440ca54185")
漩涡旋转 = Animation_meta("漩涡旋转", False, 0.500, "6782010677520241165", "703281", "6e922bdebed1d87f9a63ba285a5dd792")
跳转开幕 = Animation_meta("跳转开幕", False, 0.733, "7279999334001676857", "23185431", "817876a62d2d05e4eef9ac4cfa9c70fe")
轻微抖动 = Animation_meta("轻微抖动", False, 0.500, "6739418227031413256", "431664", "7ec99bda70fa6922395d65235991f9e5")
轻微抖动_II = Animation_meta("轻微抖动 II", False, 0.500, "6739418677910704651", "431650", "8e29ab0a86dac5719300064821e8b63d")
轻微抖动_III= Animation_meta("轻微抖动 III", False, 0.500, "6781683302672634382", "503136", "8482055860ab20c23102d78aa3486a7a")
上下抖动 = Animation_meta("上下抖动", False, 0.500, "6739418390030455300", "431652", "bff95de5e1e4803ea64a52632bcfb361")
左右抖动 = Animation_meta("左右抖动", False, 0.500, "6739418540421419524", "431654", "7572d7461e38d73c578aa8e4dca7163a")
斜切 = Animation_meta("斜切", False, 0.700, "7210657307938525751", "10696371", "a385761197d457f4599d231421045230")
钟摆 = Animation_meta("钟摆", False, 0.500, "6803260897117606414", "636115", "6b9d17389864da0a68d347365023849a")
雨刷 = Animation_meta("雨刷", False, 0.500, "6802871256849846791", "634681", "0a8846e691446c6b2f583086567579a5")
雨刷_II = Animation_meta("雨刷 II", False, 0.500, "6805748897768542727", "640101", "f67c2ccd81956813d5b1303625bed354")
向上转入 = Animation_meta("向上转入", False, 0.500, "6808401616564130312", "645307", "0247c3715de210fa89a4fc9f2f03b63c")
向上转入_II = Animation_meta("向上转入 II", False, 0.500, "6818747060649464327", "701961", "c66f550e7ab2de4ef4eb1ee7e7002fa3")
向左转入 = Animation_meta("向左转入", False, 0.500, "6816560956647150093", "699157", "aca9db228bf685cd9f02eb966252846e")
向右转入 = Animation_meta("向右转入", False, 0.500, "6805019065761927694", "638825", "c447b8637ba24ae1111b087e8d5a5739")
向上滑动 = Animation_meta("向上滑动", False, 0.500, "6798333487523828238", "624739", "9598ba5dd6e4ce29c7c3ffded39fb3b9")
向下滑动 = Animation_meta("向下滑动", False, 0.500, "6798333705401143816", "624735", "d34d52d5386e20de654b0fff9ea9704f")
向左滑动 = Animation_meta("向左滑动", False, 0.500, "6798332871267324423", "624747", "dcae7883ea619dac2661a5f21795cc9f")
向右滑动 = Animation_meta("向右滑动", False, 0.500, "6798333076469453320", "624743", "e3e2dad87aff58e7944fac67661b56b2")
向下甩入 = Animation_meta("向下甩入", False, 0.500, "6739338374441603598", "431638", "afb5afec3c42fa627a007ff609c83792")
向右甩入 = Animation_meta("向右甩入", False, 0.500, "6739338727866241539", "431636", "228f76b86355e74087a9a80647236b88")
向左上甩入 = Animation_meta("向左上甩入", False, 0.500, "6740122563692728844", "431648", "aa97897803351debd46c9182132c64c5")
向右上甩入 = Animation_meta("向右上甩入", False, 0.500, "6740122731418751495", "431644", "12ae5b6cc0b2bff43e958d5ca2d574fe")
向左下甩入 = Animation_meta("向左下甩入", False, 0.500, "6739395445346275853", "431642", "269d5e19ed83faa5f5c72a1401e4564b")
向右下甩入 = Animation_meta("向右下甩入", False, 0.500, "6739395718223499787", "431640", "f821a402edb042a9d68d825cb804ac6e")
动感放大 = Animation_meta("动感放大", False, 0.500, "6740867832570974733", "431662", "3d880239a1fa70fbaedcc7fd20794e22")
动感缩小 = Animation_meta("动感缩小", False, 0.500, "6740868384637850120", "431658", "8357dd30914ef6ba1ba89dd12a83dc3e")
轻微放大 = Animation_meta("轻微放大", False, 0.500, "6800268825611735559", "629085", "f6c8209ef7142fff6cf9c68573216371")
# 付费入场动画
快速翻页 = Animation_meta("快速翻页", True, 0.167, "7296381392340914715", "27878991", "6e1d71ff694a87526f9c5bb2c01c927d")
荧光爆闪 = Animation_meta("荧光爆闪", True, 1.000, "7347948517471556096", "51992419", "84d6cfae125a71855b500604748f1e19")
十字震动 = Animation_meta("十字震动", True, 0.800, "7352824361625063987", "54686020", "33d4a2ff79aa2fb88fadd45aee1998e9")
爱心碰撞 = Animation_meta("爱心碰撞", True, 2.667, "7327872475453198848", "41910725", "119e873890708ee4817c9778dcb20b69")
冲撞 = Animation_meta("冲撞", True, 2.000, "7215530662986519096", "11320895", "aeadb248c06d074a2d98f425a57999f0")
闪屏 = Animation_meta("闪屏", True, 1.200, "7242155802209817147", "14904085", "c2f368ce853ab863a12c686bb99bb41e")
扫描 = Animation_meta("扫描", True, 0.600, "7312335732721324554", "34385508", "191401f0b79c28d7569dfc356ba827b6")
震动波纹 = Animation_meta("震动波纹", True, 1.500, "7307196313148330547", "31806105", "95760b6f7efe0016546e38852a981f49")
分屏翻转 = Animation_meta("分屏翻转", True, 0.700, "7257782721575916088", "18711457", "013f6255cb0672198f26962bff3f788b")
立体翻转 = Animation_meta("立体翻转", True, 1.100, "7346505124820292150", "51089258", "bad88fa72b42b3c12099c31654575952")
马赛克 = Animation_meta("马赛克", True, 1.000, "7282703408383922745", "23885083", "273c4952c915c9250f0b9edadac34148")
_2024 = Animation_meta("2024", True, 1.500, "7309774750677471794", "33056565", "d68370ce25f28ec80d9c0bb7e51e2324")
多层环形 = Animation_meta("多层环形", True, 2.000, "7329444938960081460", "42686363", "54801ad31b13853ad1e3ccf945e89973")
弹力分割 = Animation_meta("弹力分割", True, 1.060, "7267827357627454013", "35994464", "9f5878effce0a857900a4f050ea52318")
弹近 = Animation_meta("弹近", True, 1.500, "7314144465944318502", "35289246", "30c62d3ccb969173e5fa43511894116b")
画出爱心 = Animation_meta("画出爱心", True, 1.600, "7248901535894082105", "16211481", "6e5cdc1e7ece582da904ac520440e88a")
发光矩形 = Animation_meta("发光矩形", True, 1.033, "7346511208171704841", "51093680", "64852509d7cb2a578469b3438b94df52")
空间扭曲 = Animation_meta("空间扭曲", True, 1.160, "7298688232294715931", "28693486", "da3a08519a9315e3625173b71a4d8ee3")
四屏转换 = Animation_meta("四屏转换", True, 1.000, "7341283787143123507", "48492378", "fdd9abc8f2abadc0ae6e909779f282e6")
展开 = Animation_meta("展开", True, 0.500, "7221413342257091133", "12088589", "553acdb325d76533d6ecbd6d621d9b9e")
划水 = Animation_meta("划水", True, 0.800, "7226632607939695161", "12811781", "57a259c58a4daddacc897c75ec9c10a4")
色散波纹 = Animation_meta("色散波纹", True, 0.830, "7299029942870741542", "28824874", "2ce459ce040280d7c4f36ab78a3612e5")
模糊聚焦 = Animation_meta("模糊聚焦", True, 1.200, "7337937899704291866", "46838778", "38841ccaef6186af6d516eeea116b3c6")
圆形开幕 = Animation_meta("圆形开幕", True, 0.900, "7218210014949806647", "11680735", "2c171ce2c85042bb518cbdc08ced9709")
聚合 = Animation_meta("聚合", True, 2.000, "7303524763589153306", "30391788", "c3293067129322c884d0865b99cb11bd")
砸出波纹 = Animation_meta("砸出波纹", True, 1.560, "7255594501694034490", "18159482", "644483b024fc852955dd807da067d8e9")
向下甩动 = Animation_meta("向下甩动", True, 1.400, "7338320641306661410", "47050546", "060ee66b7f59d3d2c8064be5ae32171c")
向上滚动 = Animation_meta("向上滚动", True, 1.000, "7312341574988337690", "34388476", "14e7c85bfa04ecbacc1e63ee386840b7")
拼图 = Animation_meta("拼图", True, 1.067, "7369889381357720102", "64963350", "4b721a1559eb3451d6cc358468537c49")
向上闪入 = Animation_meta("向上闪入", True, 0.700, "7273389803532456504", "21816946", "ecaffca7c7e1d7744fa296a29f65b366")
交错开幕 = Animation_meta("交错开幕", True, 1.100, "7280797339042714169", "23387955", "123322fa9ce7c37f0c2c35819f00b524")
便利贴 = Animation_meta("便利贴", True, 0.900, "7379456870265655859", "70486392", "06613663efa8ef29beadf8746019c823")
侧滑 = Animation_meta("侧滑", True, 0.600, "7239559299196785209", "14524393", "c67d95e820752346af44e2cb515c0115")
横向模糊 = Animation_meta("横向模糊", True, 0.500, "7301896031673782835", "29805902", "b8b953ad94b16c47601af887d4ccc8c9")
闪现 = Animation_meta("闪现", True, 0.440, "7210363235906622012", "10668047", "6a680c49cd11a05f3eb0e5a3fed165f7")
水墨 = Animation_meta("水墨", True, 2.433, "7321672946466951731", "39180627", "7e5d11c796a2e1bec5feb486e647e60b")
交叉震动 = Animation_meta("交叉震动", True, 0.833, "7222990639984546360", "12309329", "cde910202607be12ac747e2e76316e7f")
抖动横移 = Animation_meta("抖动横移", True, 0.567, "7265946978792510010", "20437845", "e4951e1d7abcdbd4e8bf1cf33430def7")
抖动变焦 = Animation_meta("抖动变焦", True, 0.800, "7156911481563386381", "5414507", "04365018fdc27b7e1175b709a739f800")
斜向拉丝 = Animation_meta("斜向拉丝", True, 0.667, "7360531434487943743", "58777551", "60ba474a0460cb7e999830c02943e977")
拉丝滑入 = Animation_meta("拉丝滑入", True, 0.500, "7112725640901562887", "3179668", "913b99e9012d50f629c59a31e030b143")
果冻_I = Animation_meta("果冻 I", True, 0.800, "7171640017574433294", "6725401", "4ef7f9da6b1331109620381229d55429")
果冻_II = Animation_meta("果冻 II", True, 0.800, "7171690870788329992", "6732061", "01d346b0f37b87c25c17a53309189432")
烟雾弹 = Animation_meta("烟雾弹", True, 1.200, "7226641244938572346", "12815013", "8c5e4642b824c252b5a556bbbcbae767")
震波 = Animation_meta("震波", True, 0.800, "7115301367786246692", "3297068", "8aaccb8f112aa3cacd80fa79fcc1690f")
震波_II = Animation_meta("震波 II", True, 0.833, "7211042099737662009", "10744265", "f8f236cd1279af3680bcc71dda889d97")
震波_III = Animation_meta("震波 III", True, 1.700, "7288985830578721336", "25545977", "3be0a1f04cf38bf05ed301ebaeb47ef8")
旋转圆球 = Animation_meta("旋转圆球", True, 0.800, "7380298290140549647", "70989966", "19b93b0edea19a73d2cf7f818ace3265")
转圈圈 = Animation_meta("转圈圈", True, 0.800, "7246643852411408952", "15726741", "f2c920e366c3c733f1d86a8473aff310")
曝光放射 = Animation_meta("曝光放射", True, 0.800, "7158737452939612703", "5529363", "09df65728356189436974e08c42bc578")
玻璃聚集 = Animation_meta("玻璃聚集", True, 1.700, "7340265236101861915", "48072242", "68c8e8f1eba4f4b2e3d35472f8b4822c")
分屏横移 = Animation_meta("分屏横移", True, 1.000, "7257878167023522365", "18746326", "dcadf2284399fe6200f77fad9a1ec41a")
流金 = Animation_meta("流金", True, 1.500, "7322367212142989850", "39438403", "6654a74eb923c201fe18765f18d4b367")
心形放大 = Animation_meta("心形放大", True, 1.500, "7042968847070007844", "1487080", "3bb1bb084e5ebf25e67fc078d3c6a119")
老电视 = Animation_meta("老电视", True, 1.400, "7290754106417746491", "26091602", "4cbe6bdc6da704e481a40f44266cee0b")
脉冲 = Animation_meta("脉冲", True, 0.900, "7379909514847326732", "70764198", "ae7fac0214409e340db6a600e97303da")
能量立方 = Animation_meta("能量立方", True, 1.333, "7359472053998588425", "58285135", "301b4ffff8510c87b7174161b2642ca3")
波纹弹动 = Animation_meta("波纹弹动", True, 1.200, "7345731405663441460", "50640360", "b29c4c4dbac023b27bac5d32e642f6bb")
class Outro_type(Effect_enum):
"""剪映自带的视频/图片出场动画类型"""
# 免费
向上转出 = Animation_meta("向上转出", False, 0.500, "6818747115934585357", "701963", "7f57dd9488a89da902a998018adafdf5")
向上转出_II = Animation_meta("向上转出 II", False, 0.500, "6818747169017696781", "701965", "0d37319fa4b20f2584ac32294f48a554")
跳转闭幕 = Animation_meta("跳转闭幕", False, 0.733, "7280420767378969143", "23302677", "82992a12a8ae1227579be0f66d87d75f")
镜像翻转 = Animation_meta("镜像翻转", False, 0.500, "6738353628215513613", "645999", "a24594428fdd0c8078b74659fc1f2679")
旋转闭幕 = Animation_meta("旋转闭幕", False, 1.000, "6942482728335970823", "1221132", "b235b8a2a8647a211494856315cde2a9")
漩涡旋转 = Animation_meta("漩涡旋转", False, 0.500, "6778418947361346061", "634701", "2f239d1240bc871d05ce582ba201b085")
向上滑动 = Animation_meta("向上滑动", False, 0.500, "6798333612958683656", "624737", "1b4343c92c2545a50216b85e2a08a6ee")
向下滑动 = Animation_meta("向下滑动", False, 0.500, "6798333787986989576", "624733", "9eced44ba9f495d053661ebd552088bb")
向左滑动 = Animation_meta("向左滑动", False, 0.500, "6798332972098392584", "624745", "771fc844822cea60f0623ecff4f4b88a")
向右滑动 = Animation_meta("向右滑动", False, 0.500, "6798333350487527950", "624741", "d1dcd128f35a8ad365847355f28e259b")
折叠闭幕 = Animation_meta("折叠闭幕", False, 1.500, "7239273967310082621", "14506017", "f750b9b6c7a756dfdd6785cde5d24d00")
轻微放大 = Animation_meta("轻微放大", False, 0.500, "6800268611807089166", "629083", "b2a1271b065aa9e6351bfd64ff7d4eea")
Kira游动 = Animation_meta("Kira游动", False, 2.267, "7312343337199997450", "34389264", "2cefeb684db271dc288ec225f0854264")
缩小 = Animation_meta("缩小", False, 0.500, "6798332648814023181", "624753", "509c5edb2131a88070bf699ad0852e4f")
放大 = Animation_meta("放大", False, 0.500, "6798332801864176142", "624749", "01497dc221d288e623a10cac94a5ceca")
旋转 = Animation_meta("旋转", False, 0.500, "6798334141323547143", "624729", "44e26ad0221385965730ae69d947d790")
斜切 = Animation_meta("斜切", False, 0.700, "7210659943051956797", "10697199", "93fd7d9c4f059c26cd3681dd512c20ed")
# 付费
渐隐 = Animation_meta("渐隐", False, 0.500, "6798320902548230669", "624707", "808a065a2319cc6d1d53d9bec791ac6e")
空间扭曲 = Animation_meta("空间扭曲", True, 0.930, "7298918355841323529", "28775864", "04c885b1dbbcf51bcc01e4df931bff72")
弹远 = Animation_meta("弹远", True, 1.200, "7314925770181186075", "35749432", "310e6755e6441af5d3405bc80a3be26d")
四屏转换 = Animation_meta("四屏转换", True, 0.900, "7341284613165158921", "48492502", "cf7d3bd0e7973868861d1e466cb238eb")
分屏翻转 = Animation_meta("分屏翻转", True, 0.560, "7259341241031070268", "19063130", "392b91fd262e9b95e1dcd18274297393")
冲撞 = Animation_meta("冲撞", True, 0.767, "7215555273501446716", "11325221", "16e01aa5454653bc89d3b1d8e86ce3a2")
旋转圆球 = Animation_meta("旋转圆球", True, 0.800, "7381753028732260916", "71750513", "e824e3d74a50eba64dd87ac11b9bbfb8")
砸出波纹 = Animation_meta("砸出波纹", True, 1.366, "7255599483226952249", "18161234", "87e9baa63de40d76f862bb8aa4349de3")
交叉震动 = Animation_meta("交叉震动", True, 0.466, "7223227564670587452", "12330095", "3a711c053dcadb7856d19778f72a58c1")
能量立方 = Animation_meta("能量立方", True, 1.133, "7361364150229930506", "59265410", "f6c5b98ea69f3b2c3265bb3249973250")
横向模糊 = Animation_meta("横向模糊", True, 0.500, "7301943351320777267", "29824130", "294f0f8ecbe4b4a8b8f2c01f579739f1")
多层环形 = Animation_meta("多层环形", True, 1.633, "7329445038604161536", "42686393", "c684bdf866bada10acb647e5339397a3")
斜向拉丝 = Animation_meta("斜向拉丝", True, 0.500, "7360531353458184715", "58777523", "71a267bc37d3dc0afa3aaae12ec995e7")
分屏横移 = Animation_meta("分屏横移", True, 0.880, "7257879855063110205", "18746674", "7382c7210c95548bfc88486be3964284")
_2024 = Animation_meta("2024", True, 1.000, "7311958876406944266", "34158075", "93bcb64554588e6f3a0a4ffffa0bb3b5")
扫描 = Animation_meta("扫描", True, 0.633, "7316816362305753609", "36871694", "a89a479b5228737e62ccd7e77059315f")
曝光放射 = Animation_meta("曝光放射", True, 0.500, "7158753896624558628", "5529791", "70911371ae8ec475600c4e30c9db8994")
色散波纹 = Animation_meta("色散波纹", True, 0.767, "7305961286762762790", "31248281", "5477505f844e9bad12dc9074631564b1")
马赛克 = Animation_meta("马赛克", True, 1.000, "7283415427328250405", "24073041", "6be9c2fd05f76e3902a9967139706468")
十字震动 = Animation_meta("十字震动", True, 0.533, "7352824282289803814", "54685998", "969e17d5d65494d0b10b9111d66802d8")
震动波纹 = Animation_meta("震动波纹", True, 1.500, "7307196476340310554", "31806349", "cdb162bc674e495b24d38a2cf4bd04b6")
弹力分割 = Animation_meta("弹力分割", True, 1.060, "7343902820808004123", "49678364", "62adcd0cd61c98d0640e657e63b0be8a")
震波_III = Animation_meta("震波 III", True, 0.733, "7289005562124046907", "25555607", "59a06bc5a9bfe9c395d45f05ae38435a")
立体翻转 = Animation_meta("立体翻转", True, 1.100, "7351333213068857892", "53792520", "82f13f68eb475cfaabaf2a674b50ac8a")
流金 = Animation_meta("流金", True, 1.133, "7322857522648322586", "39682247", "646fc008978735fbf5b5d3cde382fc22")
划水 = Animation_meta("划水", True, 0.800, "7226632692354257445", "12811717", "f30ab9f83934eafedb4ee01a3d87a995")
发光矩形 = Animation_meta("发光矩形", True, 1.133, "7346510998771077659", "51093596", "ccac330a683da920a9638b597ce1f869")
玻璃爆开 = Animation_meta("玻璃爆开", True, 0.733, "7347865496508699170", "51922869", "620f6fe34184e1f3cc2284d830c3d1e8")
转圈圈 = Animation_meta("转圈圈", True, 0.800, "7246706359381529125", "15754757", "c03fc00075c5b7e53f8bdc0c6f5c360f")
烟雾弹 = Animation_meta("烟雾弹", True, 0.900, "7229149181762343484", "13090999", "e70e26e7aa770d0deedca54e3eac0323")
闪现 = Animation_meta("闪现", True, 0.250, "7186978468087730749", "8303609", "f170e9020eaf5a6f6180c6fd30775400")
圆形闭幕 = Animation_meta("圆形闭幕", True, 0.900, "7218210114052821561", "11680737", "0acd6d992db52febb66a63a3cfc6ea00")
飘散 = Animation_meta("飘散", True, 2.000, "7305957010518839846", "31245441", "286553fb78795b8044746938e4327d5e")
闪屏 = Animation_meta("闪屏", True, 0.833, "7243999104114627132", "15215961", "e4ef6b01ae37409046d089c73cd16702")
老电视 = Animation_meta("老电视", True, 1.600, "7283429462924857914", "24079477", "50d67778f791d56b12ab5c6da30c37b6")
向上闪出 = Animation_meta("向上闪出", True, 0.700, "7273389599978689079", "21816912", "4e39075df8d20d1d938c5bf23b2604fb")
交错闭幕 = Animation_meta("交错闭幕", True, 1.100, "7280797214186672701", "23387942", "1804a8bb6a3eb61c8e5720428d4648e7")
心形缩小 = Animation_meta("心形缩小", True, 1.000, "7034346969086562824", "1463778", "677ec2564241df326a921fa9dc58bd81")
水墨 = Animation_meta("水墨", True, 2.033, "7322073757080621606", "39326538", "32664ec43aa94c7861104f4e4d401113")
折叠 = Animation_meta("折叠", True, 0.300, "7221420528148419133", "12091673", "7968ce8b7391c3725f2b7667d0e0f80a")
画出爱心 = Animation_meta("画出爱心", True, 1.100, "7248951676420231735", "16231427", "ad5c127255cc8f2c941f7406f8a36f19")
侧滑 = Animation_meta("侧滑", True, 0.400, "7239559574095663671", "14524385", "1a661b1d0728177d889353174bfb0bf8")
抖动横移 = Animation_meta("抖动横移", True, 0.400, "7265946879060349477", "20437843", "bcebbe81fc2243a3685ab8e550e3415f")
便利贴 = Animation_meta("便利贴", True, 0.800, "7379884133268328996", "70741835", "ce8f5846f77edba5099b042ef7b6958b")
拼图 = Animation_meta("拼图", True, 1.100, "7369889275233440265", "64963293", "9e1b296804c2f10ce26fcf727d1dd9af")
向下甩动 = Animation_meta("向下甩动", True, 1.000, "7338638617322983976", "47191669", "178fe900252c316f5301d805a735ce8e")
脉冲 = Animation_meta("脉冲", True, 0.800, "7379909625870553654", "70764127", "f916cc354e9c5b80698d612397a0c4f7")
向上滚动 = Animation_meta("向上滚动", True, 1.000, "7312341715220697650", "34388502", "92d44450f8557fc1d8d93eb6cbe2a832")
拉丝滑出 = Animation_meta("拉丝滑出", True, 0.500, "7114172789287817758", "3240292", "e3018d5ee625a58fdeaa5ccd75d0e2e2")
波纹弹动 = Animation_meta("波纹弹动", True, 1.200, "7345803511390540288", "50691424", "660ff84eabd735769a72978914e8e82d")
快速翻页 = Animation_meta("快速翻页", True, 0.200, "7296416099606729225", "27895223", "00b26549833daf565f2660d0abcb0462")
荧光爆闪 = Animation_meta("荧光爆闪", True, 0.800, "7347994415576650255", "52020801", "6558ab016ce06546d3c380b43480baab")
模糊聚焦 = Animation_meta("模糊聚焦", True, 0.833, "7338742568592609801", "47267179", "2cf9380884a5e9853ecdbb4869b01b0e")
抖动变焦 = Animation_meta("抖动变焦", True, 0.500, "7153942002696983047", "5188733", "6e14698c240bfa454836d26eaa44d3bc")
爱心碰撞 = Animation_meta("爱心碰撞", True, 2.300, "7328249133079204352", "42112174", "1cf69aac7b9478f5628413aada8c0707")
class Group_animation_type(Effect_enum):
"""剪映自带的视频/图片组合动画类型, 组合动画一般与视频片段等长"""
# 免费
三分割 = Animation_meta("三分割", False, 0.500, "6873360856541827591", "922958", "8eec0e58254ae6906c085ffc36570d6f")
三分割_II = Animation_meta("三分割 II", False, 0.500, "6873360923646497293", "922957", "42db12dd4ef8bdc4098ba3fd321c1de9")
上下分割 = Animation_meta("上下分割", False, 0.500, "6875935836177699335", "931224", "18312916ab04e01f4aa11f58075a86bb")
上下分割_II = Animation_meta("上下分割 II", False, 0.500, "6875935919661126157", "3144548", "2b773c5e2856fac177f9ce4b39a87b74")
上升旋转 = Animation_meta("上升旋转", False, 0.500, "6813965595915063815", "691841", "45d026e340219c0caae01e8c9e0260ba")
下降向右 = Animation_meta("下降向右", False, 0.500, "6781683518222111239", "503140", "545ed5bde7166e5e18aa5e4ba9662348")
下降向左 = Animation_meta("下降向左", False, 0.500, "6759351225772151303", "446392", "2ba01976cbb05f3a22bea55ee5fcf3c3")
中间分割 = Animation_meta("中间分割", False, 0.500, "6856970350270353928", "871868", "39118319d1910ecf60eae3e8c0871e6e")
中间分割_II = Animation_meta("中间分割 II", False, 0.500, "6856970411352003080", "871867", "d35d05906c0ffe288964f33d96cbbe14")
叠叠乐 = Animation_meta("叠叠乐", False, 0.500, "6836319728038842894", "872824", "63c0c0634a0c5f99ec74f839421018b0")
叠叠乐_II = Animation_meta("叠叠乐 II", False, 0.500, "6836319649844433415", "872826", "464c1a4bb1176029ffa3f1b6b7ae25be")
叠叠乐_III = Animation_meta("叠叠乐 III", False, 0.500, "6836319781004513805", "872828", "8c55f6c4f5abf7d41e55a77fc8f5fdad")
叠叠乐_IV = Animation_meta("叠叠乐 IV", False, 0.500, "6836319828656001550", "872830", "1b59e3f39c921c7b45f2cfa2daa6c71d")
叠叠乐_V = Animation_meta("叠叠乐 V", False, 0.500, "6836319888827486728", "872834", "9d5c1a042586999b720b9c4582f15256")
叠叠乐_Ⅵ = Animation_meta("叠叠乐 Ⅵ", False, 0.500, "6839582631345000967", "872836", "1c05ec01a8c9e8fc640a7b095ccf361d")
右拉镜 = Animation_meta("右拉镜", False, 0.500, "6772415374165021191", "471347", "0be1223dd51448374c28708e46c2f068")
向右下降 = Animation_meta("向右下降", False, 0.500, "6781683438396117517", "503138", "8941aec6123fd5424c3514402e3de777")
向右缩小 = Animation_meta("向右缩小", False, 0.500, "6772415063216099848", "471341", "3367a84172585bcfeaf4c3bb2e16bb79")
向左下降 = Animation_meta("向左下降", False, 0.500, "6760223716392571395", "447588", "c764dfbf9f82b935b807bc4420af4821")
向左缩小 = Animation_meta("向左缩小", False, 0.500, "6772415148423385607", "471343", "90c156e54a3a2c68ff282f17197e8403")
哈哈镜 = Animation_meta("哈哈镜", False, 0.500, "6832226792556728846", "748348", "eee5d8c1dd9be05badb8fecc9ec7b977")
哈哈镜_II = Animation_meta("哈哈镜 II", False, 0.500, "6832226909875606029", "748350", "87fce972209bc94afafbdaff1a806c00")
四格滑动 = Animation_meta("四格滑动", False, 0.500, "6883727868451361293", "945730", "591071275e1a96b5a82ff9c95e47d23e")
四格翻转 = Animation_meta("四格翻转", False, 0.500, "6865578846393995784", "1362932", "88c1ed96cfa3f182a341c27adc7edfdb")
四格转动 = Animation_meta("四格转动", False, 0.500, "6891835548688716302", "957940", "d6b09575f3c468b2c9b15ad3e149bad7")
四格转动_II = Animation_meta("四格转动 II", False, 0.500, "6891835601067184653", "957939", "696b72074b5476f6912d2f75c9ac923f")
回弹伸缩 = Animation_meta("回弹伸缩", False, 0.500, "6795425591014199822", "530249", "b55a407d406d39c8c34dd69178fa6699")
夹心饼干 = Animation_meta("夹心饼干", False, 0.500, "6868146033247916558", "1362936", "23091e7d56610c4253a186488657cd30")
夹心饼干_II = Animation_meta("夹心饼干 II", False, 0.500, "6868146123710665223", "1362934", "09b29b56757a17ad7ca31a57eb8b5726")
小火车 = Animation_meta("小火车", False, 0.500, "6860405888784536072", "885144", "d80771b2b33136a2b531f13bad536e08")
小火车_II = Animation_meta("小火车 II", False, 0.500, "6860406007160377863", "885143", "60609f186f005e47d27b29aa040dcc39")
小火车_III = Animation_meta("小火车 III", False, 0.500, "6860406091700769293", "885142", "e41a0312ec6ca0932ba92c163f4ad4f9")
小火车_IV = Animation_meta("小火车 IV", False, 0.500, "6860406196130550286", "885141", "e5ef14b6031eba52e9be8ff9092e093b")
小陀螺 = Animation_meta("小陀螺", False, 0.500, "6874487656969933325", "923592", "720beb8cd875bc9bb10b63515d9ac2d6")
小陀螺_II = Animation_meta("小陀螺 II", False, 0.500, "6874487735059485198", "923591", "95c42369d9e1d09e3b2d453ac0906245")
左右分割 = Animation_meta("左右分割", False, 0.500, "6886282872680878599", "948476", "3744ef4eef4fadb4630dc0674169c3d0")
左右分割_II = Animation_meta("左右分割 II", False, 0.500, "6886282936048423431", "948475", "9b880a7edbe927fd0da9a0f94829740f")
左拉镜 = Animation_meta("左拉镜", False, 0.500, "6772415248973435395", "471345", "49104c483b8eaa891e71e7a2b20c3c41")
弹入旋转 = Animation_meta("弹入旋转", False, 0.500, "6810286558826992136", "669963", "8c3498b2994796590e6d21d319a459e4")
形变右缩 = Animation_meta("形变右缩", False, 0.500, "6851395907804467720", "813139", "79bfe1364728f28383b5a4436d7a801e")
形变左缩 = Animation_meta("形变左缩", False, 0.500, "6851395726937690637", "813140", "1455b7f8a6e2970538e97046e6f2922b")
形变缩小 = Animation_meta("形变缩小", False, 0.500, "6777260789263766030", "487587", "8fb2439ce140bde6d46e40740ec29a8d")
悠悠球 = Animation_meta("悠悠球", False, 0.500, "6821451358101574152", "717346", "900be5954b07d6ef66eb6fec1606e19c")
悠悠球_II = Animation_meta("悠悠球 II", False, 0.500, "6821451462904648200", "717348", "210abff7a9bb030bef04e47317783089")
手机 = Animation_meta("手机", False, 0.500, "6861892418334102030", "1362928", "55fd386ec6f779110e3b12b89deaa79c")
手机_II = Animation_meta("手机 II", False, 0.500, "6862918279183208973", "1362926", "b861f8270870663e5c3f8bbb1fced93a")
手机_III = Animation_meta("手机 III", False, 0.500, "6862918366550561294", "1362924", "e056d0f8601d91d70e20e61bd63793f5")
扭曲拉伸 = Animation_meta("扭曲拉伸", False, 0.500, "7026278592623415822", "1426278", "ca0a43e525601adf9d14089393610d9c")
抖入放大 = Animation_meta("抖入放大", False, 0.500, "6761360765925462536", "450264", "8c01759b6ace838086122b8e2b4fc0aa")
拉伸扭曲 = Animation_meta("拉伸扭曲", False, 0.500, "7025952723027628557", "1425496", "39862f9fa5c934d72d36923f2368de4a")
放大弹动 = Animation_meta("放大弹动", False, 0.500, "7023931891363353101", "1418682", "18bfc84500372c9a49023c1a77efa6e5")
斜转 = Animation_meta("斜转", False, 0.500, "6847734302193488392", "872874", "4cc2597d961bafbd3c7877bc3f75f79a")
斜转_II = Animation_meta("斜转 II", False, 0.500, "6847734360636920327", "872876", "b37e163c186d88db144aacd6280c0811")
方片转动 = Animation_meta("方片转动", False, 0.500, "6897114113726485000", "968162", "dfc6082d56863c5e700a0a5a17102abc")
方片转动_II = Animation_meta("方片转动 II", False, 0.500, "6897114201702011405", "968161", "afdb5e78ddf7d480e78cabb527db9241")
旋入晃动 = Animation_meta("旋入晃动", False, 0.500, "6789167874511475207", "519840", "0ee3fc24d73d3d32a666c46c7f574431")
旋出渐隐 = Animation_meta("旋出渐隐", False, 0.500, "6824302025698710024", "719940", "13d85c4e8be67525a1e567121aa68170")
旋转上升 = Animation_meta("旋转上升", False, 0.500, "6813965670716281352", "691843", "56e36c8a8602ef9d2634b173ba95c75d")
旋转伸缩 = Animation_meta("旋转伸缩", False, 0.500, "6795425422046663182", "530247", "131794c7a6f15ecfde066b5e4d4e6f35")
旋转回吸 = Animation_meta("旋转回吸", False, 0.500, "6810286613898203661", "669965", "bce87aa9bfbabc1e8c97ed122fa16f49")
旋转缩小 = Animation_meta("旋转缩小", False, 0.500, "6759046644462785037", "445858", "3ae63cabefdc45ff05fb30def814c79b")
旋转降落 = Animation_meta("旋转降落", False, 0.500, "6759046515521491464", "445856", "8099feb138226b21ec8ae0a64313fa83")
晃动旋出 = Animation_meta("晃动旋出", False, 0.500, "6789167998700622350", "519842", "5b25fea3f8bd82496e39be0bb590726c")
水晶 = Animation_meta("水晶", False, 0.500, "6857333749718192654", "1362920", "de28fd5ff1c5fa607cc09306a5de1fc9")
水晶_II = Animation_meta("水晶 II", False, 0.500, "6857333869541069325", "1362922", "66d0f40fad32ba15e72d6687f12604f8")
波动滑出 = Animation_meta("波动滑出", False, 0.500, "7017646605671076359", "1392376", "c546f43ce65a4977ee11010063ee7b50")
海盗船 = Animation_meta("海盗船", False, 0.500, "6830302168751280648", "1362866", "271eda8d9ae3ff3435206719f32a6c05")
海盗船_II = Animation_meta("海盗船 II", False, 0.500, "6830302282995732999", "1362868", "13f077dc64c6c938dd8e755b0f9529bd")
海盗船_III = Animation_meta("海盗船 III", False, 0.500, "6830302335047045639", "1362872", "378d4ce23f6069e6e0752ccd6b201292")
海盗船_IV = Animation_meta("海盗船 IV", False, 0.500, "6830302424826122765", "1362870", "8bef9d70f593dfa3566ba04e8c19316b")
滑入波动 = Animation_meta("滑入波动", False, 0.500, "7023747922718102023", "1418546", "7c4a80c235da2050b672f66a0a9e54b3")
滑滑梯 = Animation_meta("滑滑梯", False, 0.500, "6828829568879563271", "741020", "45a18cb8ead63a3b6a87731adf6ac79e")
滑滑梯_II = Animation_meta("滑滑梯 II", False, 0.500, "6828829741013799432", "741022", "9c669766b045f246772095114c5ef594")
百叶窗 = Animation_meta("百叶窗", False, 0.500, "6771299961171612174", "467361", "f6f38be419308a9134467d26829576af")
百叶窗_II = Animation_meta("百叶窗 II", False, 0.500, "6782101071402635790", "506768", "9812eeaceca9d8a1adba077c8c35c06b")
碎块滑动 = Animation_meta("碎块滑动", False, 0.500, "6778405418969338382", "490068", "218746bfacd737cf075912452a10100d")
碎块滑动_II = Animation_meta("碎块滑动 II", False, 0.500, "6778300107113632269", "489860", "1abb69885123e9c59fe5f872c586d17a")
立方体 = Animation_meta("立方体", False, 0.500, "6837352063496622599", "872856", "71ae450afeb88ae2620473ab790acf0e")
立方体_II = Animation_meta("立方体 II", False, 0.500, "6834812485023830535", "872858", "efc0e23b864f5fcfbaa77723044c4957")
立方体_III = Animation_meta("立方体 III", False, 0.500, "6834812541118452237", "872860", "dfc2e372bc454764f0b355904542e228")
立方体_IV = Animation_meta("立方体 IV", False, 0.500, "6841793140949520910", "872864", "c66bf1692fe1e6bd6dd2e49eddfcd0c0")
立方体_V = Animation_meta("立方体 V", False, 0.500, "6841793224663634446", "873096", "e3935dbcaf28be18a598eebb8fb79161")
绕圈圈 = Animation_meta("绕圈圈", False, 0.500, "6850287838441771534", "872868", "98bfd8ca3177b85246b18502832232f0")
绕圈圈_II = Animation_meta("绕圈圈 II", False, 0.500, "6850287920255865357", "872872", "10eaa3db7b761a9846764a53912d7c77")
绕圈圈_III = Animation_meta("绕圈圈 III", False, 0.500, "6854782718975152653", "872918", "c2e7ff02916f19a13ada361abddb8f98")
绕圈圈_IV = Animation_meta("绕圈圈 IV", False, 0.500, "6854782786553778695", "872920", "1e7d503bcf05a17f175759e5c6cfbe7b")
缩小弹动 = Animation_meta("缩小弹动", False, 0.500, "7017689072978104869", "1392530", "bca5ca47f6f33268fb1de55fa8946519")
缩小旋转 = Animation_meta("缩小旋转", False, 0.500, "6760119657429996046", "447318", "b5791968245b8246c3e87e4d9816cd3b")
缩小转出 = Animation_meta("缩小转出", False, 0.500, "6805018974070247950", "638823", "08ab26276c336b284d07b336d5c32aad")
缩放 = Animation_meta("缩放", False, 0.500, "6759078592740594184", "446078", "091f668bbb6406305614f9de55bf4aa6")
缩放_II = Animation_meta("缩放 II", False, 0.500, "6779083172429697544", "493000", "bb460b0c6a3c424618718276b25a812b")
翻转 = Animation_meta("翻转", False, 0.500, "6843309964732142094", "872838", "5f153d35f1c3098fef8325badc40c5e8")
翻转_II = Animation_meta("翻转 II", False, 0.500, "6843310029689328135", "872840", "befc44f24a2747201d1d75e6a29753ce")
翻转_III = Animation_meta("翻转 III", False, 0.500, "6843310084743762446", "872842", "b8167fc9e9deb2f638788bfc7539ed7f")
翻转_IV = Animation_meta("翻转 IV", False, 0.500, "6843310129736061447", "872844", "9636ccab84e8f2c357812a38b785f6e0")
翻转_V = Animation_meta("翻转 V", False, 0.500, "6843310237902967304", "872848", "4d27983b5b2899b46334d3fd999bc7d8")
翻转_VI = Animation_meta("翻转 VI", False, 0.500, "6843310299991249421", "872850", "8807b174b58ee897667c08e6bee1a4f8")
荡秋千 = Animation_meta("荡秋千", False, 0.500, "6811007755785081357", "680643", "565256202d17fda9af7f56e27d099543")
荡秋千_II = Animation_meta("荡秋千 II", False, 0.500, "6811007833069326862", "680645", "212f5f11d11ee19690df59a096b7c3f8")
转入转出 = Animation_meta("转入转出", False, 0.500, "6805012562174808590", "638793", "3d26d9df896b72d5ac3926828afcd791")
转入转出_II = Animation_meta("转入转出 II", False, 0.500, "6818747242258633224", "701967", "ec4ed56911472b95462e4b0b8ac6a103")
转圈圈 = Animation_meta("转圈圈", False, 0.500, "6829129745226011144", "741502", "40d9b656e338f39f8eb2a7d27a85e036")
过山车 = Animation_meta("过山车", False, 0.500, "6870060878234915342", "911862", "64e30d2e2577f6a95313ed806807baa7")
过山车_II = Animation_meta("过山车 II", False, 0.500, "6870060932928639501", "911861", "240042ee2b35aaa7f30b6e0c03e9ac4c")
降落旋转 = Animation_meta("降落旋转", False, 0.500, "6759075297091392007", "446076", "c5c1d37924b58b5c1e5355db14e72372")
魔方 = Animation_meta("魔方", False, 0.500, "6870060995365048840", "1362938", "b104d21e0f1b7eb044946f6bf0be1133")
魔方_II = Animation_meta("魔方 II", False, 0.500, "6870061049559650829", "1362940", "53bc750124a30d746adbf44151116fde")
# 付费
分身 = Animation_meta("分身", True, 0.500, "6883761132645913096", "945872", "de31f6d54856f05a0824eab7afac58e7")
分身_II = Animation_meta("分身 II", True, 0.500, "6883761226950644231", "945871", "22ce9336e5716a87d6a2a980f6b84e78")
动感摇晃I = Animation_meta("动感摇晃I", True, 0.500, "7173927429394666020", "6983415", "ceb6b5bf10aab23f1066481cefd5adfb")
动感摇晃II = Animation_meta("动感摇晃II", True, 100.000, "7175103054956466744", "7129471", "4e88c30adc92ca2809d285ab67276467")
四格滑动_II = Animation_meta("四格滑动 II", True, 0.500, "6883727923845534216", "945729", "e8d17f7948b2805f284d82d6a6992302")
四格翻转_II = Animation_meta("四格翻转 II", True, 0.500, "6865579178599649806", "1362930", "840aa022c0a9b3b6b4876dd7084372b7")
回忆旋转 = Animation_meta("回忆旋转", True, 0.500, "7186961278022193722", "8300599", "fa3c068a56733a2149d5c0d03560aad8")
坠落 = Animation_meta("坠落", True, 0.500, "7235902373971890747", "14020637", "0049e2c104b1ae46dbf717ea73b71234")
弹动冲屏 = Animation_meta("弹动冲屏", True, 0.500, "7200308690904158778", "9491799", "cc01a66ec4b316b7342fe8fd5cfe5e87")
波动吸收 = Animation_meta("波动吸收", True, 0.500, "7107468232390349349", "2786424", "ddbc0f962c69263480e6d188bf2f4b63")
波动放大 = Animation_meta("波动放大", True, 0.500, "7111631619768717860", "3113716", "90f87e49deba3845d73b5855dc3fa442")
相框滑动 = Animation_meta("相框滑动", True, 0.500, "7206139216038728248", "10166295", "517a71d78782ebc9a9718acfb865fba9")
红酒摇晃 = Animation_meta("红酒摇晃", True, 0.800, "6903771548436402702", "1417022", "95d79896a437524c4f94dc2902bb3b6c")
跳跳糖 = Animation_meta("跳跳糖", True, 0.700, "7199944821098680890", "9432783", "fc4e0cc6a2f2c775659fa9493cff9fe8")
闪光放大 = Animation_meta("闪光放大", True, 0.500, "7166437469909422623", "6210029", "a6495ac2010a3caae003517edcc1d5bc")
闪光放大_II = Animation_meta("闪光放大 II", True, 0.500, "7166437532568130055", "6210033", "90ad69d3ad224c6e7234ad9ba9eb1467")
class Text_intro(Effect_enum):
"""文字入场动画, 默认时长为0.5秒"""
# 免费
冲屏位移 = Animation_meta("冲屏位移", False, 0.0, "7078181271393800711", "1643884", "fd73ffc26a3f02fa6d957a94b590623a")
卡拉OK = Animation_meta("卡拉OK", False, 0.0, "6771294855785091588", "1558840", "a6d37c370a463070046c5d9feb0f9dfb")
变色输入 = Animation_meta("变色输入", False, 0.0, "7397306443147252233", "77035159", "e0e29d6ea015f0d1d38b4a852a1b6202")
右上弹入 = Animation_meta("右上弹入", False, 0.0, "7074854080388010532", "1621978", "932ea0a91ca337bc1fd566aa17cb9aa7")
右下擦开 = Animation_meta("右下擦开", False, 0.0, "7088576340361744903", "1715294", "70a3ffbff2b02ede796ee38d95b38db2")
向上擦除 = Animation_meta("向上擦除", False, 0.0, "6774625910067827212", "1644272", "ee74a3a8afb2167f4403dee957338afe")
向上滑动 = Animation_meta("向上滑动", False, 0.0, "6763470111253729803", "1644267", "22030c473076074288fd01b17d1c6174")
向上翻转 = Animation_meta("向上翻转", False, 0.0, "7194703971498332727", "8945307", "0cf2050093a2bbe736ab4b2ee9002dcf")
向上重叠 = Animation_meta("向上重叠", False, 0.0, "7077500533040222756", "1639676", "b3ea1be4937b7cd032f1775d98b1f06e")
向上露出 = Animation_meta("向上露出", False, 0.0, "7163514358935327268", "5925717", "3786ff3fcc9795eead5fd5629ff7e4e9")
向下擦除 = Animation_meta("向下擦除", False, 0.0, "6774626192990409224", "1644273", "bfe1add2d59ee32449a979257d4a3448")
向下滑动 = Animation_meta("向下滑动", False, 0.0, "6724921985282871816", "1644268", "f5506a1b5ebcf9d0636d7809bf3cb81a")
向下露出 = Animation_meta("向下露出", False, 0.0, "7163514502128865823", "5925716", "a7b05a11c6bdc7010cc4dc7f1d276407")
向下飞入 = Animation_meta("向下飞入", False, 0.0, "7088942186561016356", "1719670", "b312472b5a680f49d2d1229cfe07f49d")
向右擦除 = Animation_meta("向右擦除", False, 0.0, "6771288500240126478", "1644271", "b4a5ba027822ca3e1c9d83d2f5a58a08")
向右滑动 = Animation_meta("向右滑动", False, 0.0, "6724920136056181256", "1644266", "c49f75ef6e0f886e570f68a00f7c1312")
向右缓入 = Animation_meta("向右缓入", False, 0.0, "7043778124760224292", "1488722", "2d751bb706b38a030ab7eb3382b2d248")
向右集合 = Animation_meta("向右集合", False, 0.0, "7081206983461704199", "1661186", "5a78f1024ecdc9a6b69220eac58a0963")
向右露出 = Animation_meta("向右露出", False, 0.0, "7163514730525495839", "5925714", "6f8e0a5cd98c44b79f9ec09b0b913059")
向左擦除 = Animation_meta("向左擦除", False, 0.0, "6774626830038077960", "1644270", "4db856992dc60d1220664165d4130042")
向左滑动 = Animation_meta("向左滑动", False, 0.0, "6763470195894784525", "1644277", "13c954ed3bc583f87e9f79a2325b8e84")
向左露出 = Animation_meta("向左露出", False, 0.0, "7163514612690719269", "5925715", "b4119cf3405c71bc556e1c5562e22d01")
圆形扫描 = Animation_meta("圆形扫描", False, 0.0, "6840689010034086407", "1644280", "ac77daf80de65a4beb1164ce44c500c5")
复古打字机 = Animation_meta("复古打字机", False, 0.0, "7253888335163167291", "17639720", "a69db3276f15fa2affcd98f2236c873d")
居中打字 = Animation_meta("居中打字", False, 0.0, "7265222187286532667", "20303987", "40f484d3b77321b38d53b30d94c2dce1")
左上弹入 = Animation_meta("左上弹入", False, 0.0, "7078586233030447629", "1646760", "6467514ec2a8740953d29c3915364a31")
左移弹动 = Animation_meta("左移弹动", False, 0.0, "7313890082040058406", "35176342", "c21d4019453137cd76e0d847d5d8af96")
开幕 = Animation_meta("开幕", False, 0.0, "6835571502050447879", "1644279", "99a6fdf1f3b43b15b70c31427e09c8a5")
弹入 = Animation_meta("弹入", False, 0.0, "6887482184844710413", "1644313", "0533e3aeb2cda562cdd8a86693815443")
弹弓 = Animation_meta("弹弓", False, 0.0, "6862897343176380942", "1644305", "f9300b314e5bd7df573063b15a1ab081")
弹性伸缩 = Animation_meta("弹性伸缩", False, 0.0, "6872642189260755463", "1644311", "7d23b7a68a1bf21c7692a35ffa6ddcdc")
弹簧 = Animation_meta("弹簧", False, 0.0, "6884154692398486023", "1644312", "34d74f1bf451dac1a23158380a5be322")
彩色映射 = Animation_meta("彩色映射", False, 0.0, "7039655272222036516", "1476514", "46f37098540b9250abdad9bb1282ec83")
打字机_I = Animation_meta("打字机 I", False, 0.0, "6724920249654710791", "1644275", "7c7cfe92aa22a8e131c94d20f44e97df")
打字机_II = Animation_meta("打字机 II", False, 0.0, "6724920636403094028", "1644276", "42996c18d556c4de18cc3dc2c7387158")
打字机_III = Animation_meta("打字机 III", False, 0.0, "6724920521462387207", "1644335", "1b21dfb54b0ccd50e50f383f01d0a193")
打字机IV = Animation_meta("打字机IV", False, 0.0, "7237409385092223525", "14235879", "6828d67634e66ace1e76c4eb7cc2f8e6")
扭曲模糊 = Animation_meta("扭曲模糊", False, 0.0, "7089261793406620197", "1722114", "40a9fd02e81930bc0289aeb692c382f6")
拖尾 = Animation_meta("拖尾", False, 0.0, "7244102915239973432", "15259479", "40884dac1fc802d207c69b05e2987d4d")
收拢 = Animation_meta("收拢", False, 0.0, "6779879712261935619", "1644261", "b173da2fb68d5f8e7dbb2cc000a50bdd")
放大 = Animation_meta("放大", False, 0.0, "6724919499042066958", "1644264", "cf0f072aa31d3884ba90362af063f55a")
故障打字机 = Animation_meta("故障打字机", False, 0.0, "6870061463243854350", "1644308", "b4536942105b69e637dabef4c3ebfc6d")
旋入 = Animation_meta("旋入", False, 0.0, "6763873859402732039", "1644265", "dc3a54158c51f45a0033a16f5763e047")
日出 = Animation_meta("日出", False, 0.0, "6779084126457696776", "1644269", "9e39257e0d8b60598d1c09bb31fbc62a")
晕开 = Animation_meta("晕开", False, 0.0, "7088531060341871141", "1714696", "2f7aebf0f525ef21f8b00070c17d2fc2")
模糊 = Animation_meta("模糊", False, 0.0, "6923094735116571150", "1644338", "0e57ec99758f1e12636a73c6ec4fb6f5")
水墨晕开 = Animation_meta("水墨晕开", False, 0.0, "7278295995362841145", "22734325", "5c970b17e18e3441b917a7bcba4d043b")
水平翻转 = Animation_meta("水平翻转", False, 0.0, "7051512227353858590", "1644340", "9403a81925b4886589f745130a67cb05")
波浪弹入 = Animation_meta("波浪弹入", False, 0.0, "6917178744775905806", "1644316", "301272b44278c3b5ebe228e8baa8d984")
渐显 = Animation_meta("渐显", False, 0.0, "6724916044072227332", "1644304", "40859aa05ff9f3e3a3f0de7bfead1c42")
溶解 = Animation_meta("溶解", False, 0.0, "6872642398095151629", "1644310", "162408e430501a31662f901c51476e59")
滑动上升 = Animation_meta("滑动上升", False, 0.0, "7275687883011265083", "22226771", "9ab223e5e9a0b9611b04062048173de9")
生长 = Animation_meta("生长", False, 0.0, "6869302248103481869", "1644307", "b0f76f716f571ecde209056995e96978")
甩出 = Animation_meta("甩出", False, 0.0, "7244102679851438650", "15261071", "97162e8faa56cf163b8f2c1bfd5ad6e0")
站起 = Animation_meta("站起", False, 0.0, "7265288917279052344", "20324364", "6f322d7bb7fe6b443197c2bf5d64dd8b")
缩小 = Animation_meta("缩小", False, 0.0, "6724921217721045515", "1644263", "0b58ad7d0d7cc93080e7bedfd0caa222")
缩小_II = Animation_meta("缩小 II", False, 0.0, "7041836555903701540", "1644341", "ae803da2a5d2292e0f8be3c8ab3b3788")
羽化向右擦开= Animation_meta("羽化向右擦开", False, 0.0, "6897084405781631496", "1644314", "d330712b8f96ce33d450489ea6e459a3")
羽化向左擦开= Animation_meta("羽化向左擦开", False, 0.0, "6897084292908716557", "1644315", "a4eefe0afe41cd05acd1beb3d2615b23")
翻动 = Animation_meta("翻动", False, 0.0, "7308278898330964489", "32283659", "c863f3afe0d73cccc19188d6313b1dae")
轻微放大 = Animation_meta("轻微放大", False, 0.0, "6763469998330483213", "1644262", "6f5ec0bb82bfd24a72706e2006c0e806")
逐字旋转 = Animation_meta("逐字旋转", False, 0.0, "7111643562676064805", "3114660", "17a78b3b5c193a3e30431946a8cbd696")
逐字显影 = Animation_meta("逐字显影", False, 0.0, "7038882772450021896", "1644339", "2f250516dcea1a591656dabc9c40684f")
逐字翻转 = Animation_meta("逐字翻转", False, 0.0, "7112241904216969765", "3138860", "cdf2df541dea807f4bcb29ede73dd766")
闪动 = Animation_meta("闪动", False, 0.0, "7035902226602136071", "1644322", "8a1581c846a5933e8a90204219504892")
随机弹跳 = Animation_meta("随机弹跳", False, 0.0, "7021831463867781662", "1644321", "d49f117c117e7d6b4dcb53bbe9b5ed4a")
随机飞入 = Animation_meta("随机飞入", False, 0.0, "6872642542765085191", "1644309", "d9ad3796df2b0881ea144f8dfa44e0b1")
# 付费
乱码故障 = Animation_meta("乱码故障", True, 0.0, "7325648367747338802", "40877554", "00b40103690bfb45e0125592b6ec0f5c")
二段缩放 = Animation_meta("二段缩放", True, 0.0, "7238519092997526074", "14394713", "a4cba6840c1bf92bc73bb1bcacf7b76e")
便利贴 = Animation_meta("便利贴", True, 0.0, "7307207886843679283", "31819229", "4e9265ea4703be87feaf640d79b23f7c")
倒数 = Animation_meta("倒数", True, 0.0, "7314303157360661018", "35401566", "814df0b29746943fe165ae9b16719cc2")
兔子弹跳 = Animation_meta("兔子弹跳", True, 0.0, "7187785892382118461", "8398145", "5d157129853f479ea15f75075c1ef070")
冰雪飘动 = Animation_meta("冰雪飘动", True, 0.0, "7314291622525538843", "35395178", "69dcdf8547a23b2cc92e566ab5e266ec")
发光闪入 = Animation_meta("发光闪入", True, 0.0, "7308272157442707978", "32278776", "bf803f5695c3775cd2e58797c9c8d229")
叠影并入 = Animation_meta("叠影并入", True, 0.0, "7259634012774208059", "19101418", "8358578022cd14c6232a99ddee035824")
向上弹入 = Animation_meta("向上弹入", True, 0.0, "7123116334677758501", "3704299", "28d9145ead32c23742082a37e511370e")
向下溶解 = Animation_meta("向下溶解", True, 0.0, "7028458557058060831", "1644318", "09fde2de891d18c74949e025bc0dca07")
向右模糊_II = Animation_meta("向右模糊 II", True, 0.0, "7254503374622560828", "17830700", "6b3c54ef781f16f20204d766b799abec")
向左模糊 = Animation_meta("向左模糊", True, 0.0, "7112368349257929230", "3147126", "ee5716b5bf9ef16fd99dd7d2d89dbefc")
吸入 = Animation_meta("吸入", True, 0.0, "7120438380453696031", "3576973", "42a0c7e42275986d92a2d3bbe55dd816")
呐喊声波 = Animation_meta("呐喊声波", True, 0.0, "7199943069385364005", "9432429", "6f5992c1f47cac9d33468c5e60725d0b")
喷绘 = Animation_meta("喷绘", True, 0.0, "7120131223036367367", "3563651", "77633d8638e177488dcce84086018c8a")
圆柱体滚动 = Animation_meta("圆柱体滚动", True, 0.0, "7179035729043919397", "7548913", "7ce47010b9b736d12d264cf73f6c294e")
圣诞帽弹跳 = Animation_meta("圣诞帽弹跳", True, 0.0, "7169419861158793759", "6492065", "e5de917f45c938a685b73a9e0bb464e1")
圣诞树弹跳II= Animation_meta("圣诞树弹跳II", True, 0.0, "7174706243267727930", "7080877", "c9be0fbb72056234cdc5f8e082f32c40")
弹入跳动 = Animation_meta("弹入跳动", True, 0.0, "7184797276181631546", "8058189", "18c035845489b1f6c9a4ffcaf0ec1145")
弹性伸缩_II = Animation_meta("弹性伸缩 II", True, 0.0, "7308272646913790490", "32279178", "9b0bdc149bbc541e93cddaf94b1dcaa0")
心动瞬间 = Animation_meta("心动瞬间", True, 0.0, "7332519885999706663", "44271866", "2438d9132c7b04552762ae54066f7d94")
慢速放大 = Animation_meta("慢速放大", True, 0.0, "7205177922280231479", "10063675", "33d85f938bd55928fa16bede8cf7a26b")
打字光标 = Animation_meta("打字光标", True, 0.0, "7237411357514011192", "14235878", "12196518b89652860631d196d19b6f45")
抖动甩入 = Animation_meta("抖动甩入", True, 0.0, "7301945752278798885", "29825712", "8e49d8dde0112aaf071d41e8a56527e1")
折叠 = Animation_meta("折叠", True, 0.0, "7125298122011447816", "3779439", "9f65c45595fa8c0002f7f49a61637ff2")
描边填充 = Animation_meta("描边填充", True, 0.0, "7308269965453300262", "32278219", "cb8300f18fdf8b9aab7c1eacd33e92c9")
放大震动 = Animation_meta("放大震动", True, 0.0, "7267849370727354936", "20801300", "e6f8542e114dcb8b7aea821b1c954941")
故障闪动 = Animation_meta("故障闪动", True, 0.0, "7244101806710592057", "15261571", "f0c64727504b3975b4656ee2b10760fb")
新年打字机 = Animation_meta("新年打字机", True, 0.0, "7272754730684650045", "21711818", "a5aa35ae2b69f85c944074dfeadd6c89")
旋转缩放 = Animation_meta("旋转缩放", True, 0.0, "7243633588493619773", "15140845", "cef0ccebe3406f4c53b64f39825b7bfa")
旋转飞入 = Animation_meta("旋转飞入", True, 0.0, "6775803763652301326", "1644274", "21984d5e90731f925fc58a59fef355ee")
星光闪闪 = Animation_meta("星光闪闪", True, 0.0, "7309036302962266675", "32665781", "269e1b23d766c0a3c5c9f792dedfd1a9")
星光闪闪_II = Animation_meta("星光闪闪 II", True, 0.0, "7319873264375829001", "38428077", "8cddcc9ff610948afbd705259cec8fa9")
星星弹跳 = Animation_meta("星星弹跳", True, 0.0, "7307189517562155547", "31799385", "e5a1520dee5dd3700da60c62743111e4")
模糊发光 = Animation_meta("模糊发光", True, 0.0, "7301535952101446170", "29690460", "ea9d91ad5b58f1f9a1e95264f77e9a15")
模糊滚动 = Animation_meta("模糊滚动", True, 0.0, "7264501462187643450", "20154968", "3eaa7038a9148548a6b2cc6673f77944")
模糊缩小 = Animation_meta("模糊缩小", True, 0.0, "7294147761765618186", "27144470", "203197cc1ea7d4e7dfb0f24bd256e9fd")
汇聚 = Animation_meta("汇聚", True, 0.0, "6986931575199896094", "5529369", "2774ee332a759084eaa558bad0cb3a44")
波浪弹跳 = Animation_meta("波浪弹跳", True, 0.0, "7317536986691015218", "37303562", "e5b79c83b4a12edb15d2389a83c51476")
流光扩散 = Animation_meta("流光扩散", True, 0.0, "7314566361642963493", "35505526", "49e6ab3f128387addaba317fb98cbed3")
滚入 = Animation_meta("滚入", True, 0.0, "7026674824537707038", "1644320", "d631585b87e866b31fe20fa8d578b7cd")
激光雕刻 = Animation_meta("激光雕刻", True, 0.0, "7244102612700631589", "15261101", "affa14b4f89ceb4dd01a69a24b42651f")
爱心弹跳 = Animation_meta("爱心弹跳", True, 0.0, "6845191009861636616", "1644337", "711434e690c1a1d7ebca4f13b1712f85")
玩雪 = Animation_meta("玩雪", True, 0.0, "7304943429962699290", "30904546", "501ea62f0702ab65569aa0e923bd8182")
环绕滑入 = Animation_meta("环绕滑入", True, 0.0, "7261858654561767973", "19562189", "672aae4e963ac36d9b898cb32c964995")
生长_II = Animation_meta("生长 II", True, 0.0, "7210312869282320933", "10659499", "562300bfab6b00c4853118b058f429a2")
电光 = Animation_meta("电光", True, 0.0, "7296051582246851109", "27769111", "04055d0e0520eb74c7047073e98fcf9a")
电光_II = Animation_meta("电光 II", True, 0.0, "7299364098788037171", "28928614", "8c30a310e9ce5bf2b7b5a324c9426b7c")
碰碰车 = Animation_meta("碰碰车", True, 0.0, "7338602211041088027", "47157536", "ce6822887e702ad1a4b762e267148e38")
空翻 = Animation_meta("空翻", True, 0.0, "6865175746420150792", "1644306", "c16d544824d736ad0be1a5e109aafc04")
缤纷冲屏 = Animation_meta("缤纷冲屏", True, 0.0, "7116829842271638053", "3894473", "f6b8859c215e255b61f70cdbcc239b98")
缩放_III = Animation_meta("缩放 III", True, 0.0, "7211036012401660473", "10743073", "d625a4ef458b7e8c5928cdf04ab952ac")
翻页II = Animation_meta("翻页II", True, 0.0, "7170343439832191519", "6599721", "69d372ee41a3c968e0a7b55382eb23ff")
背景滑入 = Animation_meta("背景滑入", True, 0.0, "7306794354255860250", "31601883", "69c170b50c062f8106c01b37682fe19f")
色散拖影 = Animation_meta("色散拖影", True, 0.0, "7340513927651922458", "48159236", "422b57c27cfd659d0756303189e11599")
螺旋上升 = Animation_meta("螺旋上升", True, 0.0, "6799873891352187406", "1644278", "d3e255df67130866e0d2de42a703637c")
跃进 = Animation_meta("跃进", True, 0.0, "7220685840442200634", "11996999", "40bdc1263417f53c712c54cb32438008")
跳跳捣蛋鬼 = Animation_meta("跳跳捣蛋鬼", True, 0.0, "7200340219109839419", "9503089", "897a0c194e07ace6813a2eba797ac22f")
跳跳糖 = Animation_meta("跳跳糖", True, 0.0, "7329815894933115432", "42866461", "c8ecf2f107002df92dcefec6ea988843")
辉光 = Animation_meta("辉光", True, 0.0, "7258179345192063525", "18786330", "cf0046a1d95bfc038ff7982a5dff2abb")
辉光扫描 = Animation_meta("辉光扫描", True, 0.0, "7316878401590006323", "36927710", "f9a2c9ae931b916a81f204a1b9c31f7c")
逐字弹跳 = Animation_meta("逐字弹跳", True, 0.0, "7197615431673188921", "9195301", "52b151b0021d9fa91a42e65c2a392517")
逐字旋入 = Animation_meta("逐字旋入", True, 0.0, "7229520427196879421", "13137035", "9838c6772ddbd48126f30baf74200f99")
金粉飘落 = Animation_meta("金粉飘落", True, 0.0, "7330561002922054196", "43242964", "25d1da238cd78c05757f2d6036dec895")
镂空跳入 = Animation_meta("镂空跳入", True, 0.0, "7311620091060163082", "33984693", "6acf25a6cbbe3f564b4ff1a8c666a10f")
闪烁集合 = Animation_meta("闪烁集合", True, 0.0, "7267886380439573029", "20805754", "6d86be731c4d735a5e612a45b0c8631a")
随机上升 = Animation_meta("随机上升", True, 0.0, "7233662263805088314", "13720553", "98142c53838b5a382f79cc2d89e30c04")
随机弹跳_II = Animation_meta("随机弹跳 II", True, 0.0, "7114189305781686797", "3241034", "ff0761c602fa5ec8cc31c48ce57ea003")
随机打字机 = Animation_meta("随机打字机", True, 0.0, "6926718978064650760", "1644317", "e1f7899554d34dfa3e1e4924f82acc69")
随机落下 = Animation_meta("随机落下", True, 0.0, "7231443875406025275", "13416707", "a3aa7aa5991ef3c6a3d83a2e1fc6b748")
随机集合 = Animation_meta("随机集合", True, 0.0, "7223959789175312954", "12416139", "4d1fa3b7aac9aeab107743db10372029")
雪光模糊 = Animation_meta("雪光模糊", True, 0.0, "7314614905196253705", "35545508", "cb35d22175f67f734290b48bdaf93dd6")
音符弹跳 = Animation_meta("音符弹跳", True, 0.0, "6841115718172283406", "1644336", "86c6e9061b14fd43049b6232ffc113fa")
顶出 = Animation_meta("顶出", True, 0.0, "7268221856618910264", "20880936", "7fd6da0e6ff8a46276648dc43faa4f95")
预览打字 = Animation_meta("预览打字", True, 0.0, "7268152375536259639", "20853726", "964a6cb51a01c0ddeb839010765023a6")
飞入 = Animation_meta("飞入", True, 0.0, "7029231035007111710", "1644319", "9980148af0641a8501561320ec8f967b")
鼠标点击 = Animation_meta("鼠标点击", True, 0.0, "7350128013637325353", "53149407", "1ba2fbaaeb30f7756ecd92e0121b7ac0")
class Text_outro(Effect_enum):
"""文字出场动画, 默认时长为0.5秒"""
# 免费
右上弹出 = Animation_meta("右上弹出", False, 0.0, "7076006676951732767", "1631524", "7b65a6e8a2ef7015dc780dec3524af60")
右下擦除 = Animation_meta("右下擦除", False, 0.0, "7090146831836910110", "1729286", "5e99fcba0a90d5bde52a85e034469aea")
向上擦除 = Animation_meta("向上擦除", False, 0.0, "6774625752794010115", "1644609", "d9b04e37f86d6b5cf456f396648e11d4")
向上溶解 = Animation_meta("向上溶解", False, 0.0, "7026619708627489293", "1644655", "7422f3de89f894522a0b45f3f2196131")
向上滑动 = Animation_meta("向上滑动", False, 0.0, "6763873533115240968", "1644605", "bbec5aa1ddf8df26276b99cfd9996d76")
向下擦除 = Animation_meta("向下擦除", False, 0.0, "6774626081791021576", "1644610", "4dafd6a7cbde862044fcbc543ecd818a")
向下滑动 = Animation_meta("向下滑动", False, 0.0, "6724919284893487619", "1644606", "4b1190ca81551d872f1d6b0e2ce5db2b")
向右擦除 = Animation_meta("向右擦除", False, 0.0, "6783908820176343566", "1644615", "a48325fce55a7a419b351c8a9826c7a0")
向右滑动 = Animation_meta("向右滑动", False, 0.0, "6724920744431587853", "1644614", "4026a211f18b0fc6ab9e10d09c8922ba")
向右缓出 = Animation_meta("向右缓出", False, 0.0, "7023684632591733284", "1451688", "b64ac446b7d95831919258b5799c6b25")
向左擦除 = Animation_meta("向左擦除", False, 0.0, "6774626748177846791", "1644608", "1160d9bcc8a158a65441bcfc9603bd00")
向左滑动 = Animation_meta("向左滑动", False, 0.0, "6763873602476446221", "1644613", "a193ecedf73b2b27616ee7da4f599b9b")
向左解散 = Animation_meta("向左解散", False, 0.0, "7083752251742753287", "1674332", "46b117e1d9fc552e574958fcde072a53")
圆形扫描 = Animation_meta("圆形扫描", False, 0.0, "6840698265277567496", "1644617", "84c8a6772ba3199c3fdba0c171f0f2fc")
居中打字 = Animation_meta("居中打字", False, 0.0, "7265222263174074937", "20304017", "39cf0ff875a8825a82377a11e8b89d6a")
展开 = Animation_meta("展开", False, 0.0, "6779879836916650509", "1644599", "cc9805cb2f96e99eec6c0f1978b03f70")
左上弹出 = Animation_meta("左上弹出", False, 0.0, "7078587337998864926", "1646758", "6cb5717740976cd9e65544d93bb8a8be")
左移弹动 = Animation_meta("左移弹动", False, 0.0, "7313890212529050138", "35176386", "26cd4509db97923ac2fb11eca5947750")
弹出 = Animation_meta("弹出", False, 0.0, "6887482090351235592", "1644648", "ee214499310cb2a55d2370534fd0c02b")
弹弓 = Animation_meta("弹弓", False, 0.0, "6862897350478664200", "1644618", "45f66e1fa1a3b79968b3749275bab10c")
弹性伸缩 = Animation_meta("弹性伸缩", False, 0.0, "6872642084977775118", "1644646", "f2882bcfc0abc3b0c53b39649a2c4224")
弹簧 = Animation_meta("弹簧", False, 0.0, "6884154487246688776", "1644647", "15c4e6b0a27360bab5d6f5d421bbbe1e")
打字机_I = Animation_meta("打字机 I", False, 0.0, "6763469696260903435", "1644611", "628234381485fb1dd576eeb48c85a091")
打字机_II = Animation_meta("打字机 II", False, 0.0, "6763469767555682823", "1644612", "83076ce7cda24efdaca9731b112fb097")
打字机_III = Animation_meta("打字机 III", False, 0.0, "6763469838368117256", "1644664", "3f77a87e46ee1b50cd0ac207809c4c24")
扭曲模糊 = Animation_meta("扭曲模糊", False, 0.0, "7090122015603954189", "1729226", "2e58579b330dbccc4491c5f0a8cf4a8a")
拖尾 = Animation_meta("拖尾", False, 0.0, "7244102819731477049", "15260277", "20d1992e9f7b67bedf1811c0811b1e5c")
放大 = Animation_meta("放大", False, 0.0, "6724919767200698884", "1644603", "e818fb0699073a734ecead7c2768d827")
放大_II = Animation_meta("放大 II", False, 0.0, "7042278078415901192", "1644666", "1d6882ba11b67fff13c98493bc644027")
故障打字机 = Animation_meta("故障打字机", False, 0.0, "6870061326698287624", "1644643", "71a23656184bc8438f4fa22425192185")
旋出 = Animation_meta("旋出", False, 0.0, "6763873732143354376", "1644604", "ffc35db86b29aee7a0a4342ea5ed059f")
日落 = Animation_meta("日落", False, 0.0, "6779084194392838670", "1644607", "662eea25ba7d450d9a91febf43f22f7f")
晕开 = Animation_meta("晕开", False, 0.0, "7090059095134179877", "1727994", "3f2770aa65e01746967c8289e193021b")
模糊 = Animation_meta("模糊", False, 0.0, "6923094772907250189", "1644652", "72f73d5e9fd970ccee4918008b5a9d9a")
水墨晕开 = Animation_meta("水墨晕开", False, 0.0, "7278296130432012857", "22734371", "2705529afbf57f101c042d3a96ca2795")
水平翻转 = Animation_meta("水平翻转", False, 0.0, "7052633346936934942", "1644667", "8719853b159397ea64fc2102c61e52e4")
波浪弹出 = Animation_meta("波浪弹出", False, 0.0, "6917178803521327630", "1644651", "c60021c62c10eab0aa4f408ed602405c")
渐隐 = Animation_meta("渐隐", False, 0.0, "6724919382104871427", "1644600", "11004616098603d847593ce9ede05a62")
溶解 = Animation_meta("溶解", False, 0.0, "6872642354898014728", "1644645", "46389f9f5f72e1b58020a0b8293a23b9")
滑动下落 = Animation_meta("滑动下落", False, 0.0, "7270726693277405733", "21330850", "fa4aaf84b182425eed4e330ac03ecdbd")
生长 = Animation_meta("生长", False, 0.0, "6869302139584254477", "1644642", "e6ae4e1fc5ade7bd8765ef6d918f5f6f")
缩小 = Animation_meta("缩小", False, 0.0, "6724921351385125387", "1644602", "6c679c75b88d8c69335c9faefbcd635a")
羽化向右擦除= Animation_meta("羽化向右擦除", False, 0.0, "6897085341811872270", "1644649", "9d4c77cbae673b97c629890c6687bc71")
羽化向左擦除= Animation_meta("羽化向左擦除", False, 0.0, "6897085246206906893", "1644650", "865d4874f9e21f104881bd3f1f1e02fa")
翻动 = Animation_meta("翻动", False, 0.0, "7308279288061497865", "32283993", "07d60e408004cba91944a6fbe3ec570d")
躺下 = Animation_meta("躺下", False, 0.0, "7265288999470633509", "20324365", "dc012ae6bfd6482bb0e52d02328016c8")
轻微放大 = Animation_meta("轻微放大", False, 0.0, "6763469915518145032", "1644601", "1e293df954586a261a11576481dd8454")
闪动 = Animation_meta("闪动", False, 0.0, "7039245189638001183", "1644658", "6b16591d61fa6ee68eef9148dbf0aa31")
闭幕 = Animation_meta("闭幕", False, 0.0, "6834511218552607239", "1644616", "02a28db581b74aac8547c2479cb219bc")
随机弹跳 = Animation_meta("随机弹跳", False, 0.0, "7026617357300666893", "1644665", "c260caa85b16e7d471ddeb2015cdf3f3")
随机飞出 = Animation_meta("随机飞出", False, 0.0, "6872642497013617159", "1644644", "d1292de2cfc57d0ca12fdbafb4e0bca2")
# 付费
二段缩放 = Animation_meta("二段缩放", True, 0.0, "7238519014866031162", "14394793", "bc54fc23dff39b105104f5bb15043ff9")
发光闪出 = Animation_meta("发光闪出", True, 0.0, "7308275717505028617", "32281161", "980fe827d603f3785e69854b6e5967a4")
叠影并出 = Animation_meta("叠影并出", True, 0.0, "7259634082760364603", "19101496", "1cc4801fbe64f100872abd1d502ac121")
向上飞出 = Animation_meta("向上飞出", True, 0.0, "7090139631861109278", "1730928", "3513093fd914fcccfa87cb98a410062e")
向下弹出 = Animation_meta("向下弹出", True, 0.0, "7127158940151845390", "3859743", "751b7e005e3ec297f5d3d2c40664f585")
向下翻转 = Animation_meta("向下翻转", True, 0.0, "7198395913948107301", "9282213", "860c71ba47b9cf749ac977cb437ae1a8")
向左模糊 = Animation_meta("向左模糊", True, 0.0, "7112703727336690189", "3176752", "02ee1da62468714f7b17a671ee61acf0")
向左模糊_II = Animation_meta("向左模糊 II", True, 0.0, "7254503584732025381", "17830676", "0374eb3b551fbd0d36c78d3105e6f976")
吸出 = Animation_meta("吸出", True, 0.0, "7121986743141667358", "3647465", "27d43c1a8f3bb21f88f25fadfd74e113")
喷绘 = Animation_meta("喷绘", True, 0.0, "7120131305303446029", "3563649", "a2efafd9407094f2706c38b5ea2867c0")
复古打字机 = Animation_meta("复古打字机", True, 0.0, "7252619798108967484", "17250228", "7739c9b46eb8c9ed7105c7c5c859ea8d")
弹出跳动 = Animation_meta("弹出跳动", True, 0.0, "7184797189627974200", "8058215", "dffb8966b47b6eae5fb9ef0e0fe6e6b9")
弹性伸缩_II = Animation_meta("弹性伸缩 II", True, 0.0, "7308276711039177225", "32281815", "9b225f4fafa2341876eec98ba91c89ee")
打字光标 = Animation_meta("打字光标", True, 0.0, "7237411511755346491", "14235852", "1285f4e58d3989468cc7c7679145e155")
打字机IV = Animation_meta("打字机IV", True, 0.0, "7237411448303915557", "14235853", "3f2d4916f48390652f4abaff69742c0b")
折叠 = Animation_meta("折叠", True, 0.0, "7124961998919438884", "3769517", "ccce629bcf7f98a8de4d4e1a2228d11a")
描边填充 = Animation_meta("描边填充", True, 0.0, "7308273254127374874", "32279531", "9dc334dd67a2ace030c8d0f0d01ecede")
收缩震动 = Animation_meta("收缩震动", True, 0.0, "7268214314022998588", "20877442", "c95da61de0632a74d061f03806a8ea9b")
故障 = Animation_meta("故障", True, 0.0, "7091567288385540622", "1789138", "b106b2d684134a06b033aa2ba70baea2")
故障闪动 = Animation_meta("故障闪动", True, 0.0, "7244102414377161276", "15261509", "ba766fab0ea8b838f1c64973aee2b54b")
旋转缩放 = Animation_meta("旋转缩放", True, 0.0, "7243633648237285949", "15140857", "37af568e3f004232b19507b24d5438c1")
旋转飞出 = Animation_meta("旋转飞出", True, 0.0, "6775804032318444045", "1644639", "802b2078b18d70ecd073ffacff59c1d8")
模糊发光 = Animation_meta("模糊发光", True, 0.0, "7301536173959156274", "29690520", "a21891cf3eff128b2a5190cad5356d69")
模糊滚动 = Animation_meta("模糊滚动", True, 0.0, "7264501549240422949", "20154980", "9c07a1d5d75f675d32f8917dc76f7381")
波浪弹跳 = Animation_meta("波浪弹跳", True, 0.0, "7317637880799564297", "37396324", "17dc7c4e6498440fcafc56dfbe3fb4fe")
消散 = Animation_meta("消散", True, 0.0, "7155790075794559525", "5323563", "21888446c8d15d56c60864985328652b")
滚出 = Animation_meta("滚出", True, 0.0, "7023684709737566728", "1644656", "f25af0cdef9584d588584b3765350f64")
激光雕刻 = Animation_meta("激光雕刻", True, 0.0, "7244102529573720635", "15261103", "bb0ab89c7396d11d5663b0071296f27d")
炸开 = Animation_meta("炸开", True, 0.0, "7142816577971294734", "4577477", "15ced8e31e8d57f8932820fe99f96391")
炸开_II = Animation_meta("炸开 II", True, 0.0, "7148309755121898015", "4834739", "bff4571b77bca8598b6ce8ba65d93252")
炸开_Ⅲ = Animation_meta("炸开 Ⅲ", True, 0.0, "7308274161992864266", "32280237", "0060b15237436dc553a3a050825d18a6")
环绕滑出 = Animation_meta("环绕滑出", True, 0.0, "7261858590808347193", "19562193", "c88f30f314faade1a6e71884234a380b")
甩回 = Animation_meta("甩回", True, 0.0, "7244102747698500156", "15261069", "0203e194e3bcf10f7f96fde73dc350f3")
空翻 = Animation_meta("空翻", True, 0.0, "6865176065514410503", "1644641", "f578720479df7746fa067199a1e4ea8b")
螺旋下降 = Animation_meta("螺旋下降", True, 0.0, "6799874105710481927", "1644640", "e6e1a2239d894b408e41341a6ca578ca")
逐字旋出 = Animation_meta("逐字旋出", True, 0.0, "7229520513586958908", "13137113", "3df3f26182ac9c6359be95dfb443d5da")
逐字旋转 = Animation_meta("逐字旋转", True, 0.0, "7112021029085516319", "3129838", "ee29d8b9e06a471972f36734c53dbea8")
逐字翻转 = Animation_meta("逐字翻转", True, 0.0, "7112274846326723086", "3139394", "ffc81a4b0c44427fbfd60984f7ddcdc2")
逐字虚影 = Animation_meta("逐字虚影", True, 0.0, "7034717113130422791", "1644657", "fe2cfbc08c330517caa8b602187ced07")
镂空跳出 = Animation_meta("镂空跳出", True, 0.0, "7312331703903588902", "34383204", "f1bb60aeec2ee712e813b3cab75050bc")
闪烁散开 = Animation_meta("闪烁散开", True, 0.0, "7268169968204649020", "20860262", "b58f8939e94946a70c35188819a65a78")
随机弹跳_II = Animation_meta("随机弹跳 II", True, 0.0, "7114191629346411016", "3241116", "0f0b492622513301a7cd8f30b035a056")
随机打字机 = Animation_meta("随机打字机", True, 0.0, "6926719087158497806", "1644653", "9db48fc9916b5b8554ce7262bb90f18f")
顶出 = Animation_meta("顶出", True, 0.0, "7268231069768356408", "20882164", "98ad0ec3b5980352e4709158def77960")
预览打字 = Animation_meta("预览打字", True, 0.0, "7268216065337856572", "20878188", "360d883bb43dab551defd1e94b9730d6")
飞出 = Animation_meta("飞出", True, 0.0, "7029522072724312612", "1644654", "324c695abdd43e1ec3506364fce0a087")
class Text_loop_anim(Effect_enum):
"""文字循环动画
由于重名而仅保留了其中一项的动画: 心跳, 流光
"""
# 免费
VHS = Animation_meta("VHS", False, 0.0, "7399879467457319463", "77851352", "f82d0f25b2cc4f0696dce7d97c7b02be")
上弧 = Animation_meta("上弧", False, 0.0, "7075224569421763079", "1626238", "a0362ebaa2f5016487abfab05d47605b")
刷屏 = Animation_meta("刷屏", False, 0.0, "7308280358691148315", "32284703", "e92c576feca5efb75feda14004b269c5")
发光模糊多行= Animation_meta("发光模糊多行", False, 0.0, "7397688001356108339", "77132594", "ee68176782c8b62a207c04f4a979957a")
吹泡泡 = Animation_meta("吹泡泡", False, 0.0, "7045155566003425823", "1644539", "6db3746838af18903d01968e6af07185")
吹泡泡_II = Animation_meta("吹泡泡 II", False, 0.0, "7052257626897256968", "1644528", "b378734fd7a0e8ec78e53987823fad79")
呐喊 = Animation_meta("呐喊", False, 0.0, "7119024816480326157", "4002167", "04933b5e575c54cbf09c57c5e933f0ec")
复古涂鸦 = Animation_meta("复古涂鸦", False, 0.0, "7400234025392017956", "77997810", "4bc57fba68e0cce14e2ea8ab652dabc2")
字体变换 = Animation_meta("字体变换", False, 0.0, "7402185694732358170", "78763194", "06c685c00a9c1a7a484c7841ac45742a")
弹幕滚动 = Animation_meta("弹幕滚动", False, 0.0, "6790247082155315719", "1644518", "4ca7b3a27da98849561b21c9c6d964fc")
彩虹 = Animation_meta("彩虹", False, 0.0, "6908592625406710280", "990096", "fac0ebef55c57c31b3142f5840299b03")
彩虹_情人节 = Animation_meta("彩虹-情人节", False, 0.0, "6916820108211917325", "1012617", "c45282c8e30b8639a71345769060f3d5")
彩虹_新年 = Animation_meta("彩虹-新年", False, 0.0, "6916820045519655432", "1012618", "dd9fcbbcfc17cad31ab42e886769c66e")
彩虹_马卡龙 = Animation_meta("彩虹-马卡龙", False, 0.0, "6921528300573561358", "1022790", "a614b3dd7d4b852f1a126afe4c5ee50f")
扫光 = Animation_meta("扫光", False, 0.0, "7051843475892867598", "1520868", "0495742cdb3a26ff28dfabf7f8ef236b")
投影颤抖_II = Animation_meta("投影颤抖 II", False, 0.0, "7070332370963927559", "1599696", "673aa54d5519360162ea8ec38986ea1c")
折叠 = Animation_meta("折叠", False, 0.0, "7064823078542381581", "1567212", "c9b3ef10e455a3916dbef47a7f711eaa")
拼贴纹理 = Animation_meta("拼贴纹理", False, 0.0, "7399983060806013479", "77918388", "922ca4e87c7eed7e60d062c18e928bc6")
描边粉笔 = Animation_meta("描边粉笔", False, 0.0, "7399879712140431883", "77851433", "05c3c10997b885c71ed0dd64aff14dd2")
摇摆 = Animation_meta("摇摆", False, 0.0, "6724920869363126795", "1644515", "8af4da60a802e3ca6c9fe2184fbe22d0")
摇荡 = Animation_meta("摇荡", False, 0.0, "6840710593289130503", "1644523", "61f24344eb8bf86582d6140ad985ef14")
故障闪动 = Animation_meta("故障闪动", False, 0.0, "6857714281136263687", "1644524", "51d9ee83fbaf2dfa049885676ec2d5d9")
旋转 = Animation_meta("旋转", False, 0.0, "6763900973946507784", "1644510", "151421d4de4d49e65b050cb413482cd5")
晃动 = Animation_meta("晃动", False, 0.0, "6790246693674684942", "1644520", "383dabd75d7fe7985d990ebb34d63732")
波纹 = Animation_meta("波纹", False, 0.0, "7275663372148806203", "22223033", "929efca6bd35df0718dadf77836cfba7")
爆闪 = Animation_meta("爆闪", False, 0.0, "7308279705252139530", "32284413", "61951bd303975761bc99f187bdb8fdab")
环绕 = Animation_meta("环绕", False, 0.0, "6980916124976157220", "1644542", "0d14427906b240809f0d9838f35cf95c")
翻转 = Animation_meta("翻转", False, 0.0, "6763897586328801805", "1644511", "e4983ce92d02628087780832ef631c7d")
色差故障 = Animation_meta("色差故障", False, 0.0, "6835878163575214605", "1644522", "e0295a9f4f19fe21692c405f7c00d1e5")
蓝黄滑动 = Animation_meta("蓝黄滑动", False, 0.0, "7398492769628459539", "77383265", "bb717e125d34532ec904d1bc01ec25da")
超强晃动 = Animation_meta("超强晃动", False, 0.0, "7065208406633615909", "1568854", "b129b0e6bed4f9835f871848db646763")
超强晃动_II = Animation_meta("超强晃动 II", False, 0.0, "7069965879437431303", "1597286", "2b8adf8a719de3e0bcfa10569d364a81")
超强波浪 = Animation_meta("超强波浪", False, 0.0, "6857036499389518349", "872098", "87f7332abda9ac46d5dc81f69c48daab")
超强波浪_II = Animation_meta("超强波浪 II", False, 0.0, "7065219379687854623", "1568964", "bdd007527d0eda9d64bfbf6aef103e97")
跳动 = Animation_meta("跳动", False, 0.0, "6724920002958332420", "1644512", "784250e657b472a46a3b3ce0a838e4f7")
轻微跳动 = Animation_meta("轻微跳动", False, 0.0, "6884155832838132231", "1644525", "ac5c4160fae860fd74e5b7ab6d053252")
钟摆 = Animation_meta("钟摆", False, 0.0, "6724921579517514248", "1644516", "320b71150105629f7ab1b318716181eb")
闪烁 = Animation_meta("闪烁", False, 0.0, "6724921437930394120", "1644514", "6fe3f0fcd14e11e70b7510f42444b86c")
雨刷 = Animation_meta("雨刷", False, 0.0, "6799874389669057037", "1644521", "6a4c40e24db5027cb42892d8ade9df38")
频闪边框 = Animation_meta("频闪边框", False, 0.0, "7308280718302384690", "32284883", "36184bd37eae10c2d8247fb5bd59c6f2")
颤抖 = Animation_meta("颤抖", False, 0.0, "6764189482871689742", "1644509", "82a2b88dc69ce9f9a36f975968649d5b")
颤抖_III = Animation_meta("颤抖 III", False, 0.0, "7070036604429013535", "1598082", "c6f744d4c3d208abf97a3af3afe9d356")
# 付费
喷涌 = Animation_meta("喷涌", True, 0.0, "7134190113780666887", "4175399", "76cc53a7bb20385d208c858a13cf06fd")
喷绘 = Animation_meta("喷绘", True, 0.0, "7110160318529016350", "2999942", "fbd35399a1880d2637731d20eb619d29")
圆形涂鸦 = Animation_meta("圆形涂鸦", True, 0.0, "7276420462131810874", "22362181", "696d3b443b4c6ed8b9f0f28825c08a8c")
声波震动 = Animation_meta("声波震动", True, 0.0, "7239526343833031223", "14518651", "9098085cd316045cf912e54a73d845a4")
字幕滚动 = Animation_meta("字幕滚动", True, 0.0, "6790246884683289102", "1644519", "9aa4e0d045c61892c2b2e3fdfaf1b093")
尾巴摇摆 = Animation_meta("尾巴摇摆", True, 0.0, "7212897307782550053", "10967121", "c1585ff28130b111d0458c6490d20ef2")
弹幕 = Animation_meta("弹幕", True, 0.0, "7107592133472686606", "2795622", "8d0a44c1f51ea9cd7a8174f72751d2b7")
弹幕_II = Animation_meta("弹幕 II", True, 0.0, "7096375845773644318", "1826548", "11bcd8965488f2c70e27c8dc5112c6cb")
强调三遍 = Animation_meta("强调三遍", True, 0.0, "7129767866894651917", "3966601", "e008ee1c0ba1e9beb3fb5bb84b4c0643")
彩色切换 = Animation_meta("彩色切换", True, 0.0, "7303430211519910451", "30322872", "e2c7f4ec20555abe1e50c1920e81a0f9")
彩色火焰 = Animation_meta("彩色火焰", True, 0.0, "7308278472541999654", "32283417", "94dd9722a4b46d248c5e1d3d4b7c71fb")
影像叠加 = Animation_meta("影像叠加", True, 0.0, "7193989785319379515", "8882439", "018a39f66ba7ceb39f4d61e4446624f8")
# 心跳 = Animation_meta("心跳", True, 0.0, "6724919955654971918", "1644513", "1b9a454256f041c19f723ba27358740b")
心跳 = Animation_meta("心跳", True, 0.0, "7210283971316290085", "10650869", "3c2c6a7f6b8b102e9ae5f918600f83c0")
急了 = Animation_meta("急了", True, 0.0, "7134634461588623909", "4200435", "4f01b8c42b2d4a26a89aa528e6cc1544")
悸动 = Animation_meta("悸动", True, 0.0, "7229526981807706680", "13139395", "dc1aa28b54954465640c40928fae55f7")
情绪加载 = Animation_meta("情绪加载", True, 0.0, "7130142075995034119", "3983735", "6293429c9f4e12407d38089ee43b77cd")
扩音器 = Animation_meta("扩音器", True, 0.0, "7277870806552547895", "22619881", "ba24954b91039982fabf75ad533e7ff1")
扭动 = Animation_meta("扭动", True, 0.0, "7123093247672455711", "3733565", "5380b570671074788541d13e389daa4f")
投影颤抖 = Animation_meta("投影颤抖", True, 0.0, "7070332284934558245", "1599698", "4f4bebc9ab74f05801dca7b9b2ffa047")
抖动故障 = Animation_meta("抖动故障", True, 0.0, "7283103017526628921", "23998441", "55749de55fe55fc230a31952790142f3")
拉住 = Animation_meta("拉住", True, 0.0, "7221747595884892731", "12135594", "98db2339ea77225948ed8b7f8d72fc36")
拉开 = Animation_meta("拉开", True, 0.0, "7223675733606928957", "12390761", "41f672adaa1cdccdb81c8d0b2b1124a4")
排队入场 = Animation_meta("排队入场", True, 0.0, "7225496399817740855", "12628547", "0a7a9cb49305092f638d65888f149348")
摇摆_I = Animation_meta("摇摆 I", True, 0.0, "6908281696253121038", "1520478", "ea2f688a517d18a9de5912fa09f3bd56")
放大缩小 = Animation_meta("放大缩小", True, 0.0, "7224077152587616805", "12453543", "3e1538ad9a9f723238bb922423e20aed")
放大镜 = Animation_meta("放大镜", True, 0.0, "7272339163142165050", "21635790", "e9f8437306ec0f948c1eb485f09692a3")
文字泛光 = Animation_meta("文字泛光", True, 0.0, "7124226995231134239", "3740251", "879231435782ed4b72f278290070f20a")
波浪 = Animation_meta("波浪", True, 0.0, "6724927688047333891", "1644517", "176a075543ef82c04df1dd40d181ac5b")
波浪_II = Animation_meta("波浪 II", True, 0.0, "7067046171381862919", "1576246", "62245c9799544b75258689eb1ff222bb")
波浪_III = Animation_meta("波浪 III", True, 0.0, "7067812686557352456", "1583302", "8eecb90b305442a4568e2e9ff7151735")
# 流光 = Animation_meta("流光", True, 0.0, "7308277700492268042", "32283005", "810cca793722d3736730aadf62d77301")
流光 = Animation_meta("流光", True, 0.0, "7181754919827804728", "7776353", "16711992a6719a5c798f8fb138550229")
涂鸦手绘 = Animation_meta("涂鸦手绘", True, 0.0, "7276407256965452346", "22361305", "1ae8ceff3f65dd62f36b3eb43baff6b4")
涂鸦手绘_II = Animation_meta("涂鸦手绘 II", True, 0.0, "7276407576625943100", "22361304", "f72282b1f43b0d5e59144bbca7fbeda8")
渐变拖尾 = Animation_meta("渐变拖尾", True, 0.0, "7308277117622424090", "32282151", "950687cffad02a7b17bc9b672c9585f2")
漂浮 = Animation_meta("漂浮", True, 0.0, "7213291988500615738", "11017729", "451fbb332b33ec6ba683dc9d22055810")
漩涡 = Animation_meta("漩涡", True, 0.0, "7099419657290912286", "1936778", "416be3d42ae0d037597209d2a2f843c4")
环形滚动 = Animation_meta("环形滚动", True, 0.0, "7179135028343870012", "7564487", "e167e03db93ab98c4917ff53f59162c1")
环绕_II = Animation_meta("环绕 II", True, 0.0, "7114181846086193701", "3240866", "6df622ca3b91909a8d23ae24f1c2a675")
甜甜圈 = Animation_meta("甜甜圈", True, 0.0, "7070415354656199181", "1600378", "23a8cee8851ad7e169a094cee8ca9513")
福袋炸开 = Animation_meta("福袋炸开", True, 0.0, "7047088638932292127", "1531460", "2646a21f26faeb4103acacaa74c171f6")
空间翻转_I = Animation_meta("空间翻转 I", True, 0.0, "7163896186972148261", "5965291", "24cd6c57edb2d457135c7c24a2b79a02")
空间翻转_II = Animation_meta("空间翻转 II", True, 0.0, "7163901901589713444", "5966503", "ce769779dfa1d9c69eb593318bf1bc28")
空间翻转_III= Animation_meta("空间翻转 III", True, 0.0, "7163892769176424991", "5964737", "f9c82b94ebd990e6734ddef5ebba68cb")
翻页I = Animation_meta("翻页I", True, 0.0, "7168819879183651359", "6443365", "8e4559d96b415b5c1ec0748b8a138f4e")
调皮 = Animation_meta("调皮", True, 0.0, "6917143282690560526", "1644527", "b832fcbb8ea3bcc64ddbd70c56166956")
逐字放大 = Animation_meta("逐字放大", True, 0.0, "6908592686781960717", "1644526", "4cd5a5c4144a3a713469043722579306")
错位 = Animation_meta("错位", True, 0.0, "7243633488249754173", "15140783", "cc869e81ac3b5d769afa6836bab5937b")
随机弹跳 = Animation_meta("随机弹跳", True, 0.0, "7045150354672980516", "1644538", "8656e9848f862adf1adfa30c26113a80")
颤抖_II = Animation_meta("颤抖 II", True, 0.0, "6986920909927879199", "1446098", "8d180f0ad5ff173a44f9142baeee536c")
飘起 = Animation_meta("飘起", True, 0.0, "7211060597352305189", "10749797", "1ab6d9a8761c108da6989633b933647e")
@@ -1,367 +0,0 @@
from .effect_meta import Effect_enum
from .effect_meta import Effect_meta, Effect_param
class Tone_effect_type(Effect_enum):
"""剪映自带的音频“音色”效果类型"""
# 免费
台湾小哥 = Effect_meta("台湾小哥", False, "7255565276819755576", "18149602", "8dd8889045e6c065177df791ddb3dfb8", [])
圣诞精灵 = Effect_meta("圣诞精灵", False, "7310059412062736946", "33214695", "8dd8889045e6c065177df791ddb3dfb8", [])
圣诞老人 = Effect_meta("圣诞老人", False, "7310059178133819930", "33214489", "8dd8889045e6c065177df791ddb3dfb8", [])
广告男声 = Effect_meta("广告男声", False, "7328088579811316263", "42060748", "f554735f65a98cc4da17a1c53ef6a886", [])
港普男声 = Effect_meta("港普男声", False, "7328087687548637732", "42060743", "f554735f65a98cc4da17a1c53ef6a886", [])
老婆婆 = Effect_meta("老婆婆", False, "7328089253114548799", "42060746", "f554735f65a98cc4da17a1c53ef6a886", [])
解说小帅 = Effect_meta("解说小帅", False, "7332473259369173540", "44254166", "f554735f65a98cc4da17a1c53ef6a886", [])
大叔 = Effect_meta("大叔", False, "7020344898033291790", "2672760", "2509bbd71e127b04a29f52a54e82c53c", [
Effect_param("音调", 0.834, 0.000, 1.000),
Effect_param("音色", 1.000, 0.000, 1.000)])
"""参数:
- 音调: 默认0.83, 0.00 ~ 1.00
- 音色: 默认1.00, 0.00 ~ 1.00
"""
女生 = Effect_meta("女生", False, "7020345715901600270", "2672757", "0ce1aade5958506c97bffea150772b6e", [
Effect_param("音调", 0.834, 0.000, 1.000),
Effect_param("音色", 0.334, 0.000, 1.000)])
"""参数:
- 音调: 默认0.83, 0.00 ~ 1.00
- 音色: 默认0.33, 0.00 ~ 1.00
"""
怪物 = Effect_meta("怪物", False, "7020344978794615327", "2672759", "2130ffa21e5980196e014ec0baade179", [
Effect_param("音调", 0.650, 0.000, 1.000),
Effect_param("音色", 0.780, 0.000, 1.000)])
"""参数:
- 音调: 默认0.65, 0.00 ~ 1.00
- 音色: 默认0.78, 0.00 ~ 1.00
"""
机器人 = Effect_meta("机器人", False, "7018011705414259213", "2672750", "4b87db25aecd2f6f71927930110c4a1e", [
Effect_param("强弱", 1.000, 0.000, 1.000)])
"""参数:
- 强弱: 默认1.00, 0.00 ~ 1.00
"""
男生 = Effect_meta("男生", False, "7020345085233467917", "2672758", "ffd7a609207fd849efc9f63bf31697b1", [
Effect_param("音调", 0.375, 0.000, 1.000),
Effect_param("音色", 0.250, 0.000, 1.000)])
"""参数:
- 音调: 默认0.38, 0.00 ~ 1.00
- 音色: 默认0.25, 0.00 ~ 1.00
"""
花栗鼠 = Effect_meta("花栗鼠", False, "7018011553081332231", "2672752", "e30b1922b8300423f21f9f84eff41ced", [
Effect_param("音调", 0.500, 0.000, 1.000),
Effect_param("音色", 0.500, 0.000, 1.000)])
"""参数:
- 音调: 默认0.50, 0.00 ~ 1.00
- 音色: 默认0.50, 0.00 ~ 1.00
"""
萝莉 = Effect_meta("萝莉", False, "7020345789599715848", "2672756", "00b7ed2ccfe4d6076f78c8d751347a53", [
Effect_param("音调", 0.750, 0.000, 1.000),
Effect_param("音色", 0.600, 0.000, 1.000)])
"""参数:
- 音调: 默认0.75, 0.00 ~ 1.00
- 音色: 默认0.60, 0.00 ~ 1.00
"""
# 付费
TVB女声 = Effect_meta("TVB女声", True, "7260024060417937978", "19186454", "8dd8889045e6c065177df791ddb3dfb8", [])
东厂公公 = Effect_meta("东厂公公", True, "7328092524612948491", "42060742", "f554735f65a98cc4da17a1c53ef6a886", [])
云龙哥 = Effect_meta("云龙哥", True, "7376558114830553612", "68856989", "f554735f65a98cc4da17a1c53ef6a886", [])
侠客 = Effect_meta("侠客", True, "7328089134331859468", "42060738", "f554735f65a98cc4da17a1c53ef6a886", [])
做作夹子音 = Effect_meta("做作夹子音", True, "7367676929496846911", "63231108", "f554735f65a98cc4da17a1c53ef6a886", [])
八戒 = Effect_meta("八戒", True, "7265891792766112314", "20427371", "8dd8889045e6c065177df791ddb3dfb8", [])
军事解说 = Effect_meta("军事解说", True, "7328092289480266252", "42060734", "f554735f65a98cc4da17a1c53ef6a886", [])
动漫小新 = Effect_meta("动漫小新", True, "7360901047662940708", "58979441", "f554735f65a98cc4da17a1c53ef6a886", [])
动漫海绵 = Effect_meta("动漫海绵", True, "7367676859883983379", "63231109", "f554735f65a98cc4da17a1c53ef6a886", [])
咆哮哥 = Effect_meta("咆哮哥", True, "7332473122605503039", "44254278", "f554735f65a98cc4da17a1c53ef6a886", [])
商务殷语 = Effect_meta("商务殷语", True, "7328085477267870249", "42060747", "f554735f65a98cc4da17a1c53ef6a886", [])
四郎 = Effect_meta("四郎", True, "7250403044414722621", "16627073", "8dd8889045e6c065177df791ddb3dfb8", [])
太白 = Effect_meta("太白", True, "7328091247308968484", "42060736", "f554735f65a98cc4da17a1c53ef6a886", [])
如来佛祖 = Effect_meta("如来佛祖", True, "7376558174049931830", "68856990", "f554735f65a98cc4da17a1c53ef6a886", [])
姜饼人 = Effect_meta("姜饼人", True, "7310059267384414747", "33214539", "8dd8889045e6c065177df791ddb3dfb8", [])
容嬷嬷 = Effect_meta("容嬷嬷", True, "7332472945366798860", "44254320", "f554735f65a98cc4da17a1c53ef6a886", [])
小孩 = Effect_meta("小孩", True, "7262648951948448315", "19716244", "8dd8889045e6c065177df791ddb3dfb8", [])
强势妹 = Effect_meta("强势妹", True, "7328091624427229759", "42060740", "f554735f65a98cc4da17a1c53ef6a886", [])
快板 = Effect_meta("快板", True, "7328088454183522827", "42060741", "f554735f65a98cc4da17a1c53ef6a886", [])
恐怖电影 = Effect_meta("恐怖电影", True, "7325710953247412787", "40932465", "f554735f65a98cc4da17a1c53ef6a886", [])
悬疑解说 = Effect_meta("悬疑解说", True, "7325711304390349362", "40932811", "f554735f65a98cc4da17a1c53ef6a886", [])
懒小羊 = Effect_meta("懒小羊", True, "7332473035116515859", "44254304", "f554735f65a98cc4da17a1c53ef6a886", [])
搞笑解说 = Effect_meta("搞笑解说", True, "7262648842238038584", "19716150", "8dd8889045e6c065177df791ddb3dfb8", [])
文艺女声 = Effect_meta("文艺女声", True, "7379565719991620132", "70562787", "f554735f65a98cc4da17a1c53ef6a886", [])
樱桃丸子 = Effect_meta("樱桃丸子", True, "7325709643332719113", "40931609", "f554735f65a98cc4da17a1c53ef6a886", [])
樱花小哥 = Effect_meta("樱花小哥", True, "7328091741678998055", "42060735", "f554735f65a98cc4da17a1c53ef6a886", [])
武则天 = Effect_meta("武则天", True, "7328088300474864167", "42060744", "f554735f65a98cc4da17a1c53ef6a886", [])
沉稳解说 = Effect_meta("沉稳解说", True, "7367676791164506636", "63231110", "f554735f65a98cc4da17a1c53ef6a886", [])
温柔姐姐 = Effect_meta("温柔姐姐", True, "7379565769190806079", "70562785", "f554735f65a98cc4da17a1c53ef6a886", [])
熊二 = Effect_meta("熊二", True, "7250403222798471740", "16627311", "8dd8889045e6c065177df791ddb3dfb8", [])
猴哥 = Effect_meta("猴哥", True, "7236944659547689531", "14477015", "4f6a1fbc0000e178c724d355efea1d9f", [])
甜美悦悦 = Effect_meta("甜美悦悦", True, "7325710673978069530", "40932253", "f554735f65a98cc4da17a1c53ef6a886", [])
生活小妙招 = Effect_meta("生活小妙招", True, "7328092409525441065", "42060737", "f554735f65a98cc4da17a1c53ef6a886", [])
电竞解说 = Effect_meta("电竞解说", True, "7325711893551649330", "40933559", "f554735f65a98cc4da17a1c53ef6a886", [])
电视广告 = Effect_meta("电视广告", True, "7360901109667336743", "58979440", "f554735f65a98cc4da17a1c53ef6a886", [])
紫薇 = Effect_meta("紫薇", True, "7281175506391667257", "23475307", "8dd8889045e6c065177df791ddb3dfb8", [])
舌尖解说 = Effect_meta("舌尖解说", True, "7328091500753982015", "42060739", "f554735f65a98cc4da17a1c53ef6a886", [])
蜡笔小妮 = Effect_meta("蜡笔小妮", True, "7379565670398169619", "70562786", "f554735f65a98cc4da17a1c53ef6a886", [])
语音助手 = Effect_meta("语音助手", True, "7325710335455793714", "40931973", "f554735f65a98cc4da17a1c53ef6a886", [])
那姐 = Effect_meta("那姐", True, "7369177370873303587", "64206631", "f554735f65a98cc4da17a1c53ef6a886", [])
锤子哥 = Effect_meta("锤子哥", True, "7328091348098093580", "42060745", "f554735f65a98cc4da17a1c53ef6a886", [])
顾姐 = Effect_meta("顾姐", True, "7250403134923608631", "16627197", "8dd8889045e6c065177df791ddb3dfb8", [])
黛玉 = Effect_meta("黛玉", True, "7255565592093004343", "18149634", "8dd8889045e6c065177df791ddb3dfb8", [])
class Audio_scene_effect_type(Effect_enum):
"""剪映自带的音频“场景音”效果类型"""
# 免费
_8bit = Effect_meta("8bit", False, "7161319747584266766", "5723961", "8d24238329ea5c250e33ae241d5adae2", [
Effect_param("change_voice_param_pitch_shift", 0.500, 0.000, 1.000),
Effect_param("change_voice_param_timbre", 1.000, 0.000, 1.000),
Effect_param("change_voice_param_strength", 1.000, 0.000, 1.000)])
"""参数:
- change_voice_param_pitch_shift: 默认0.50, 0.00 ~ 1.00
- change_voice_param_timbre: 默认1.00, 0.00 ~ 1.00
- change_voice_param_strength: 默认1.00, 0.00 ~ 1.00
"""
低保真 = Effect_meta("低保真", False, "7024390914537689614", "2672762", "7ddbd39a691a66a021f684cab756a89a", [
Effect_param("强弱", 1.000, 0.000, 1.000)])
"""参数:
- 强弱: 默认1.00, 0.00 ~ 1.00
"""
合成器 = Effect_meta("合成器", False, "7018011500577034759", "2672753", "394efea5922637bcd8288e0fb3c2372e", [
Effect_param("强弱", 1.000, 0.000, 1.000)])
"""参数:
- 强弱: 默认1.00, 0.00 ~ 1.00
"""
回音 = Effect_meta("回音", False, "7018011608408396325", "5723901", "5377f66109693f2d473df5ea6ec8f791", [
Effect_param("change_voice_param_quantity", 0.800, 0.000, 1.000),
Effect_param("change_voice_param_strength", 0.762, 0.000, 1.000)])
"""参数:
- change_voice_param_quantity: 默认0.80, 0.00 ~ 1.00
- change_voice_param_strength: 默认0.76, 0.00 ~ 1.00
"""
扩音器 = Effect_meta("扩音器", False, "7018011975514853924", "2672749", "13169f6ab9957ff005d316239bef0045", [
Effect_param("强弱", 1.000, 0.000, 1.000)])
"""参数:
- 强弱: 默认1.00, 0.00 ~ 1.00
"""
水下 = Effect_meta("水下", False, "7106404450444513806", "2673077", "53956694a8b68b2855faa2adc043b5b1", [
Effect_param("深度", 0.500, 0.000, 1.000)])
"""参数:
- 深度: 默认0.50, 0.00 ~ 1.00
"""
没电了 = Effect_meta("没电了", False, "7018012193769656845", "2672747", "87f91614bac060840ad5a57ef2b0c9ca", [
Effect_param("强弱", 1.000, 0.000, 1.000)])
"""参数:
- 强弱: 默认1.00, 0.00 ~ 1.00
"""
环绕音 = Effect_meta("环绕音", False, "7161319847819743780", "5723960", "fa9a4cb20d3488bf79e176571d5841f5", [
Effect_param("change_voice_param_center_position", 0.500, 0.000, 1.000),
Effect_param("change_voice_param_surrounding_frequency", 0.500, 0.000, 1.000)])
"""参数:
- change_voice_param_center_position: 默认0.50, 0.00 ~ 1.00
- change_voice_param_surrounding_frequency: 默认0.50, 0.00 ~ 1.00
"""
电音 = Effect_meta("电音", False, "7018011438379700773", "2672754", "d893a319d5175d9f09f70ddef1f79980", [
Effect_param("强弱", 1.000, 0.000, 1.000)])
"""参数:
- 强弱: 默认1.00, 0.00 ~ 1.00
"""
颤音 = Effect_meta("颤音", False, "7018011370289369637", "2672755", "c5e4874f83337e1cb9f8322fb843c901", [
Effect_param("频率", 0.714, 0.000, 1.000),
Effect_param("幅度", 0.905, 0.000, 1.000)])
"""参数:
- 频率: 默认0.71, 0.00 ~ 1.00
- 幅度: 默认0.91, 0.00 ~ 1.00
"""
麦霸 = Effect_meta("麦霸", False, "7018012141332468260", "2672748", "3eedef5ef82b32912203a1f4fb901182", [
Effect_param("空间大小", 0.052, 0.000, 1.000),
Effect_param("强弱", 0.450, 0.000, 1.000)])
"""参数:
- 空间大小: 默认0.05, 0.00 ~ 1.00
- 强弱: 默认0.45, 0.00 ~ 1.00
"""
黑胶 = Effect_meta("黑胶", False, "7024391411764040205", "2672761", "59e61d687a0f612bfae43bccf770f090", [
Effect_param("强弱", 1.000, 0.000, 1.000),
Effect_param("噪点", 0.743, 0.000, 1.000)])
"""参数:
- 强弱: 默认1.00, 0.00 ~ 1.00
- 噪点: 默认0.74, 0.00 ~ 1.00
"""
# 付费
_3d环绕音 = Effect_meta("3d环绕音", True, "7350214888242811455", "53187169", "577c3d8e5312012b1d98ba5fc0b206d0", [
Effect_param("强度", 0.000, 0.000, 1.000)])
"""参数:
- 强度: 默认0.00, 0.00 ~ 1.00
"""
Autotune = Effect_meta("Autotune", True, "7360900806851170828", "58979352", "1477f4ca8307e2fa4ee2243d98d8b837", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
下雨 = Effect_meta("下雨", True, "7375069649446113804", "68076030", "83bb223637d5368384c47e3d2b061b62", [
Effect_param("strength", 1.000, 0.000, 1.000),
Effect_param("noise", 0.743, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
- noise: 默认0.74, 0.00 ~ 1.00
"""
乡村大喇叭 = Effect_meta("乡村大喇叭", True, "7282691036197950009", "23897651", "c996243ac50d235f00e5931e5ecadc52", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
人声增强 = Effect_meta("人声增强", True, "7106404399756349983", "2673078", "626f988dbd2cbd17acaa24d08451e314", [
Effect_param("强弱", 1.000, 0.000, 1.000)])
"""参数:
- 强弱: 默认1.00, 0.00 ~ 1.00
"""
低音增强 = Effect_meta("低音增强", True, "7106404304247853604", "2673080", "e7c09c96d10c163269fc4e35c1f4b1ee", [
Effect_param("change_voice_param_strength", 1.000, 0.000, 1.000)])
"""参数:
- change_voice_param_strength: 默认1.00, 0.00 ~ 1.00
"""
停车场 = Effect_meta("停车场", True, "7372150242524795446", "66413024", "d2dd515293081a8573485159db5a71e0", [
Effect_param("strength", 1.000, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
"""
冰川之下 = Effect_meta("冰川之下", True, "7375068986829967883", "68076029", "6b9cda93f6d75b9a3b19b2e8eb6ad40f", [
Effect_param("strength", 1.000, 0.000, 1.000),
Effect_param("noise", 0.743, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
- noise: 默认0.74, 0.00 ~ 1.00
"""
刮风 = Effect_meta("刮风", True, "7375069247275274771", "68076028", "8600891882159f364d8c53e4f703cff4", [
Effect_param("strength", 1.000, 0.000, 1.000),
Effect_param("noise", 0.743, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
- noise: 默认0.74, 0.00 ~ 1.00
"""
噪音混响 = Effect_meta("噪音混响", True, "7382844688987853349", "72110975", "3b3b09b530b0a64666f1c5b6d20d4018", [
Effect_param("strength", 1.000, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
"""
地狱 = Effect_meta("地狱", True, "7375069113988682281", "68076027", "5ec03c41ada16530949daa4106c85a90", [
Effect_param("strength", 1.000, 0.000, 1.000),
Effect_param("noise", 0.743, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
- noise: 默认0.74, 0.00 ~ 1.00
"""
复古收音机 = Effect_meta("复古收音机", True, "7350215379714576907", "53187166", "301d642d131aabff7ea8c3b717b36a79", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
失真电子 = Effect_meta("失真电子", True, "7350215296801575443", "53187167", "a1c00df42076ed1bd6a81f2d30b94566", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
对讲机 = Effect_meta("对讲机", True, "7350214704284832275", "53187168", "016dbdb3c786896c92bb936ece11acf6", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
房间 = Effect_meta("房间", True, "7282691385872880165", "23880629", "639f5c0c6b20418aaeb0e144da21151c", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
捂嘴 = Effect_meta("捂嘴", True, "7372405649684042292", "66552320", "9f9a8270c0005a480547d6ddf2a9293a", [
Effect_param("strength", 1.000, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
"""
教堂 = Effect_meta("教堂", True, "7282691146759803429", "23882063", "96dc71756d0025e96a504b42d988b2ac", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
教室 = Effect_meta("教室", True, "7282687783833965113", "23897703", "678c14a6f63f75e03daa062a254081f7", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
机器人2 = Effect_meta("机器人2", True, "7372150541738054156", "66413023", "952f3feddf3555939adbbfd1c1869474", [
Effect_param("strength", 1.000, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
"""
沙漠 = Effect_meta("沙漠", True, "7375069515530375691", "68076025", "099c935428943c9c3662b15b35b1ee36", [
Effect_param("strength", 1.000, 0.000, 1.000),
Effect_param("noise", 0.743, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
- noise: 默认0.74, 0.00 ~ 1.00
"""
派对 = Effect_meta("派对", True, "7381685442795541042", "71718513", "723386ab87f938779a3369436234d903", [
Effect_param("strength", 1.000, 0.000, 1.000),
Effect_param("noise", 0.743, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
- noise: 默认0.74, 0.00 ~ 1.00
"""
深海回声 = Effect_meta("深海回声", True, "7350215168413929995", "53187172", "37a16a2dc77540b7d70fe301e482d4f2", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
电话 = Effect_meta("电话", True, "7264894634285863483", "20255003", "5da5a98b8c926c0dcc1c3c8bc3f3012f", [
Effect_param("强弱", 0.700, 0.000, 1.000)])
"""参数:
- 强弱: 默认0.70, 0.00 ~ 1.00
"""
留声机 = Effect_meta("留声机", True, "7282687663872676408", "23897797", "e692fae669650c948451b5811a04e7e6", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
百老汇 = Effect_meta("百老汇", True, "7372150379150053907", "66413025", "73e3a35496b9766d0400165844be72f1", [
Effect_param("strength", 1.000, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
"""
空灵感 = Effect_meta("空灵感", True, "7350215092975178252", "53187171", "aa1887a8b3375d20df6bf9438d62083a", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
空谷回声 = Effect_meta("空谷回声", True, "7350214991628210727", "53187170", "9913daa32167a17c1f41ad2f5596c411", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
老式电话 = Effect_meta("老式电话", True, "7282691476843139621", "23880011", "2eb835175e1e72e9d86b09bf513077cf", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
言灵术 = Effect_meta("言灵术", True, "7382844601435951653", "72110974", "7184386e75226a36942c60a5d5bb5618", [
Effect_param("strength", 1.000, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
"""
豪宅回声 = Effect_meta("豪宅回声", True, "7360900963294515775", "58979353", "7c20b5fba991f3188f14d7cdb0de1fa1", [
Effect_param("强度", 1.000, 0.000, 1.000)])
"""参数:
- 强度: 默认1.00, 0.00 ~ 1.00
"""
迷幻电子 = Effect_meta("迷幻电子", True, "7375069381769826879", "68076026", "ce220d25a6f95bd31a81f6421bbf2525", [
Effect_param("strength", 1.000, 0.000, 1.000),
Effect_param("noise", 0.743, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
- noise: 默认0.74, 0.00 ~ 1.00
"""
class Speech_to_song_type(Effect_enum):
"""剪映自带的音频“声音成曲”效果类型, 此类效果目前不能自动被剪映所识别"""
Lofi = Effect_meta("Lofi", False, "7252917861948068410", "17345060", "8dd8889045e6c065177df791ddb3dfb8", [])
民谣 = Effect_meta("民谣", False, "7251868698170888759", "17046923", "8dd8889045e6c065177df791ddb3dfb8", [])
嘻哈 = Effect_meta("嘻哈", True, "7252918249036190245", "17344948", "8dd8889045e6c065177df791ddb3dfb8", [])
爵士 = Effect_meta("爵士", True, "7264413578860433978", "20120940", "8dd8889045e6c065177df791ddb3dfb8", [])
节奏蓝调 = Effect_meta("节奏蓝调", True, "7252918101958726200", "17345046", "8dd8889045e6c065177df791ddb3dfb8", [])
雷鬼 = Effect_meta("雷鬼", True, "7264413386962637368", "20120864", "8dd8889045e6c065177df791ddb3dfb8", [])
@@ -1,190 +0,0 @@
from .effect_meta import Effect_enum
from .animation_meta import Animation_meta
class CapCut_Intro_type(Effect_enum):
"""CapCut自带的入场动画, 默认时长为0.5秒"""
Fade_In = Animation_meta("Fade In", False, 0.500, "6798320778182922760", "6798320778182922760", "883ad04bd79b502aaa55b5d9b87175ea")
Zoom_1 = Animation_meta("Zoom 1", False, 0.500, "6740868384637850120", "6740868384637850120", "6444aa1a1706f02003f9c56c4c0757b3")
Rock_Vertically = Animation_meta("Rock Vertically", False, 0.500, "6739418390030455300", "6739418390030455300", "c55e541676bc97120a3985ee7bde44cc")
Slide_Down = Animation_meta("Slide Down", False, 0.500, "6798333705401143816", "6798333705401143816", "dd4a5c03f0ee1a03413b9166c9b2e254")
Slide_Up = Animation_meta("Slide Up", False, 0.500, "6798333487523828238", "6798333487523828238", "51657913dffa9f4c5f9d4411b53611e5")
Slide_Right = Animation_meta("Slide Right", False, 0.500, "6798333076469453320", "6798333076469453320", "abb44c05890e39fdfeb58abc8524c1a6")
Slide_Left = Animation_meta("Slide Left", False, 0.500, "6798332871267324423", "6798332871267324423", "667952e8cf6918f62e16b8e6dfc2fef2")
Rotate = Animation_meta("Rotate", False, 0.500, "6798334070653719054", "6798334070653719054", "c97081cea815078e71a6c51197ed8b33")
Flame_Risen = Animation_meta("Flame Risen", False, 2.867, "7447086181751198224", "7447086181751198224", "37f3e9ceaabb3b3a50a353d223149ba3")
Rotation_Opening = Animation_meta("Rotation Opening", False, 1.000, "7197354677820723714", "7197354677820723714", "8308459d002ce5bd241c93a82acaad72")
Retro_Fadein_2 = Animation_meta("Retro Fade-in 2", False, 2.000, "7473710409103446545", "7473710409103446545", "74b90ae9e4ac14acefcd1e42f09f7e46")
Retro_Fadein = Animation_meta("Retro Fade-in", False, 2.000, "7473710410428846608", "7473710410428846608", "9ee9890543a20651e4b2a6ff7b09237a")
Screen_Wipe = Animation_meta("Screen Wipe", False, 2.000, "7450390477871780353", "7450390477871780353", "a37e8b30f8debf2be5c931369dee8408")
RGB_Scanlines = Animation_meta("RGB Scanlines", False, 1.000, "7480796814837304581", "7480796814837304581", "40ca0fd33319c572ff6d1a5bc209d8b2")
Zoom_2 = Animation_meta("Zoom 2", False, 0.500, "6740867832570974733", "6740867832570974733", "4c241a9c8ef566b91b6a499c33648062")
Zoom_Out = Animation_meta("Zoom Out", False, 0.500, "6798332584276267527", "6798332584276267527", "0c736f993d36a7b1ef00cc73d2ba656f")
Zoom_In = Animation_meta("Zoom In", False, 0.500, "6798332733694153230", "6798332733694153230", "028a77e121c22a4dd130a46a0ed90714")
Shake_3 = Animation_meta("Shake 3", False, 0.500, "6781683302672634382", "6781683302672634382", "e2799421fc7fc57796222bd27966c812")
CRT_Bands = Animation_meta("CRT Bands", False, 2.000, "7473710408977617424", "7473710408977617424", "21a440db23f032255ea2ad9544d7a4d2")
Vibrating_Panels = Animation_meta("Vibrating Panels", False, 2.000, "7473710409023754753", "7473710409023754753", "3c51bc51a78c387f21034e770ff2c82c")
Swing_Top_Right = Animation_meta("Swing Top Right", False, 0.500, "6740122731418751495", "6740122731418751495", "e807e0130c771613d50ebac118fb9ee7")
Anime_Frame = Animation_meta("Anime Frame", False, 1.000, "7460018714935562769", "7460018714935562769", "bc473429a461fc519c74651c1e736461")
Rock_Horizontally = Animation_meta("Rock Horizontally", False, 0.500, "6739418540421419524", "6739418540421419524", "e3b4c7ff19cc1d221ffff7b69f55a2fd")
Gray_Mask = Animation_meta("Gray Mask", False, 1.533, "7473710409040531985", "7473710409040531985", "861023094b989c46ca97f3c51e95e046")
Shake_1 = Animation_meta("Shake 1", False, 0.500, "6739418227031413256", "6739418227031413256", "72fb15b943898171056a76fb509880af")
Spin_Up_2 = Animation_meta("Spin Up 2", False, 0.500, "6818747060649464327", "6818747060649464327", "4d972df8465406e54473cf550e7d96ff")
Whirl = Animation_meta("Whirl", False, 0.500, "6782010677520241165", "6782010677520241165", "03a38600832cda8d47c82e121513efd4")
Mini_Zoom = Animation_meta("Mini Zoom", False, 0.500, "6800268825611735559", "6800268825611735559", "b547d896cac3d5e620033e53f139426d")
Spin_Up_1 = Animation_meta("Spin Up 1", False, 0.500, "6808401616564130312", "6808401616564130312", "18e8ea7ff7f074aa56f5449d4daca501")
Swing_Bottom = Animation_meta("Swing Bottom", False, 0.500, "6739338374441603598", "6739338374441603598", "4c3ac20ec647fc31079df672e39bf1f7")
Swing_Right = Animation_meta("Swing Right", False, 0.500, "6739338727866241539", "6739338727866241539", "03aa26f798ad7fbb98880e35bc128829")
Swing_Bottom_Left = Animation_meta("Swing Bottom Left", False, 0.500, "6739395445346275853", "6739395445346275853", "5b8031554e3c336f9275933f48ef688a")
Flip = Animation_meta("Flip", False, 0.500, "6797338697625768455", "6797338697625768455", "94e00999e45d4ef7715901152889b07a")
Shake_2 = Animation_meta("Shake 2", False, 0.500, "6739418677910704651", "6739418677910704651", "dc958f2f8ad9124767731914748f5413")
Blinds = Animation_meta("Blinds", False, 0.500, "6782101071402635790", "6782101071402635790", "e7f3101f49c2891c627275f0aadfd242")
Swing_Bottom_Right = Animation_meta("Swing Bottom Right", False, 0.500, "6739395718223499787", "6739395718223499787", "1101f5affae043d86067251bd64c86db")
Puzzle = Animation_meta("Puzzle", False, 0.500, "6778300107113632269", "6778300107113632269", "1343011abfd6982e186ac5403bc377ca")
Swing_Top_Left = Animation_meta("Swing Top Left", False, 0.500, "6740122563692728844", "6740122563692728844", "c442ab84beaa8da41f731d13d61a28f0")
Shake_Down = Animation_meta("Shake Down", False, 0.500, "6995802540361126402", "6995802540361126402", "660ccbf427bc7d885fe6b789c166d8f1")
Swing = Animation_meta("Swing", False, 0.500, "6803260897117606414", "6803260897117606414", "f3fa59690a9bcceed01b594cc363598b")
Wiper = Animation_meta("Wiper", False, 0.500, "6802871256849846791", "6802871256849846791", "bfc925823097f5f8a0f460133d35280a")
Roll_Right = Animation_meta("Roll Right", False, 0.500, "6805019065761927694", "6805019065761927694", "1096226c559457f5b95b55e4a224f4df")
Spin_Left = Animation_meta("Spin Left", False, 0.500, "6816560956647150093", "6816560956647150093", "43de115d1158ea57027635b7a3cf0478")
class CapCut_Outro_type(Effect_enum):
"""CapCut自带的出场动画, 默认时长为0.5秒"""
Fade_Out = Animation_meta("Fade Out", False, 0.500, "6798320902548230669", "6798320902548230669", "c6f05ce62355b537be762550040bfc08")
RGB_Scanlines = Animation_meta("RGB Scanlines", False, 1.000, "7480796062245014790", "7480796062245014790", "75447137a5f585089d33445eda2ecea4")
Blurred_Fadein = Animation_meta("Blurred Fade-in", False, 2.000, "7473710407329255953", "7473710407329255953", "0b044ebdb1a22f212aa537ff91d72f46")
Slide_Down = Animation_meta("Slide Down", False, 0.500, "6798333787986989576", "6798333787986989576", "c1f3d6530ffa1646b03fbaa22266f04b")
Slide_Up = Animation_meta("Slide Up", False, 0.500, "6798333612958683656", "6798333612958683656", "443a2085da756085ed06e2e338f76523")
Slide_Right = Animation_meta("Slide Right", False, 0.500, "6798333350487527950", "6798333350487527950", "55fd54674cdd4de3f6a7b1d1482c308c")
Slide_Left = Animation_meta("Slide Left", False, 0.500, "6798332972098392584", "6798332972098392584", "45dc53f993e77e2dbbcbc2de8df5f092")
Blurred_Fadein_1 = Animation_meta("Blurred Fade-in", False, 2.000, "7473710410407875073", "7473710410407875073", "7aaa4899430661fd955f898f6ea7796c")
Zoom_In = Animation_meta("Zoom In", False, 0.500, "6798332801864176142", "6798332801864176142", "01497dc221d288e623a10cac94a5ceca")
CRT_Bands = Animation_meta("CRT Bands", False, 2.000, "7473710409145389585", "7473710409145389585", "63782405a7730ecadf707fb8d41cf013")
Flame_Risen = Animation_meta("Flame Risen", False, 2.967, "7447086181742825985", "7447086181742825985", "cfae1a683f11299f0c1d133d436b2746")
Screen_Wipe = Animation_meta("Screen Wipe", False, 2.000, "7450390477863408129", "7450390477863408129", "0ac1cfe94bb7f54b8a38dc0de67b05ca")
Rotation_Closing = Animation_meta("Rotation Closing", False, 1.000, "7197354764579901953", "7197354764579901953", "c9ff648f5a206e0da5be0d60a286b403")
Rotate = Animation_meta("Rotate", False, 0.500, "6798334141323547143", "6798334141323547143", "982f83d952f2161660d781a9542d76a9")
Anime_Frame = Animation_meta("Anime Frame", False, 1.000, "7460018714935579152", "7460018714935579152", "bc473429a461fc519c74651c1e736461")
Zoom_Out = Animation_meta("Zoom Out", False, 0.500, "6798332648814023181", "6798332648814023181", "a719ad21c4968b730d366d4f92b792c5")
Rotate_Out_1 = Animation_meta("Rotate Out 1", False, 0.500, "6818747115934585357", "6818747115934585357", "7bd213e79bc1bd54a241be243dbbf8be")
Mini_Zoom = Animation_meta("Mini Zoom", False, 0.500, "6800268611807089166", "6800268611807089166", "094a9454e856be4ef2f43c391a7d6b38")
Gray_Mask = Animation_meta("Gray Mask", False, 1.533, "7473710410357543425", "7473710410357543425", "947652cf982d4868e8f9ebe19308e959")
Whirl = Animation_meta("Whirl", False, 0.500, "6778418947361346061", "6778418947361346061", "107ee2571bae820df3912ebe83b7d899")
Vibrating_Panels = Animation_meta("Vibrating Panels", False, 2.000, "7473710409195721233", "7473710409195721233", "4bcf3a8724c7c709b1d008d758728357")
Rotate_Out_2 = Animation_meta("Rotate Out 2", False, 0.500, "6818747169017696781", "6818747169017696781", "e4324969c3f4e215227dfd91402ddb85")
Flip = Animation_meta("Flip", False, 0.500, "6738353628215513613", "6738353628215513613", "9c3bd6309ff93abc7da1e22be6d103ab")
class CapCut_Group_animation_type(Effect_enum):
"""CapCut自带的组合动画, 默认时长为0.5秒"""
Zoom_1 = Animation_meta("Zoom 1", False, 4.000, "6759078592740594184", "6759078592740594184", "cac9a365aab6a7fe878431abd85d4b5d")
Stretch_and_distort = Animation_meta("Stretch and distort", False, 3.500, "7032223224863658497", "7032223224863658497", "4f1a31ff5cb6cf8223512aa55d16f3d9")
Bounce_1 = Animation_meta("Bounce 1", False, 2.500, "6795425591014199822", "6795425591014199822", "67f82884f9d3a9069479925989811c35")
Sway_Out = Animation_meta("Sway Out", False, 4.000, "6789167998700622350", "6789167998700622350", "b3b5bbf151c2f6cd6883ca88ab955cd0")
_3D_card_2 = Animation_meta("3D card 2", False, 4.000, "6836319649844433415", "6836319649844433415", "f5555b74fed96dd78c5b292b035595b3")
Slide_and_wave = Animation_meta("Slide and wave", False, 4.000, "7032224062973678082", "7032224062973678082", "1ba51897f314706b2fd04d1852f6d38c")
Pendulum_1 = Animation_meta("Pendulum 1", False, 4.000, "6811007755785081357", "6811007755785081357", "47cc5d94c283293166c3d3d3fde86655")
Wobble = Animation_meta("Wobble", False, 2.500, "6761360765925462536", "6761360765925462536", "87049bd0502eb6e07aaba92e83b8b09d")
Wave_and_slide = Animation_meta("Wave and slide", False, 1.633, "7032223862586610178", "7032223862586610178", "c3bfd4dfce887af6305579b04327cd64")
Enlarge_and_bounce = Animation_meta("Enlarge and bounce", False, 2.000, "7032223659116728833", "7032223659116728833", "18bfc84500372c9a49023c1a77efa6e5")
Distort_and_stretch = Animation_meta("Distort and stretch", False, 0.033, "7032223355365233154", "7032223355365233154", "e0a1f868f0161970c4d2a2f5ae3c6896")
Pendulum_2 = Animation_meta("Pendulum 2", False, 1.000, "6811007833069326862", "6811007833069326862", "4958eff996309ec58d9d5d13810d49fd")
Zoom_2 = Animation_meta("Zoom 2", False, 2.000, "6779083172429697544", "6779083172429697544", "60cdf52561e071069e0a3fdcb5b704c7")
Sway_In = Animation_meta("Sway In", False, 3.500, "6789167874511475207", "6789167874511475207", "b658fe0ba15b223730949f885fd5a470")
BendZoom = Animation_meta("Bend-Zoom", False, 3.500, "6777260789263766030", "6777260789263766030", "641101ae551a661560994dca7c8c4809")
Bounce_2 = Animation_meta("Bounce 2", False, 4.000, "6795425422046663182", "6795425422046663182", "c37bbe6dbe2a75321b9fbf1bb2c3756c")
Spin_Rise = Animation_meta("Spin Rise", False, 4.000, "6813965670716281352", "6813965670716281352", "a04cb028ba78bf152840dfe9ef94f6fb")
Train_2 = Animation_meta("Train 2", False, 4.000, "6860406007160377863", "6860406007160377863", "572c74f24408cb0c7db3567ce29ace09")
Spin = Animation_meta("Spin", False, 1.467, "6829129745226011144", "6829129745226011144", "21db4621193a6f135c5101ba87dfc0e3")
Shrink_and_bounce = Animation_meta("Shrink and bounce", False, 2.500, "7032223526635442690", "7032223526635442690", "bca5ca47f6f33268fb1de55fa8946519")
Smartphone_1 = Animation_meta("Smartphone 1", False, 2.500, "6861892418334102030", "6861892418334102030", "6ae8e419d84d1dadd79f2c816a453806")
Distort_Right = Animation_meta("Distort Right", False, 3.500, "6851395907804467720", "6851395907804467720", "7712b11531b0afd5187f0a4952a6e520")
Trisect_2 = Animation_meta("Trisect 2", False, 4.000, "6874466931919819266", "6874466931919819266", "4fe7ed9ccc1834224d0c3fd3985a908b")
Train_4 = Animation_meta("Train 4", False, 3.467, "6860406196130550286", "6860406196130550286", "0bde5bf5f5a7d3ce8d869671ec034c3e")
Fall_Spin = Animation_meta("Fall Spin", False, 4.500, "6759075297091392007", "6759075297091392007", "31cbe2991de64f5ff8e478b5643a3c5d")
_3D_card_1 = Animation_meta("3D card 1", False, 4.500, "6836319728038842894", "6836319728038842894", "2177261ca87ec366db301c046c2a7b54")
Spinning_top_2 = Animation_meta("Spinning top 2", False, 4.500, "6876994663325110786", "6876994663325110786", "035a6bc939af9eb7376009b185e12cf7")
Fall_Right = Animation_meta("Fall Right", False, 4.500, "6781683518222111239", "6781683518222111239", "c40c11d1a6dc09ec68a93044eb349fac")
Pan_Right = Animation_meta("Pan Right", False, 4.500, "6772415374165021191", "6772415374165021191", "e47d729d30ec77b361f163ecb37c20dc")
Distort_Left = Animation_meta("Distort Left", False, 4.500, "6851395726937690637", "6851395726937690637", "48d34352aeb9aee85801abb7cb81d840")
Slip_and_slide_2 = Animation_meta("Slip and slide 2", False, 4.500, "6828829741013799432", "6828829741013799432", "0b89958e782890e475cb21cf71d697f5")
Slip_and_slide_1 = Animation_meta("Slip and slide 1", False, 4.500, "6828829568879563271", "6828829568879563271", "2ffbf81b3f77f966b697698291078308")
Roll_InOut_2 = Animation_meta("Roll In&Out 2", False, 4.500, "6818747242258633224", "6818747242258633224", "efb9910c822718c31648d61da2e6f7d2")
Right_Zoom = Animation_meta("Right Zoom", False, 4.500, "6772415063216099848", "6772415063216099848", "64d73a2a8d4b857816f103d1d0496adc")
Slice__Rotate_2 = Animation_meta("Slice & Rotate 2", False, 4.500, "6900760591321797121", "6900760591321797121", "2816ae00206cc067d0fac4905b4ebd65")
Cube_3 = Animation_meta("Cube 3", False, 4.500, "6841793140949520910", "6841793140949520910", "c8a758318bd0b421006767cd08cc8524")
Pirate_ship_1 = Animation_meta("Pirate ship 1", False, 4.500, "6830302168751280648", "6830302168751280648", "44fd11d2b67322a3954b33eb8851091e")
Bisect_2 = Animation_meta("Bisect 2", False, 4.500, "6856970411352003080", "6856970411352003080", "035cfab958d2e0bec0ae60c39e6e6eb7")
Pan_Left = Animation_meta("Pan Left", False, 4.500, "6772415248973435395", "6772415248973435395", "0126690613352a2cf97550b6a8181c4e")
Train_3 = Animation_meta("Train 3", False, 4.500, "6860406091700769293", "6860406091700769293", "6d1607c50ea210073b17afaa6da87afd")
Train_1 = Animation_meta("Train 1", False, 4.500, "6860405888784536072", "6860405888784536072", "02b09df0a764000d55892ea96a5a5b27")
Magic_Cube_2 = Animation_meta("Magic Cube 2", False, 4.500, "6872233503220568578", "6872233503220568578", "6bd6ee4f2cbd13049e0b670b0bec8174")
Yoyo_2 = Animation_meta("Yo-yo 2", False, 4.500, "6821451462904648200", "6821451462904648200", "930d3141277ddda51fb05002595f599e")
_3D_card_5 = Animation_meta("3D card 5", False, 5.000, "6836319888827486728", "6836319888827486728", "ae1d9e7741f5bc6ccd231acf10ebc813")
Fall_Bottom_Right = Animation_meta("Fall Bottom Right", False, 5.000, "6781683438396117517", "6781683438396117517", "7a75f84f6f9c82870d22e6bb89300a52")
_3D_card_3 = Animation_meta("3D card 3", False, 5.000, "6836319781004513805", "6836319781004513805", "0e37189a4f9c953672ab959403f2c851")
Funhouse_mirror_1 = Animation_meta("Funhouse mirror 1", False, 5.000, "6832226792556728846", "6832226792556728846", "42e24b02b48a069eda3bae90ba69ea28")
Revolving_Checker_2 = Animation_meta("Revolving Checker 2", False, 5.000, "6894449215796154882", "6894449215796154882", "50b1a6caf0ad4c57295a318ea8020447")
Roll_InOut_1 = Animation_meta("Roll In&Out 1", False, 5.000, "6805012562174808590", "6805012562174808590", "6d6d61a51dc4425a7b9a4e29c8d6d6c3")
Left_Zoom = Animation_meta("Left Zoom", False, 5.000, "6772415148423385607", "6772415148423385607", "2b170a07ed5b6eea5753a34c6ed2d50b")
Fall_Left = Animation_meta("Fall Left", False, 5.000, "6759351225772151303", "6759351225772151303", "3b4ea61a67352fb9f1d22e1bd7cd17f6")
Checker_Slide_2 = Animation_meta("Checker Slide 2", False, 5.000, "6885172240342585857", "6885172240342585857", "af11a9469a4cd4f2c10f001a07ed4401")
Waltzer_2 = Animation_meta("Waltzer 2", False, 5.000, "6850287920255865357", "6850287920255865357", "4b91788d470dc3407aaa2ffc40fb6578")
Smartphone_3 = Animation_meta("Smartphone 3", False, 5.000, "6862918366550561294", "6862918366550561294", "5500e7b47698dd5fe75410d84783d0e7")
Spinning_top_1 = Animation_meta("Spinning top 1", False, 5.000, "6876994577786475010", "6876994577786475010", "c1c40ff93670136bbd0286f345b501d3")
Smaller = Animation_meta("Smaller", False, 5.000, "6759046644462785037", "6759046644462785037", "1f5d674d24ae59aa475b370e2153fe6c")
Zoom_Spin = Animation_meta("Zoom Spin", False, 5.000, "6760119657429996046", "6760119657429996046", "1b332dcc28c53b4b6d65917f4253f15f")
Spin_In = Animation_meta("Spin In", False, 5.000, "6810286558826992136", "6810286558826992136", "7c5154b92cb9eaf62dfe6a8b862af720")
Fall_Bottom_Left = Animation_meta("Fall Bottom Left", False, 5.000, "6760223716392571395", "6760223716392571395", "e6540724540a619734bea5758c488513")
Yoyo_1 = Animation_meta("Yo-yo 1", False, 5.000, "6821451358101574152", "6821451358101574152", "4221221eb86e8473b568c9783af55591")
Flip_6 = Animation_meta("Flip 6", False, 5.000, "6843310299991249421", "6843310299991249421", "e6eca0c277134d07217d5e9c67941117")
Funhouse_mirror_2 = Animation_meta("Funhouse mirror 2", False, 5.000, "6832226909875606029", "6832226909875606029", "e2978681483020a37fc79ab92d7234b4")
ZoomRoll = Animation_meta("Zoom-Roll", False, 5.000, "6805018974070247950", "6805018974070247950", "a77c79a553bc381cf0709c05e71ebdf8")
_3D_card_4 = Animation_meta("3D card 4", False, 5.000, "6836319828656001550", "6836319828656001550", "5a283eddf746a7dca43522681d2a0fef")
Spin_Fall = Animation_meta("Spin Fall", False, 5.000, "6759046515521491464", "6759046515521491464", "050514f87393b3f12b85d8563ee078c5")
Cube = Animation_meta("Cube", False, 5.000, "6837352063496622599", "6837352063496622599", "6cf65fcb4b6c9ffde44453a5bed75e6c")
Fan_Out = Animation_meta("Fan Out", False, 5.000, "6885172192766595585", "6885172192766595585", "22ce9336e5716a87d6a2a980f6b84e78")
Triplets_1 = Animation_meta("Triplets 1", False, 5.000, "6868146033247916558", "6868146033247916558", "2a30e5f26dc2f857c7701608186849c4")
Magic_Cube_1 = Animation_meta("Magic Cube 1", False, 5.000, "6872233360521957890", "6872233360521957890", "2a3a439dccad5615dae22e343990265c")
_3D_card_6 = Animation_meta("3D card 6", False, 5.000, "6839582631345000967", "6839582631345000967", "62b36ad9c0ebf58d48f901b82f6dda66")
Quarter_2 = Animation_meta("Quarter 2", False, 5.000, "6865579178599649806", "6865579178599649806", "bdab1437e1f2531c3e763a30821748ab")
Spin_Out = Animation_meta("Spin Out", False, 5.000, "6810286613898203661", "6810286613898203661", "f98cbb7677a7b7eb3b40922162635a91")
Pirate_ship_2 = Animation_meta("Pirate ship 2", False, 5.000, "6830302282995732999", "6830302282995732999", "dcfdf23a704abb026623c00913d085ba")
Bisect_Domino_2 = Animation_meta("Bisect Domino 2", False, 5.000, "6887447494821679617", "6887447494821679617", "681f4f5d57af86bad50d1f314a1bb36f")
Waltzer_4 = Animation_meta("Waltzer 4", False, 5.000, "6854782786553778695", "6854782786553778695", "ca260e5c700b69406c106bb4f372168c")
Rise_Spin = Animation_meta("Rise Spin", False, 5.000, "6813965595915063815", "6813965595915063815", "9c9f40961508028be988a103f40f7071")
Puzzle = Animation_meta("Puzzle", False, 5.000, "6778405418969338382", "6778405418969338382", "92aa7ffce8c23041f0e556013acff086")
Bisect_1 = Animation_meta("Bisect 1", False, 5.000, "6856970350270353928", "6856970350270353928", "2eac59ac28531dd3f9ee78c22343fafa")
Pirate_ship_3 = Animation_meta("Pirate ship 3", False, 5.000, "6830302335047045639", "6830302335047045639", "5118eb6d02a84c39ffb678f6ecbc895a")
Pirate_ship_4 = Animation_meta("Pirate ship 4", False, 5.000, "6830302424826122765", "6830302424826122765", "09c1204e3f3f44bfadf2a55cd6a4000b")
Checker_Slide_1 = Animation_meta("Checker Slide 1", False, 5.000, "6885172212056199681", "6885172212056199681", "b62622615f1adb22bf5df9bfe4e8c307")
Waltzer_1 = Animation_meta("Waltzer 1", False, 5.000, "6850287838441771534", "6850287838441771534", "8b3b09b0e8c3b1a7f3f580f86dffc763")
Smartphone_2 = Animation_meta("Smartphone 2", False, 5.000, "6862918279183208973", "6862918279183208973", "33f8b44f27e06e16e1dfdf52794a3ed0")
Sliding_Doors_1 = Animation_meta("Sliding Doors 1", False, 5.000, "6885172172587799041", "6885172172587799041", "de31f6d54856f05a0824eab7afac58e7")
Split_up__down_2 = Animation_meta("Split up & down 2", False, 5.000, "6876994486052852225", "6876994486052852225", "4e6cbade1d8b48cd6b8473e40bc8d12e")
Cube_2 = Animation_meta("Cube 2", False, 5.000, "6841793224663634446", "6841793224663634446", "c167baef667407ab0e1e6fca48ef6c3c")
Crystal_1 = Animation_meta("Crystal 1", False, 5.000, "6857333749718192654", "6857333749718192654", "156f60965f55684a158197bbf5bcc029")
Angle_1 = Animation_meta("Angle 1", False, 5.000, "6847734302193488392", "6847734302193488392", "fa0a52a3ef758e27359bb014bccdc9fc")
Trisect_1 = Animation_meta("Trisect 1", False, 5.000, "6874467891899535873", "6874467891899535873", "8e66f5e6bc1a881fc62679276bb7cabe")
Flip_2 = Animation_meta("Flip 2", False, 5.000, "6843310029689328135", "6843310029689328135", "520adf156b9f908075227cf58f57c3f5")
Waltzer_3 = Animation_meta("Waltzer 3", False, 5.000, "6854782718975152653", "6854782718975152653", "187f66ad384afff2a83c06df1b1ddfc7")
Blinds = Animation_meta("Blinds", False, 5.000, "7425512249630002437", "7425512249630002437", "61e2ab1e9b0a47af6aa057997562934e")
Crystal_2 = Animation_meta("Crystal 2", False, 5.000, "6857333869541069325", "6857333869541069325", "6e7642751a8dbcaf1a4a848a68691b17")
Triplets_2 = Animation_meta("Triplets 2", False, 5.000, "6868146123710665223", "6868146123710665223", "537a84c9befbb05f44ae713121d9418d")
Angle_2 = Animation_meta("Angle 2", False, 5.000, "6847734360636920327", "6847734360636920327", "0be39058880e8d7e73430e6aa9a57591")
Cube_3_1 = Animation_meta("Cube 3", False, 5.000, "6834812541118452237", "6834812541118452237", "7c3b8d6ab6175e1cbe2c008306d41c10")
Cube_2_1 = Animation_meta("Cube 2", False, 5.000, "6834812485023830535", "6834812485023830535", "00a120634edb134ca67c16147f13c9c3")
Slice__Rotate_1 = Animation_meta("Slice & Rotate 1", False, 5.000, "6900760492877287938", "6900760492877287938", "6043ed4691fab54f724e9fb60a74389b")
Quarter_1 = Animation_meta("Quarter 1", False, 5.000, "6865578846393995784", "6865578846393995784", "ede54a888ccea145ced3e377a9cb031a")
Revolving_Checker_1 = Animation_meta("Revolving Checker 1", False, 5.000, "6894449368728867329", "6894449368728867329", "12dd7150e6a6f9dacfbd3669c2b0bd9a")
Flip_II = Animation_meta("Flip II", False, 5.000, "6843309964732142094", "6843309964732142094", "fc95809653133b181421de3bc8880602")
Flip_3 = Animation_meta("Flip 3", False, 5.000, "6843310084743762446", "6843310084743762446", "2d0f1613c434cbc83557e4288a0be8a5")
Flip_4 = Animation_meta("Flip 4", False, 5.000, "6843310129736061447", "6843310129736061447", "e477e654de34a7b82a8a1ce23ee5ae5a")
Rollercoaster_1 = Animation_meta("Roller-coaster 1", False, 5.000, "6872233216867045890", "6872233216867045890", "efa94806c6ac55227fbca7c847ae27ad")
Rollercoaster_2 = Animation_meta("Roller-coaster 2", False, 5.000, "6872233274891047426", "6872233274891047426", "026fe685eeb8e00dbfaf7085d7219f2e")
Split_up__down_1 = Animation_meta("Split up & down 1", False, 5.000, "6876994436950135298", "6876994436950135298", "10d434d1f8ac88a9a7f208759d2d32be")
Bisect_Domino_1 = Animation_meta("Bisect Domino 1", False, 5.000, "6887447635439915522", "6887447635439915522", "a261c2080741de332be207398ebd01a2")
Flip_5 = Animation_meta("Flip 5", False, 5.000, "6843310237902967304", "6843310237902967304", "43bf1ef1a1d937e1b44db68c8f585804")
@@ -1,144 +0,0 @@
from .effect_meta import Effect_enum
from .effect_meta import Effect_meta, Effect_param
class CapCut_Voice_filters_effect_type(Effect_enum):
"""CapCut自带的Voice filters特效类型"""
Big_House = Effect_meta("Big House", False, "7350559836590838274", "8954C5C2-A0BB-4915-8CB2-B422445DCB71", "3b1d62bbe927104e393b0fc5043dc0a6", [
Effect_param("strength", 1.000, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
"""
Low = Effect_meta("Low", False, "7021052731091587586", "4D23A0EA-5E4B-4B6A-8CE7-E3B0ADAFBCE1", "e2e27786b25e4cf9b4e74558d6f6c832", [
Effect_param("change_voice_param_pitch", 0.375, 0.000, 1.000),
Effect_param("change_voice_param_timbre", 0.250, 0.000, 1.000)])
"""参数:
- change_voice_param_pitch: 默认0.38, 0.00 ~ 1.00
- change_voice_param_timbre: 默认0.25, 0.00 ~ 1.00
"""
Energetic = Effect_meta("Energetic", False, "7320193885114733057", "FA559CAA-D9AA-443B-9D39-392B43D2DB02", "99fee98d58dd023a9f54a772dffe1ac1", [
Effect_param("Intensity", 1.000, 0.000, 1.000)])
"""参数:
- Intensity: 默认1.00, 0.00 ~ 1.00
"""
High = Effect_meta("High", False, "7021052551755731457", "E663A5D0-A024-4DED-8F0D-DA6D70A9F50C", "a83c56bd3fb17e93a1437d06498ab7ec", [
Effect_param("change_voice_param_pitch", 0.834, 0.000, 1.000),
Effect_param("change_voice_param_timbre", 0.334, 0.000, 1.000)])
"""参数:
- change_voice_param_pitch: 默认0.83, 0.00 ~ 1.00
- change_voice_param_timbre: 默认0.33, 0.00 ~ 1.00
"""
Low_Battery = Effect_meta("Low Battery", False, "7021052694370456065", "3FB0AA17-B7E8-4820-86A2-0A34E3F2F881", "a96ff559c9f1afec0603ae8bb107d98c", [
Effect_param("change_voice_param_strength", 1.000, 0.000, 1.000)])
"""参数:
- change_voice_param_strength: 默认1.00, 0.00 ~ 1.00
"""
Tremble = Effect_meta("Tremble", False, "7021052770924892674", "4AEE9A06-71E0-4188-A87E-A161DDB80F4A", "337b1ba48ea61c95ac84ba238598ca0c", [
Effect_param("change_voice_param_frequency", 0.714, 0.000, 1.000),
Effect_param("change_voice_param_width", 0.905, 0.000, 1.000)])
"""参数:
- change_voice_param_frequency: 默认0.71, 0.00 ~ 1.00
- change_voice_param_width: 默认0.91, 0.00 ~ 1.00
"""
Electronic = Effect_meta("Electronic", False, "7021052717204247042", "0285BDC4-794F-48D0-A8BD-78B248FDE822", "a6f883d8294fd5f49952cbf08544a0c5", [
Effect_param("change_voice_param_strength", 1.000, 0.000, 1.000)])
"""参数:
- change_voice_param_strength: 默认1.00, 0.00 ~ 1.00
"""
Sweet = Effect_meta("Sweet", False, "7320193577613529602", "2CD71FC4-7B4E-4E53-B337-32173184F480", "ac2110d039d35ad01ca8452a6eadc921", [
Effect_param("strength", 1.000, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
"""
Vinyl = Effect_meta("Vinyl", False, "7025484451710767618", "6D42DEB5-D9DE-479F-955C-9F63C3B88F06", "fe8fdb1bcec05647749e076a15443f08", [
Effect_param("change_voice_param_strength", 1.000, 0.000, 1.000),
Effect_param("change_voice_param_noise", 0.743, 0.000, 1.000)])
"""参数:
- change_voice_param_strength: 默认1.00, 0.00 ~ 1.00
- change_voice_param_noise: 默认0.74, 0.00 ~ 1.00
"""
Mic_Hog = Effect_meta("Mic Hog", False, "7021052785101640194", "9A48AB2D-B527-4DF0-8512-058819047877", "f2bab335416833134ab4bb780c128cd2", [
Effect_param("change_voice_param_room", 0.052, 0.000, 1.000),
Effect_param("change_voice_param_strength", 0.450, 0.000, 1.000)])
"""参数:
- change_voice_param_room: 默认0.05, 0.00 ~ 1.00
- change_voice_param_strength: 默认0.45, 0.00 ~ 1.00
"""
LoFi = Effect_meta("Lo-Fi", False, "7025484400313766402", "1C8426BF-AC3B-4F90-B145-CA712BD486D3", "44a00f0e2b85e0006f49ef345a305ec1", [
Effect_param("change_voice_param_strength", 1.000, 0.000, 1.000)])
"""参数:
- change_voice_param_strength: 默认1.00, 0.00 ~ 1.00
"""
Megaphone = Effect_meta("Megaphone", False, "7021052620592648705", "8A5CF5B8-0959-4E8A-8CC5-AD17BA176D89", "b2ca5803b90f44ee0c833f34ef684d40", [
Effect_param("change_voice_param_strength", 1.000, 0.000, 1.000)])
"""参数:
- change_voice_param_strength: 默认1.00, 0.00 ~ 1.00
"""
Echo = Effect_meta("Echo", False, "7021052523762946561", "83B7B5D7-B539-4FAA-8CF3-3318394C9278", "c37d02ae5853211ad84c13e6dca31b81", [
Effect_param("change_voice_param_quantity", 0.800, 0.000, 1.000),
Effect_param("change_voice_param_strength", 0.762, 0.000, 1.000)])
"""参数:
- change_voice_param_quantity: 默认0.80, 0.00 ~ 1.00
- change_voice_param_strength: 默认0.76, 0.00 ~ 1.00
"""
Synth = Effect_meta("Synth", False, "7021052503919694337", "450DE367-AD03-4D06-B635-C947161AAA8E", "0247a95158fda7a9e44ccd4f832a9a14", [
Effect_param("change_voice_param_strength", 1.000, 0.000, 1.000)])
"""参数:
- change_voice_param_strength: 默认1.00, 0.00 ~ 1.00
"""
Deep = Effect_meta("Deep", False, "7021052537344102913", "188C5140-E4AC-41A5-B42A-901ACAEF1B62", "583e3ccf9d2daad3860aa70ad61b64ca", [
Effect_param("change_voice_param_pitch", 0.834, 0.000, 1.000),
Effect_param("change_voice_param_timbre", 1.000, 0.000, 1.000)])
"""参数:
- change_voice_param_pitch: 默认0.83, 0.00 ~ 1.00
- change_voice_param_timbre: 默认1.00, 0.00 ~ 1.00
"""
class CapCut_Voice_characters_effect_type(Effect_enum):
"""CapCut自带的Voice characters特效类型"""
Fussy_male = Effect_meta("Fussy male", False, "7337197310696231425", "00C65F8A-44A7-4B17-8F39-93464E72823D", "", [])
Bestie = Effect_meta("Bestie", False, "7252272084292735489", "B9B3885C-BF7D-4B5C-9545-B0CD3218F292", "", [])
Queen = Effect_meta("Queen", False, "7337197136242545153", "17A7F413-C044-4F1F-9644-1337686BE406", "", [])
Squirrel = Effect_meta("Squirrel", False, "7338257533796094466", "76668599-E132-42DF-99F8-6F086B3B56E9", "b2b3f551b703c87e8e057ad8f92fafbb", [
Effect_param("strength", 1.000, 0.000, 1.000)])
"""参数:
- strength: 默认1.00, 0.00 ~ 1.00
"""
Distorted = Effect_meta("Distorted", False, "7021052602091573761", "F995614C-D100-481D-A708-59829794EF3E", "ce0bc10d76e22a718094c152f7beae25", [
Effect_param("change_voice_param_pitch", 0.650, 0.000, 1.000),
Effect_param("change_voice_param_timbre", 0.780, 0.000, 1.000)])
"""参数:
- change_voice_param_pitch: 默认0.65, 0.00 ~ 1.00
- change_voice_param_timbre: 默认0.78, 0.00 ~ 1.00
"""
Chipmunk = Effect_meta("Chipmunk", False, "7021052742021943810", "B5C8BB3C-7765-4572-B8B9-9071A903D899", "4ff3edc0229bfac112c1caefe75e7039", [
Effect_param("change_voice_param_pitch", 0.500, 0.000, 1.000),
Effect_param("change_voice_param_timbre", 0.500, 0.000, 1.000)])
"""参数:
- change_voice_param_pitch: 默认0.50, 0.00 ~ 1.00
- change_voice_param_timbre: 默认0.50, 0.00 ~ 1.00
"""
Trickster = Effect_meta("Trickster", False, "7254407946195440130", "11F394B0-E601-4DD5-BBEA-76A8CADE222A", "8dd8889045e6c065177df791ddb3dfb8", [])
Elf = Effect_meta("Elf", False, "7021052754512581122", "EF781DEC-265B-4B6D-A68E-5EDC75DDCA84", "bbf0f0d1532a249e9a1f7f3444e1e437", [
Effect_param("change_voice_param_pitch", 0.750, 0.000, 1.000),
Effect_param("change_voice_param_timbre", 0.600, 0.000, 1.000)])
"""参数:
- change_voice_param_pitch: 默认0.75, 0.00 ~ 1.00
- change_voice_param_timbre: 默认0.60, 0.00 ~ 1.00
"""
Elfy = Effect_meta("Elfy", False, "7311544785477571074", "58E4D6DE-5D7A-42C8-BE16-1AFF43666512", "8dd8889045e6c065177df791ddb3dfb8", [])
Santa = Effect_meta("Santa", False, "7311544442723242497", "8E8A0DA9-1267-41E6-AFA4-20B2A4171BA4", "8dd8889045e6c065177df791ddb3dfb8", [])
Jessie = Effect_meta("Jessie", False, "7254408415026352642", "F3EBF9DB-195D-4531-94A8-F52964DB0C83", "8dd8889045e6c065177df791ddb3dfb8", [])
Good_Guy = Effect_meta("Good Guy", False, "7259231960889823746", "27D9D7EC-BFF2-4481-92D0-40E3CBF9C2FB", "8dd8889045e6c065177df791ddb3dfb8", [])
Robot = Effect_meta("Robot", False, "7021052669863137794", "DD71C5CB-683A-4FFA-BEAA-33D568333486", "123114835bda73b8de4aa106ccde0bb2", [
Effect_param("change_voice_param_strength", 1.000, 0.000, 1.000)])
"""参数:
- change_voice_param_strength: 默认1.00, 0.00 ~ 1.00
"""
class CapCut_Speech_to_song_effect_type(Effect_enum):
"""CapCut自带的Speech to song特效类型"""
Folk = Effect_meta("Folk", False, "7413437147539164421", "9A9C3804-5241-44E9-AF56-1BE8271083F2", "", [])
File diff suppressed because it is too large Load Diff
@@ -1,24 +0,0 @@
from .effect_meta import Effect_enum
from .mask_meta import Mask_meta
class CapCut_Mask_type(Effect_enum):
"""CapCut自带的蒙版类型"""
Split = Mask_meta("Split", "line", "7374020197990011409", "B52CD1BC-63CE-4B74-B180-0B61E4AC928A", "4c6a0ef5de6a844342d40330e00c59eb", 1.0)
"""配置: centerX: 0.0, centerY: 0.0, expansion: 0.0, feather: 0.0, height: 0.0, invert: False, rotation: 0.0, roundCorner: 0.0, width: 0.16"""
Filmstrip = Mask_meta("Filmstrip", "mirror", "7374021024985125377", "C4A9A4BD-280D-4625-AA7D-F5F70E97B438", "95ac211c99063c41b86b9b63742f4a6d", 1.0)
"""配置: centerX: 0.0, centerY: 0.0, expansion: 0.0, feather: 0.0, height: 0.5, invert: False, rotation: 0.0, roundCorner: 0.0, width: 0.16"""
Circle = Mask_meta("Circle", "circle", "7374021188315517456", "E827751C-8DA7-412C-800D-DF2FE8712F77", "3ab1c47350d987c8ad415497e020a38b", 1.0)
"""配置: centerX: 0.0, centerY: 0.0, expansion: 0.0, feather: 0.0, height: 0.5, invert: False, rotation: 0.0, roundCorner: 0.0, width: 0.16"""
Rectangle = Mask_meta("Rectangle", "rectangle", "7374021450748924432", "E55A3414-9C81-4664-BB2B-42528D098F2F", "02b8999168d121538a98ea59127483ef", 1.0)
"""配置: centerX: 0.0, centerY: 0.0, expansion: 0.0, feather: 0.0, height: 0.5, invert: False, rotation: 0.0, roundCorner: 0.0, width: 0.16"""
Stars = Mask_meta("Stars", "pentagram", "7374021798087627265", "D824ED5D-D0C1-4EE2-B098-65F99CB38B95", "d3eb0298b2b1c345c123470c9194c8ad", 1.0471014493)
"""配置: centerX: 0.0, centerY: 0.0, expansion: 0.0, feather: 0.0, height: 0.5, invert: False, rotation: 0.0, roundCorner: 0.0, width: 0.16"""
Heart = Mask_meta("Heart", "heart", "7350964630979613186", "2CA4F90A-87A6-483E-B71B-FDA65EE46860", "cfa1154e4873fda2c09716c8aa546236", 1.1148148148)
"""配置: centerX: 0.0, centerY: 0.0, expansion: 0.0, feather: 0.0, height: 0.5, invert: False, rotation: 0.0, roundCorner: 0.0, width: 0.16"""
Text = Mask_meta("Text", "text", "7439320146876830225", "61E0D039-1A51-4570-B3F1-6AAC82AC1520", "ada210b1e21e860006c8324db359d8a3", 1.0)
"""配置: centerX: 0.0, centerY: 0.0, expansion: 0.0, feather: 0.0, height: 0.5, invert: False, rotation: 0.0, roundCorner: 0.0, width: 0.16"""
Brush = Mask_meta("Brush", "custom", "7374021798087627265", "31AC68F1-9EC3-4A4E-8D53-D556B7CDAC9E", "7e3c26bd14a0b68a84fee058db7f1ade", 1.0)
"""配置: centerX: 0.0, centerY: 0.0, expansion: 0.0, feather: 0.0, height: 0.5, invert: False, rotation: 0.0, roundCorner: 0.0, width: 0.16"""
Pen = Mask_meta("Pen", "contour", "7414333113955783185", "E3F45CAF-D445-4975-BE57-67AA716425D3", "9ee4e93af66335a75843446555efd8a6", 1.0)
"""配置: centerX: 0.0, centerY: 0.0, expansion: 0.0, feather: 0.0, height: 1.0, invert: False, rotation: 0.0, roundCorner: 0.0, width: 1.0"""
@@ -1,213 +0,0 @@
from .effect_meta import Effect_enum
from .animation_meta import Animation_meta
class CapCut_Text_intro(Effect_enum):
"""CapCut自带的文字入场动画, 默认时长为0.5秒"""
Throw_Out = Animation_meta("Throw Out", False, 0.500, "7233110260204966402", "7233110260204966402", "97162e8faa56cf163b8f2c1bfd5ad6e0")
Typewriter = Animation_meta("Typewriter", False, 0.500, "7210980292243231233", "7210980292243231233", "6828d67634e66ace1e76c4eb7cc2f8e6")
Concentrate = Animation_meta("Concentrate", False, 0.500, "7044433622119485954", "7044433622119485954", "49ca01f4c5f0b75d8c10e8023362cffa")
Fade_In = Animation_meta("Fade In", False, 0.500, "6724916044072227332", "6724916044072227332", "3ed092e2c06abae5644f5f12014e3020")
Glitch = Animation_meta("Glitch", False, 0.500, "7077812383946641921", "7077812383946641921", "de64c5a073e2517b8d5a07244034fc62")
Spin_In_2 = Animation_meta("Spin In 2", False, 0.500, "6775803763652301326", "6775803763652301326", "c1e619166960120b52986dd94ce15417")
Spin_In_1 = Animation_meta("Spin In 1", False, 0.500, "6763873859402732039", "6763873859402732039", "87d5263bcd792156b91109cca5fc5aae")
Zoom_Out_2 = Animation_meta("Zoom Out 2", False, 0.500, "7054480742507614722", "7054480742507614722", "d57145a34871f239c1512d7c748e3131")
Wave_in = Animation_meta("Wave in", False, 0.500, "6918927741362377218", "6918927741362377218", "28bad8ddc1ee27d91a2f48deacbba9f7")
Faulty_text = Animation_meta("Faulty text", False, 0.500, "6870325507511030274", "6870325507511030274", "c1c83996ee60af2be54d81a8f58f84ea")
Dissolve = Animation_meta("Dissolve", False, 0.500, "6873386253367120386", "6873386253367120386", "3bac40f9a5d0b2a6b569ac8e4ca3c670")
Pop_Up = Animation_meta("Pop Up", False, 0.500, "7145435451946439170", "7145435451946439170", "28d9145ead32c23742082a37e511370e")
Random_Typewriter = Animation_meta("Random Typewriter", False, 0.500, "7145435525799744002", "7145435525799744002", "49221bfc90329890d81c3612e6222a51")
Fly_In = Animation_meta("Fly In", False, 0.500, "7037028196277031425", "7037028196277031425", "33d2b2dfaf2e62325e4027463ce5bfbe")
Chroma_Type = Animation_meta("Chroma Type", False, 0.500, "7402175560819937809", "7402175560819937809", "e3283c9eb0db927fa7cdb6d138030814")
Spiral = Animation_meta("Spiral", False, 0.500, "6799873891352187406", "6799873891352187406", "9f8838b63890f4522ccce6b344fe4509")
Blur = Animation_meta("Blur", False, 0.500, "6923135604519604737", "6923135604519604737", "a5f4d3998c0648ec65c03251506bd0a0")
Type_2 = Animation_meta("Type 2", False, 0.500, "6724920636403094028", "6724920636403094028", "8bd0b8cec591907fc2a56682d8e14274")
Type_1 = Animation_meta("Type 1", False, 0.500, "6724920249654710791", "6724920249654710791", "c539514fc398e05a6cf4d7c196f78305")
Float_Down = Animation_meta("Float Down", False, 0.500, "7094880375222047233", "7094880375222047233", "b312472b5a680f49d2d1229cfe07f49d")
Zoom_In = Animation_meta("Zoom In", False, 0.500, "6724919499042066958", "6724919499042066958", "43a8026720374e330daf7b70a91ac7ce")
Open = Animation_meta("Open", False, 0.500, "6943606694240850434", "6943606694240850434", "229acba913af69794139dfd359fedb92")
Blur_to_the_Left = Animation_meta("Blur to the Left", False, 0.500, "7131932467698602497", "7131932467698602497", "ee5716b5bf9ef16fd99dd7d2d89dbefc")
Karaoke = Animation_meta("Karaoke", False, 0.500, "6771294855785091588", "6771294855785091588", "1cb64a1965c8199c61442d25989078d9")
Flicker = Animation_meta("Flicker", False, 0.500, "7040020396136993282", "7040020396136993282", "1c34ef7d819c78f05977685370e320ec")
Flip_and_jump = Animation_meta("Flip and jump", False, 0.500, "6865175746420150792", "6865175746420150792", "4d9af68136aafd135073befdbfca7e39")
Flutter = Animation_meta("Flutter", False, 0.500, "7094880213590348290", "7094880213590348290", "ab2dbbce0edfafdaad328707d6864bae")
Dissolve_Down = Animation_meta("Dissolve Down", False, 0.500, "7037028613287318018", "7037028613287318018", "766af9230fe82c84e551c1f1100aac58")
Wipe_Right = Animation_meta("Wipe Right", False, 0.500, "6771288500240126478", "6771288500240126478", "137e4f6e581377e6c98b18e3d29694a2")
Blur_Wipe_Right = Animation_meta("Blur Wipe Right", False, 0.500, "6909714649797628417", "6909714649797628417", "b11884681d795aaf41a34f28b7b8d51f")
Slingshot = Animation_meta("Slingshot", False, 0.500, "6862897343176380942", "6862897343176380942", "f4127b21d8ec8cca132953398388eec2")
Blur_to_the_right = Animation_meta("Blur to the right", False, 0.500, "7203606035557257730", "7203606035557257730", "0eff42d557a9d5c8c9974daef189b570")
Jolt_Forward = Animation_meta("Jolt Forward", False, 0.500, "7086778010807833090", "7086778010807833090", "53dadd15e28f30461bea6ab0244f1082")
Rotation_Verbatim = Animation_meta("Rotation Verbatim", False, 0.500, "7131932250437849602", "7131932250437849602", "17a78b3b5c193a3e30431946a8cbd696")
Elastic_Telescopic_II = Animation_meta("Elastic Telescopic II", False, 0.500, "7161336180561154562", "7161336180561154562", "9b0bdc149bbc541e93cddaf94b1dcaa0")
Flip_Verbatim = Animation_meta("Flip Verbatim", False, 0.500, "7131932337893282306", "7131932337893282306", "cdf2df541dea807f4bcb29ede73dd766")
Zoom_Out = Animation_meta("Zoom Out", False, 0.500, "6724921217721045515", "6724921217721045515", "0b58ad7d0d7cc93080e7bedfd0caa222")
Trail = Animation_meta("Trail", False, 0.500, "7231492571321602562", "7231492571321602562", "40884dac1fc802d207c69b05e2987d4d")
Slide_Right = Animation_meta("Slide Right", False, 0.500, "6724920136056181256", "6724920136056181256", "c49f75ef6e0f886e570f68a00f7c1312")
Clock_wipe = Animation_meta("Clock wipe", False, 0.500, "6840689010034086407", "6840689010034086407", "5df8f0147561089a7e98c2e15b31c15c")
Flipping = Animation_meta("Flipping", False, 0.500, "7221379732166676993", "7221379732166676993", "c863f3afe0d73cccc19188d6313b1dae")
Squeeze = Animation_meta("Squeeze", False, 0.500, "6779879712261935619", "6779879712261935619", "87deb51be366cd3e83fb4a04c6ea2240")
Fold = Animation_meta("Fold", False, 0.500, "7131933414189437441", "7131933414189437441", "9f65c45595fa8c0002f7f49a61637ff2")
Roll_In = Animation_meta("Roll In", False, 0.500, "7037027812351414786", "7037027812351414786", "c877f5d0bb23720b302244e7e9b9f0bc")
Judder_Up = Animation_meta("Judder Up", False, 0.500, "7086778112611979777", "7086778112611979777", "b3ea1be4937b7cd032f1775d98b1f06e")
Type_3 = Animation_meta("Type 3", False, 0.500, "6724920521462387207", "6724920521462387207", "5916ce3ef5af2ecc787b16353dd32074")
Bounce_In = Animation_meta("Bounce In", False, 0.500, "6887766069587481090", "6887766069587481090", "83cd5b21c6a1cea2d11aac09bf328d1b")
Slide_Up = Animation_meta("Slide Up", False, 0.500, "6763470111253729803", "6763470111253729803", "7369b47c2bd5267948b0422f69f686c0")
Blow_In = Animation_meta("Blow In", False, 0.500, "6873386357952090626", "6873386357952090626", "39fb9e67642a084fc3a22944d28bbbba")
Wobble = Animation_meta("Wobble", False, 0.500, "7095603439912096258", "7095603439912096258", "d9099a94194f6a60366a2115ecca7646")
Bounce_from_TR = Animation_meta("Bounce from TR", False, 0.500, "7080126619364364801", "7080126619364364801", "ccff88fa7a5e6a545e8ff343593ae255")
Showing_Right = Animation_meta("Showing Right", False, 0.500, "7149113362096329217", "7149113362096329217", "6f8e0a5cd98c44b79f9ec09b0b913059")
Showing_Up = Animation_meta("Showing Up", False, 0.500, "7149113228788765186", "7149113228788765186", "8c4b711fc99437b6b4aebf575ca3e552")
Mini_Zoom = Animation_meta("Mini Zoom", False, 0.500, "6763469998330483213", "6763469998330483213", "6f5ec0bb82bfd24a72706e2006c0e806")
Set_to_the_Right = Animation_meta("Set to the Right", False, 0.500, "7145435431297880577", "7145435431297880577", "5a78f1024ecdc9a6b69220eac58a0963")
Slide_Left = Animation_meta("Slide Left", False, 0.500, "7403255792146584081", "7403255792146584081", "6623efc403e59006d52ef89ca8cab5fe")
Bounce_In_TL = Animation_meta("Bounce In TL", False, 0.500, "7080126868136923650", "7080126868136923650", "7cfe7399370f640c938a4226b688e0a3")
Wipe_Up = Animation_meta("Wipe Up", False, 0.500, "6774625910067827212", "6774625910067827212", "b18e5a9811cc39acd1342b404f67235b")
Random_Bounce = Animation_meta("Random Bounce", False, 0.500, "7046650374005985793", "7046650374005985793", "08211765b28b4f74406367e8998ef907")
Blur_Wipe_Left = Animation_meta("Blur Wipe Left", False, 0.500, "6909714445518246401", "6909714445518246401", "c6b81d117c36f8028015e1ba72afeabd")
Sunrise = Animation_meta("Sunrise", False, 0.500, "6779084126457696776", "6779084126457696776", "5135096b047fe38ea94febe82b97ffde")
Wipe_Down = Animation_meta("Wipe Down", False, 0.500, "6774626192990409224", "6774626192990409224", "da43ba0acb3e0f247373c40e51ec0952")
Wipe_In_LR = Animation_meta("Wipe In LR", False, 0.500, "7095603601355051521", "7095603601355051521", "f83eb09e4eebd66587abf023688739a5")
Wipe_Left = Animation_meta("Wipe Left", False, 0.500, "6774626830038077960", "6774626830038077960", "c3b5c38587edc82914b1bbb9c8b1b070")
Slide_Left_1 = Animation_meta("Slide Left", False, 0.500, "6763470195894784525", "6763470195894784525", "7715ee0fb10ee4db78e3e84ca6076c1d")
Slide_Down = Animation_meta("Slide Down", False, 0.500, "7403256520537805329", "7403256520537805329", "cf042bc2dd475dc6166e33f43b116641")
Slide_Up_1 = Animation_meta("Slide Up", False, 0.500, "7275682326678344193", "7275682326678344193", "9ab223e5e9a0b9611b04062048173de9")
Showing_Left = Animation_meta("Showing Left", False, 0.500, "7149113444279521793", "7149113444279521793", "b4119cf3405c71bc556e1c5562e22d01")
Slide_Down_1 = Animation_meta("Slide Down", False, 0.500, "6724921985282871816", "6724921985282871816", "4ef6c5a0fc93b203e40cb38c8bbdd7bb")
Boing = Animation_meta("Boing", False, 0.500, "6873386210002211330", "6873386210002211330", "cbc371fed78af934a95433cef2923b96")
Spring = Animation_meta("Spring", False, 0.500, "6887766363436225025", "6887766363436225025", "feb1261746ba3792d367c214383fdaf0")
Ease_In_Right = Animation_meta("Ease In Right", False, 0.500, "7054065145990877698", "7054065145990877698", "09369ebe9ac7df7d95981647795b726d")
Turn_Horizontal = Animation_meta("Turn Horizontal", False, 0.500, "7063344665025581570", "7063344665025581570", "e7b57129e1b9b24b14e5c6257e03ad94")
Grow = Animation_meta("Grow", False, 0.500, "6873386301182185986", "6873386301182185986", "6a574fce0c4041c452997d059ebe018c")
Showing_Down = Animation_meta("Showing Down", False, 0.500, "7149113292747706881", "7149113292747706881", "a7b05a11c6bdc7010cc4dc7f1d276407")
Flip_up = Animation_meta("Flip up", False, 0.500, "7195849719673786882", "7195849719673786882", "0cf2050093a2bbe736ab4b2ee9002dcf")
class CapCut_Text_outro(Effect_enum):
"""CapCut自带的文字出场动画, 默认时长为0.5秒"""
Fade_Out = Animation_meta("Fade Out", False, 0.500, "6724919382104871427", "6724919382104871427", "6ecc8fa1d956c3e14c84cdc0679982a9")
Blur = Animation_meta("Blur", False, 0.500, "6923134492760609282", "6923134492760609282", "a455f364ad8079365e4d9c880ee58902")
Zoom_In = Animation_meta("Zoom In", False, 0.500, "6724919767200698884", "6724919767200698884", "31f07f6c0980eef948904395c7ba4bd4")
Typewriter = Animation_meta("Typewriter", False, 0.500, "7210980400984756738", "7210980400984756738", "3f2d4916f48390652f4abaff69742c0b")
Zoom_In_2 = Animation_meta("Zoom In 2", False, 0.500, "7054480833201050114", "7054480833201050114", "826379869afa4037da8bbcafc1e8a6c7")
Dissolve_Up = Animation_meta("Dissolve Up", False, 0.500, "7037028782544261634", "7037028782544261634", "11ea5c712b93ca8d0df41c2378073d29")
Slide_Down = Animation_meta("Slide Down", False, 0.500, "7403256664498901520", "7403256664498901520", "30080fd3aae7a739d431c59387afdd4f")
Dissolve = Animation_meta("Dissolve", False, 0.500, "6873386286082691586", "6873386286082691586", "46389f9f5f72e1b58020a0b8293a23b9")
Slide_Up = Animation_meta("Slide Up", False, 0.500, "6763873533115240968", "6763873533115240968", "bbec5aa1ddf8df26276b99cfd9996d76")
Flicker = Animation_meta("Flicker", False, 0.500, "7040020559656129025", "7040020559656129025", "91be98f44180d877cbcb2b515315eb01")
Blur_to_the_Left = Animation_meta("Blur to the Left", False, 0.500, "7131932497641738753", "7131932497641738753", "02ee1da62468714f7b17a671ee61acf0")
Zoom_Out = Animation_meta("Zoom Out", False, 0.500, "7428455252141100293", "7428455252141100293", "4caa7ab406013ea4c9febad3ab95cabf")
Slide_Down_1 = Animation_meta("Slide Down", False, 0.500, "6724919284893487619", "6724919284893487619", "4b1190ca81551d872f1d6b0e2ce5db2b")
Mini_Zoom = Animation_meta("Mini Zoom", False, 0.500, "6763469915518145032", "6763469915518145032", "1e293df954586a261a11576481dd8454")
Bounce_Out = Animation_meta("Bounce Out", False, 0.500, "6887765964515971585", "6887765964515971585", "465f833066158d62db9e54df6cd77354")
Wipe_Left = Animation_meta("Wipe Left", False, 0.500, "6774626748177846791", "6774626748177846791", "1160d9bcc8a158a65441bcfc9603bd00")
Expand = Animation_meta("Expand", False, 0.500, "6779879836916650509", "6779879836916650509", "9691c2574e653e0263365df7446a8af9")
Throw_Back = Animation_meta("Throw Back", False, 0.500, "7233110388701663745", "7233110388701663745", "0203e194e3bcf10f7f96fde73dc350f3")
Slide_Left = Animation_meta("Slide Left", False, 0.500, "6763873602476446221", "6763873602476446221", "a193ecedf73b2b27616ee7da4f599b9b")
Slide_Up_1 = Animation_meta("Slide Up", False, 0.500, "7403256763803243024", "7403256763803243024", "126062701f0797dedd8019fdf82969d5")
Type_1 = Animation_meta("Type 1", False, 0.500, "6763469696260903435", "6763469696260903435", "628234381485fb1dd576eeb48c85a091")
Dilute = Animation_meta("Dilute", False, 0.500, "7044433705141539329", "7044433705141539329", "fe2cfbc08c330517caa8b602187ced07")
Type_2 = Animation_meta("Type 2", False, 0.500, "6763469767555682823", "6763469767555682823", "83076ce7cda24efdaca9731b112fb097")
Horizontal_Close = Animation_meta("Horizontal Close", False, 0.500, "6943606672514355714", "6943606672514355714", "e7048d848c90a6e15fbc9349dad6f95c")
Slide_Right = Animation_meta("Slide Right", False, 0.500, "6724920744431587853", "6724920744431587853", "4026a211f18b0fc6ab9e10d09c8922ba")
Disband_to_the_Left = Animation_meta("Disband to the Left", False, 0.500, "7145435368777585153", "7145435368777585153", "46b117e1d9fc552e574958fcde072a53")
Random_Typewriter = Animation_meta("Random Typewriter", False, 0.500, "7145435491129627137", "7145435491129627137", "e667d209a1c3ab8dfdfb00f2f014ec9d")
Flutter = Animation_meta("Flutter", False, 0.500, "7094881109661454849", "7094881109661454849", "2e58579b330dbccc4491c5f0a8cf4a8a")
Fold = Animation_meta("Fold", False, 0.500, "7131933395650613762", "7131933395650613762", "ccce629bcf7f98a8de4d4e1a2228d11a")
Trail = Animation_meta("Trail", False, 0.500, "7231863704063578626", "7231863704063578626", "20d1992e9f7b67bedf1811c0811b1e5c")
Chromatic_Aberration_Tailing = Animation_meta("Chromatic Aberration Tailing", False, 0.500, "7161314207609131522", "7161314207609131522", "998e6b4aee4a58c7810ae427f4ef2a6e")
Roll_Out = Animation_meta("Roll Out", False, 0.500, "7037027990873575938", "7037027990873575938", "f25af0cdef9584d588584b3765350f64")
Pop_Down = Animation_meta("Pop Down", False, 0.500, "7145435533580177921", "7145435533580177921", "751b7e005e3ec297f5d3d2c40664f585")
Slingshot = Animation_meta("Slingshot", False, 0.500, "6862897350478664200", "6862897350478664200", "45f66e1fa1a3b79968b3749275bab10c")
Faulty_text = Animation_meta("Faulty text", False, 0.500, "6870325383217025538", "6870325383217025538", "71a23656184bc8438f4fa22425192185")
Sunset = Animation_meta("Sunset", False, 0.500, "6779084194392838670", "6779084194392838670", "662eea25ba7d450d9a91febf43f22f7f")
Ink_Print = Animation_meta("Ink Print", False, 0.500, "7131933235000381953", "7131933235000381953", "ffde7ad26438a2a7e38c55cbfc2a06e6")
Wipe_Right = Animation_meta("Wipe Right", False, 0.500, "6783908820176343566", "6783908820176343566", "a48325fce55a7a419b351c8a9826c7a0")
Bounce_Out_TR = Animation_meta("Bounce Out TR", False, 0.500, "7080126748129497601", "7080126748129497601", "c686d80fd584cd755a3a9a8168b90c91")
Glitch = Animation_meta("Glitch", False, 0.500, "7077812264559972865", "7077812264559972865", "ef29a8a0678cfc09c6888cf3cd0cd1fe")
Stroke_Fill = Animation_meta("Stroke Fill", False, 0.500, "7239696026389451266", "7239696026389451266", "88e26415caea51e4cd4453f113e4ce82")
Wipe_Down = Animation_meta("Wipe Down", False, 0.500, "6774626081791021576", "6774626081791021576", "4dafd6a7cbde862044fcbc543ecd818a")
Flip_Down = Animation_meta("Flip Down", False, 0.500, "7198418239955669506", "7198418239955669506", "fb59d5300e87e87718c3fd2f956df6f1")
Blur_Erase_Right = Animation_meta("Blur Erase Right", False, 0.500, "6909715076459008514", "6909715076459008514", "b55ab5e5eb7c4b540f3065e25c5b2862")
Turn_Horizontal = Animation_meta("Turn Horizontal", False, 0.500, "7063344803768963585", "7063344803768963585", "d7e4694ce021064f57fb9d56ea9ca955")
Flipping = Animation_meta("Flipping", False, 0.500, "7221823093847626241", "7221823093847626241", "07d60e408004cba91944a6fbe3ec570d")
Grow = Animation_meta("Grow", False, 0.500, "6873386318026510850", "6873386318026510850", "e6ae4e1fc5ade7bd8765ef6d918f5f6f")
Ease_Out_Right = Animation_meta("Ease Out Right", False, 0.500, "7054065225024147969", "7054065225024147969", "4efcd0a37ec562695391e6e24ff805aa")
Spring = Animation_meta("Spring", False, 0.500, "6887766592759796225", "6887766592759796225", "0bed65b365b11c525396282d2d6070c0")
Blur_Erase_Left = Animation_meta("Blur Erase Left", False, 0.500, "6909714891058188801", "6909714891058188801", "e491ca3b41a5dba9af4db1ca6b72500f")
Wipe_Up = Animation_meta("Wipe Up", False, 0.500, "6774625752794010115", "6774625752794010115", "d9b04e37f86d6b5cf456f396648e11d4")
Bounce_Out_TL = Animation_meta("Bounce Out TL", False, 0.500, "7080126963121132033", "7080126963121132033", "2901b7202d9ac40d48bd5f242ad2edac")
Vrille = Animation_meta("Vrille", False, 0.500, "6799874105710481927", "6799874105710481927", "e6e1a2239d894b408e41341a6ca578ca")
Blow_Away = Animation_meta("Blow Away", False, 0.500, "6873386371508081154", "6873386371508081154", "d1292de2cfc57d0ca12fdbafb4e0bca2")
Type_3 = Animation_meta("Type 3", False, 0.500, "6763469838368117256", "6763469838368117256", "3f77a87e46ee1b50cd0ac207809c4c24")
Rotation_Verbatim = Animation_meta("Rotation Verbatim", False, 0.500, "7131932325171958273", "7131932325171958273", "ee29d8b9e06a471972f36734c53dbea8")
Fly_Out = Animation_meta("Fly Out", False, 0.500, "7037028379068994050", "7037028379068994050", "324c695abdd43e1ec3506364fce0a087")
Float_Up = Animation_meta("Float Up", False, 0.500, "7094881236941804033", "7094881236941804033", "3513093fd914fcccfa87cb98a410062e")
Spin_Out_1 = Animation_meta("Spin Out 1", False, 0.500, "6763873732143354376", "6763873732143354376", "ffc35db86b29aee7a0a4342ea5ed059f")
Spin_Out_2 = Animation_meta("Spin Out 2", False, 0.500, "6775804032318444045", "6775804032318444045", "dc208cb851dff052cac198a5989f27b2")
Slide_Down_2 = Animation_meta("Slide Down", False, 0.500, "7275978484902531585", "7275978484902531585", "fa4aaf84b182425eed4e330ac03ecdbd")
Flip_Verbatim = Animation_meta("Flip Verbatim", False, 0.500, "7131932349456978433", "7131932349456978433", "ffc81a4b0c44427fbfd60984f7ddcdc2")
Boing = Animation_meta("Boing", False, 0.500, "6873386227546984961", "6873386227546984961", "f2882bcfc0abc3b0c53b39649a2c4224")
Random_Bounce = Animation_meta("Random Bounce", False, 0.500, "7047418513429893633", "7047418513429893633", "c260caa85b16e7d471ddeb2015cdf3f3")
Wave_out = Animation_meta("Wave out", False, 0.500, "6918927254676312578", "6918927254676312578", "66ea8431aa7bc02f3b4d3219a127b313")
Elastic_Telescopic_II = Animation_meta("Elastic Telescopic II", False, 0.500, "7163958556784333313", "7163958556784333313", "9b225f4fafa2341876eec98ba91c89ee")
Clock_wipe = Animation_meta("Clock wipe", False, 0.500, "6840698265277567496", "6840698265277567496", "e2faf1635350ccf31739618a257d87ad")
Jump_and_flip = Animation_meta("Jump and flip", False, 0.500, "6865176065514410503", "6865176065514410503", "f578720479df7746fa067199a1e4ea8b")
class CapCut_Text_loop_anim(Effect_enum):
"""CapCut自带的文字循环动画, 默认时长为0.5秒"""
Flare = Animation_meta("Flare", False, 0.500, "7128311749186425346", "7128311749186425346", "494af236e19eefc9895a4cc2b8d20736")
Wobble_2 = Animation_meta("Wobble 2", False, 0.500, "7054065409686770178", "7054065409686770178", "8d180f0ad5ff173a44f9142baeee536c")
Wave = Animation_meta("Wave", False, 0.500, "6724927688047333891", "6724927688047333891", "c2d44ce51bddfa48d479f2d2d37b5a7f")
Color_Glitch = Animation_meta("Color Glitch", False, 0.500, "6835878163575214605", "6835878163575214605", "e0295a9f4f19fe21692c405f7c00d1e5")
Enlarge_Letters = Animation_meta("Enlarge Letters", False, 0.500, "6909707735827223042", "6909707735827223042", "ccd09fe5c4969b5f195099a8ec2ff418")
Converge = Animation_meta("Converge", False, 0.500, "7402173132787683841", "7402173132787683841", "ee68176782c8b62a207c04f4a979957a")
Scroll_Up = Animation_meta("Scroll Up", False, 0.500, "6790246884683289102", "6790246884683289102", "9aa4e0d045c61892c2b2e3fdfaf1b093")
Flash = Animation_meta("Flash", False, 0.500, "6724921437930394120", "6724921437930394120", "6fe3f0fcd14e11e70b7510f42444b86c")
Jiggly = Animation_meta("Jiggly", False, 0.500, "6918928011601383937", "6918928011601383937", "b0a3224256abcedf4507f2e93e8dfc1e")
Gushing = Animation_meta("Gushing", False, 0.500, "7145435416810754562", "7145435416810754562", "76cc53a7bb20385d208c858a13cf06fd")
Wobbly_Projector_1 = Animation_meta("Wobbly Projector 1", False, 0.500, "7075252119409791490", "7075252119409791490", "4930ab2d5f8f174782d352e36f4d6602")
Wave_3 = Animation_meta("Wave 3", False, 0.500, "7080126475633955329", "7080126475633955329", "47c2db2f5ad8ba96cfb5f1279c019464")
Ink_Print = Animation_meta("Ink Print", False, 0.500, "7131932098310443521", "7131932098310443521", "fbd35399a1880d2637731d20eb619d29")
Donut = Animation_meta("Donut", False, 0.500, "7075252014443139585", "7075252014443139585", "73803bb6fddd47749d1ac09334be8bfc")
Shout_Out = Animation_meta("Shout Out", False, 0.500, "7145435518468100610", "7145435518468100610", "fe67ad0c257c8c9057971f1a0b3e429d")
Pulse = Animation_meta("Pulse", False, 0.500, "6724919955654971918", "6724919955654971918", "1b9a454256f041c19f723ba27358740b")
Tremble = Animation_meta("Tremble", False, 0.500, "6790246693674684942", "6790246693674684942", "383dabd75d7fe7985d990ebb34d63732")
Super_Wavy_2 = Animation_meta("Super Wavy 2", False, 0.500, "7070118615852257793", "7070118615852257793", "bdd007527d0eda9d64bfbf6aef103e97")
Font_Reel = Animation_meta("Font Reel", False, 0.500, "7402179921738469905", "7402179921738469905", "06c685c00a9c1a7a484c7841ac45742a")
VHS = Animation_meta("VHS", False, 0.500, "7402174665675772417", "7402174665675772417", "f82d0f25b2cc4f0696dce7d97c7b02be")
Space_Type = Animation_meta("Space Type", False, 0.500, "7402174374549131777", "7402174374549131777", "bb717e125d34532ec904d1bc01ec25da")
Wobble_3 = Animation_meta("Wobble 3", False, 0.500, "7077492231011045889", "7077492231011045889", "4aff94a92515e98e1abb3328c254d1bf")
Top_Arch = Animation_meta("Top Arch", False, 0.500, "7086778564552430081", "7086778564552430081", "9fb14748e774977b21030e730b4d8343")
Rotate = Animation_meta("Rotate", False, 0.500, "7063296016895709697", "7063296016895709697", "e81fcebf0885fa5d698f6ca7d027a556")
Random_Bounce = Animation_meta("Random Bounce", False, 0.500, "7047418055487394306", "7047418055487394306", "47bc0418ebda9df7a65094758aed8b3b")
Jump = Animation_meta("Jump", False, 0.500, "6724920002958332420", "6724920002958332420", "784250e657b472a46a3b3ce0a838e4f7")
Shake = Animation_meta("Shake", False, 0.500, "7161320851327947265", "7161320851327947265", "ea2f688a517d18a9de5912fa09f3bd56")
Wave_2 = Animation_meta("Wave 2", False, 0.500, "7070118516619219457", "7070118516619219457", "62245c9799544b75258689eb1ff222bb")
Scrolling = Animation_meta("Scrolling", False, 0.500, "7218822076507886082", "7218822076507886082", "1ca0b292402789b45b6b3aaf2e2d9ea0")
Strong_Tremble_1 = Animation_meta("Strong Tremble 1", False, 0.500, "7075252522998305281", "7075252522998305281", "0af5d6c9651c04f38e33cbe6710205dd")
Jiggle = Animation_meta("Jiggle", False, 0.500, "6887766216576864770", "6887766216576864770", "29ddfc38309d3914e53d5ea99f3ca33a")
Rotate_1 = Animation_meta("Rotate", False, 0.500, "6763900973946507784", "6763900973946507784", "151421d4de4d49e65b050cb413482cd5")
Dance = Animation_meta("Dance", False, 0.500, "6840710593289130503", "6840710593289130503", "61f24344eb8bf86582d6140ad985ef14")
Super_Wavy = Animation_meta("Super Wavy", False, 0.500, "6857036499389518349", "6857036499389518349", "87f7332abda9ac46d5dc81f69c48daab")
Emotional_Loading = Animation_meta("Emotional Loading", False, 0.500, "7145435536323252737", "7145435536323252737", "bd57e018dc5d1ed418826460407499c4")
Retro_BW = Animation_meta("Retro B&W", False, 0.500, "7402175225015570945", "7402175225015570945", "4bc57fba68e0cce14e2ea8ab652dabc2")
Wobble = Animation_meta("Wobble", False, 0.500, "6764189482871689742", "6764189482871689742", "82a2b88dc69ce9f9a36f975968649d5b")
Pixel_Bounce = Animation_meta("Pixel Bounce", False, 0.500, "7128308949710803458", "7128308949710803458", "e989174c257abde2caa0a923f6181b37")
Swing = Animation_meta("Swing", False, 0.500, "6724921579517514248", "6724921579517514248", "320b71150105629f7ab1b318716181eb")
Fold = Animation_meta("Fold", False, 0.500, "7067799306392048129", "7067799306392048129", "c9b3ef10e455a3916dbef47a7f711eaa")
Trailing_Beating = Animation_meta("Trailing Beating", False, 0.500, "7160943125341409793", "7160943125341409793", "3275b0c50bf50725148ffa4e6f168031")
Pressing = Animation_meta("Pressing", False, 0.500, "7145435411911807489", "7145435411911807489", "4f01b8c42b2d4a26a89aa528e6cc1544")
Page_Turning_I = Animation_meta("Page Turning I", False, 0.500, "7179117105252405762", "7179117105252405762", "8e4559d96b415b5c1ec0748b8a138f4e")
Bullet_Screen = Animation_meta("Bullet Screen", False, 0.500, "7131931877975265794", "7131931877975265794", "0e40f8536ac38d14811e8eb5b1a7c792")
Wiper = Animation_meta("Wiper", False, 0.500, "6799874389669057037", "6799874389669057037", "6a4c40e24db5027cb42892d8ade9df38")
Shake_1 = Animation_meta("Shake 1", False, 0.500, "6724920869363126795", "6724920869363126795", "8af4da60a802e3ca6c9fe2184fbe22d0")
Blocks = Animation_meta("Blocks", False, 0.500, "7402172635615859217", "7402172635615859217", "05c3c10997b885c71ed0dd64aff14dd2")
Scream = Animation_meta("Scream", False, 0.500, "7145435416013836801", "7145435416013836801", "04933b5e575c54cbf09c57c5e933f0ec")
Strong_Tremble_2 = Animation_meta("Strong Tremble 2", False, 0.500, "7075252650312208897", "7075252650312208897", "7092c0f011294519b95e7890deab7bc4")
Flip = Animation_meta("Flip", False, 0.500, "6763897586328801805", "6763897586328801805", "e4983ce92d02628087780832ef631c7d")
Wobbly_Projector_2 = Animation_meta("Wobbly Projector 2", False, 0.500, "7075252258757153281", "7075252258757153281", "9df9af3c2c79411a4018ec0cb4f027d9")
Wobbly_Projector_3 = Animation_meta("Wobbly Projector 3", False, 0.500, "7075252420023947777", "7075252420023947777", "8a8221e8a954c2b9b453b8fc89cd7707")
Jump_Pieces = Animation_meta("Jump Pieces", False, 0.500, "7402172473166270992", "7402172473166270992", "922ca4e87c7eed7e60d062c18e928bc6")
@@ -1,238 +0,0 @@
from .effect_meta import Effect_enum
from .transition_meta import Transition_meta
class CapCut_Transition_type(Effect_enum):
"""CapCut自带的转场效果类型"""
Montage_Snippets = Transition_meta("Montage Snippets", False, "7481553072678784311", "460B9343-B792-4c38-B6F5-6886C031B8D2", "c0cbbcfab2b63efeac02dedc1929da3e", 2.000000, True)
"""默认时长: 2.00s"""
Mix = Transition_meta("Mix", False, "6724845717472416269", "CE454E9E-9C57-43c5-9E80-B46A6A495D10", "7b53f4c008c4c684fccf8c7d4d46cc92", 1.000000, True)
"""默认时长: 1.00s"""
Mix_1 = Transition_meta("Mix", False, "6943605272933831169", "2C1C4FD5-A421-43a1-8A0B-3A7AF421761F", "6f18fb242b64f9641da79aa773a33687", 0.466666, True)
"""默认时长: 0.47s"""
Mix_2 = Transition_meta("Mix", False, "6943605272933831169", "3C343329-8D98-4429-A849-52F6567233DF", "6f18fb242b64f9641da79aa773a33687", 0.466666, True)
"""默认时长: 0.47s"""
Black_Fade = Transition_meta("Black Fade", False, "6724239388189921806", "7CBE3442-7B48-4a73-9391-C74FB7580D30", "3bca53e9f3dfa2c184fbee96438ea097", 0.466666, False)
"""默认时长: 0.47s"""
Then_and_Now = Transition_meta("Then and Now", False, "7012818976015127041", "8811269D-67E1-4783-9E1C-14F27DE06021", "ce3cfe333baf3493f6a3714c08eaae12", 0.466666, False)
"""默认时长: 0.47s"""
White_Flash = Transition_meta("White Flash", False, "6724845376098013708", "B5F63066-4B98-4c8a-B4AD-1398E1D313F2", "b033ea56618d5b0f098071fb326bb02a", 0.466666, False)
"""默认时长: 0.47s"""
Dissolve = Transition_meta("Dissolve", False, "6724846004274729480", "392FD26E-A514-4d0f-8950-EA4A20CB407C", "986161b2af25f7aa752278aa8b39c7b7", 0.466666, False)
"""默认时长: 0.47s"""
Dissolve_1 = Transition_meta("Dissolve", False, "6724846004274729480", "5B2D1EF0-E00B-43b5-8762-E85B5CC851A2", "986161b2af25f7aa752278aa8b39c7b7", 0.466666, False)
"""默认时长: 0.47s"""
Gradient_Wipe = Transition_meta("Gradient Wipe", False, "6923134021744464386", "DDA0714D-730D-499d-AED1-05BA6455ED35", "2fff9b60c929559bce574ab8ef2c14a7", 0.466666, False)
"""默认时长: 0.47s"""
Dissolve_II = Transition_meta("Dissolve II", False, "6724866927933526542", "85592C7A-A74A-49fe-9ECD-8BD4707346D2", "8179e342f9b24dd1817c56f7ef1f8f9b", 0.466666, False)
"""默认时长: 0.47s"""
Dissolve_III = Transition_meta("Dissolve III", False, "6724867032312975875", "A020BA55-B7F4-4502-9BD4-AD0771812BD5", "293a03bd140d09b0c616f879bda235e1", 0.466666, False)
"""默认时长: 0.47s"""
Black_smoke = Transition_meta("Black smoke", False, "6886275127743353346", "90218FDB-E10B-4bb5-86B8-3E35CB4F14C1", "fa02f80c28a9671a206c2ccf17b41c58", 0.466666, False)
"""默认时长: 0.47s"""
White_smoke = Transition_meta("White smoke", False, "6886274983962612226", "ED48A507-B76C-409f-AF58-A0F6A79B1305", "9b679b32ec03c42932fa37b10c141bda", 0.466666, False)
"""默认时长: 0.47s"""
BW_Flash = Transition_meta("B&W Flash", False, "7481552579042774278", "18AE2008-538B-40ca-8B3D-17B651213554", "ca293bf055b3ff4fdd6d8ff720d47322", 2.000000, True)
"""默认时长: 2.00s"""
Rainbow_Warp = Transition_meta("Rainbow Warp", False, "7480764852131155206", "B69CCBDA-E788-41b7-9889-7085C31B5588", "c19609823e3c48b75c95969131e48e45", 1.000000, True)
"""默认时长: 1.00s"""
RGB_Glitch = Transition_meta("RGB Glitch", False, "7480389949041200390", "7C44F868-52C9-4b15-9F96-E7316A9A3DE9", "4ab3aeca2bc4a82817cf9e978849496d", 1.000000, True)
"""默认时长: 1.00s"""
Rainbow_Filter = Transition_meta("Rainbow Filter", False, "7480387198152379653", "44E6A5E7-DA3D-4e95-BF5C-EB2078B68F03", "5c5e0e3c721a279c64ba196cf3f944a6", 1.000000, True)
"""默认时长: 1.00s"""
Urban_Glitch = Transition_meta("Urban Glitch", False, "7480387121325395255", "CC8C88B9-DA60-46e1-AEFF-5907CE1FA557", "48bc6b9d80ab44ada1be807611a0ed23", 1.000000, True)
"""默认时长: 1.00s"""
Camera_Glow = Transition_meta("Camera Glow", False, "7480386884728917254", "EDA25C90-4EC3-43b5-B35A-02C253AACAB5", "56e4dca1f4540d77784eaf42a3fe6ea5", 1.000000, True)
"""默认时长: 1.00s"""
White_Flash_1 = Transition_meta("White Flash", False, "7345079500327096833", "91A17180-5C82-4807-9E1F-0F08CB68B16B", "c1f7073a94d22565ace1ab3023d1c154", 0.400000, True)
"""默认时长: 0.40s"""
Light_Sweep_II = Transition_meta("Light Sweep II", False, "7224393850444321282", "6A6EEB83-F8ED-4c18-8628-22F9276DF3DD", "1941195d514a2078634b4132f1127f7d", 0.800000, True)
"""默认时长: 0.80s"""
Flash = Transition_meta("Flash", False, "6987208055511323137", "15F94905-7A39-4789-8285-92188260756B", "009f3e9678994c70c3b45e8a5ea4b999", 0.466666, False)
"""默认时长: 0.47s"""
Light_Beam = Transition_meta("Light Beam", False, "6983988935890309634", "6C2B6DA1-DDD0-4a27-9D87-15857C68B656", "84525ee78728b5cce44c8404d9f50b0d", 0.466666, False)
"""默认时长: 0.47s"""
Burn = Transition_meta("Burn", False, "7091576396731912705", "5F342C77-D6E5-4f9c-8B28-3236EA47CE38", "da10f2f4ae0aa70ad4d61b2c750aef6b", 0.466666, False)
"""默认时长: 0.47s"""
Blanch = Transition_meta("Blanch", False, "6952697453275517442", "3402A62F-694A-4844-97A1-01A1EBE672E6", "9fae2e7e4e9b0c3b0da92e35accbd280", 0.466666, False)
"""默认时长: 0.47s"""
Fold_Over = Transition_meta("Fold Over", False, "7397628078492488209", "B3084812-C914-4873-8E1F-C9C4AFFEE9F4", "091f7995a43fc66fd0a95b2a6b88834f", 1.000000, True)
"""默认时长: 1.00s"""
Bottom_Left_II = Transition_meta("Bottom Left II", False, "7291513615989871105", "ED60780D-C6B9-4619-AFA3-4F1475D6D83A", "e0296196f0ec6666a33b33fead4f63d6", 0.666666, True)
"""默认时长: 0.67s"""
Vertical_Blur_II = Transition_meta("Vertical Blur II", False, "7291574063514784257", "27D567C6-A093-463a-A72F-1CDDAB2E2209", "85e381982a94778e003f3acc9527d5cf", 0.600000, True)
"""默认时长: 0.60s"""
Fold_Over_1 = Transition_meta("Fold Over", False, "7397628078492488209", "028BE63C-E232-49b9-AC89-7D52AD42B4D7", "091f7995a43fc66fd0a95b2a6b88834f", 1.000000, True)
"""默认时长: 1.00s"""
Bottom_Left_II_1 = Transition_meta("Bottom Left II", False, "7291513615989871105", "9CD97556-1602-497c-A22B-38F21A66853A", "e0296196f0ec6666a33b33fead4f63d6", 0.666666, True)
"""默认时长: 0.67s"""
Inhale = Transition_meta("Inhale", False, "7259950322024452610", "A319AE0A-56B0-418b-AF76-454BF6F87A13", "476af19d13e50283042b2f2c3d59f651", 0.600000, True)
"""默认时长: 0.60s"""
Shake_3 = Transition_meta("Shake 3", False, "7252670515926536705", "33EED074-6860-488a-9C94-D5B8F07C1CA6", "c1447e068949ba2fb1d8c6738656c2e9", 0.800000, True)
"""默认时长: 0.80s"""
Rotate_CW_II = Transition_meta("Rotate CW II", False, "7252989706198061569", "7FDC0CB7-1EF6-4625-95E0-115626185F87", "daafcc4b40351ba97bc8c4a2ba33408d", 0.800000, True)
"""默认时长: 0.80s"""
Rotate_CCW_II = Transition_meta("Rotate CCW II", False, "7252989957319430658", "B64D4180-9B0E-4b25-8602-4397D00557D6", "248ab60641bf5ff2760a16c7f0df15d6", 0.800000, True)
"""默认时长: 0.80s"""
Pull_in = Transition_meta("Pull in", False, "6724226861666144779", "E27206B3-FFA0-4ea4-B6E7-44350CED4574", "4d5a316f2eae582e7d0604b47feb8c32", 0.466666, False)
"""默认时长: 0.47s"""
Pull_Out = Transition_meta("Pull Out", False, "6724226338418332167", "39411271-04D8-40f1-9DF9-1E0A7DA5CF64", "8d97f1c1a60d9393c97ff4e9da0669ae", 0.466666, False)
"""默认时长: 0.47s"""
CW_Swirl = Transition_meta("CW Swirl", False, "6941282502480761346", "E5BF0039-EC93-4529-8D4C-6922E16246B4", "191c91dacfa44e337ac1a02f72514735", 0.466666, False)
"""默认时长: 0.47s"""
Right = Transition_meta("Right", False, "6724227599616184836", "C3D52822-B616-4e73-9588-AAED851B6CF9", "94ddc5b44c66c523dbf70622efb612d3", 0.466666, False)
"""默认时长: 0.47s"""
AntiCW_Swirl = Transition_meta("Anti-CW Swirl", False, "6941282383836484098", "B3E4C41E-A7F3-4463-8A7B-35D5CB32AB50", "de63b182c2c654b2eef98b8681d12f2c", 0.466666, False)
"""默认时长: 0.47s"""
Transform_Shimmer = Transition_meta("Transform Shimmer", False, "7452646287318454785", "0CEA0FD6-E103-4982-8583-6C2087AB14DF", "486a1593cc532d15663279bd4a127a45", 0.466666, True)
"""默认时长: 0.47s"""
Twinkle_Zoom = Transition_meta("Twinkle Zoom", False, "7452646287326843393", "15C1A448-AB09-4867-8A9A-DDDD11A5AB27", "7eeeca7c07e67b54519995ebdf71d6fc", 1.000000, True)
"""默认时长: 1.00s"""
Horizontal_Blur = Transition_meta("Horizontal Blur", False, "7451535587812594193", "63C1D344-D734-4945-A2D8-867AE7559ABC", "38f584c24f4383e9d10037ad4ce6fa00", 0.466666, True)
"""默认时长: 0.47s"""
Horizontal_Blur_1 = Transition_meta("Horizontal Blur", False, "7451535587812594193", "1F8B47C7-9873-4a99-8005-CDCD3BB92475", "38f584c24f4383e9d10037ad4ce6fa00", 1.466666, True)
"""默认时长: 1.47s"""
Horizontal_Blur_2 = Transition_meta("Horizontal Blur", False, "7451535587812594193", "BCC3D324-3D51-45bd-9887-5951024C6AF3", "38f584c24f4383e9d10037ad4ce6fa00", 0.466666, True)
"""默认时长: 0.47s"""
Radial_Blur = Transition_meta("Radial Blur", False, "7215489792597824001", "53E34B82-8CA8-483f-BBE9-EB36EFD0EE1B", "917c209246e975d4f10d9b8c8c78035f", 0.466666, False)
"""默认时长: 0.47s"""
Blurred_Highlight = Transition_meta("Blurred Highlight", False, "7134999483762348545", "A1C6E234-BAE9-4de6-B659-528933BABFE2", "b48f47c097e83842d1c0f919d9c67af6", 0.466666, False)
"""默认时长: 0.47s"""
Vertical_Blur = Transition_meta("Vertical Blur", False, "7140916992118100482", "6A89818E-BB6F-4246-AE07-8AFE7313E55D", "f55306a27ff8e0a8ae29584bb661ad73", 0.466666, False)
"""默认时长: 0.47s"""
Blur = Transition_meta("Blur", False, "6916426617455645186", "C5F81057-B249-4f1c-9F80-050CE6C2B25C", "fc1352435f88c6f284b6c6dce8552ffe", 0.466666, False)
"""默认时长: 0.47s"""
Woosh = Transition_meta("Woosh", False, "6724239584663704071", "CD580815-D706-4c17-8DA1-D31CDD568A44", "06cc8d49c558d57e21207f68a6a7dbc0", 0.466666, False)
"""默认时长: 0.47s"""
Particles = Transition_meta("Particles", False, "6873386344463208961", "57FF7625-725F-42e5-B38B-46891069A35E", "3895bd9b5abd7037c3bfc0d2a8a589c9", 0.466666, False)
"""默认时长: 0.47s"""
Mosaic = Transition_meta("Mosaic", False, "6724866519022440967", "D3BFC8FC-0F55-4ff6-9424-BCE5740E4D2B", "eed93b26d9cd6296b10d2f5065ee396e", 0.466666, False)
"""默认时长: 0.47s"""
Blink = Transition_meta("Blink", False, "6864867302936941064", "B57A7648-AE5E-420a-8072-1076AF79C58D", "bf695506c8091f7a01ee7b1323a4d601", 0.466666, False)
"""默认时长: 0.47s"""
Flip_II = Transition_meta("Flip II", False, "7049556888014295553", "38215832-385B-4135-A874-7208224A0552", "b1c8a0ab546d85581327609c5c0a3b1a", 0.466666, False)
"""默认时长: 0.47s"""
Flip = Transition_meta("Flip", False, "6848792278710882824", "280B7887-CD12-466f-B32C-D3595AC99805", "ff85b6664407c72dbb592f3780a32ac9", 1.000000, False)
"""默认时长: 1.00s"""
Left = Transition_meta("Left", False, "6726711499676455435", "9CA0C177-8A1D-410c-9D37-7F6606CD5BB5", "1315a55c2f804d86894e1453976b48fd", 0.466666, False)
"""默认时长: 0.47s"""
Up = Transition_meta("Up", False, "6724846395116753416", "19845B95-29A4-46a4-9E8D-9863FBA84E01", "df9bc16697464de201a4924de49234a2", 0.466666, False)
"""默认时长: 0.47s"""
Wipe_Right = Transition_meta("Wipe Right", False, "6724849898857959950", "0CF8046E-31BD-4b4e-94D0-13050511EE07", "316d71f3567673d63575f027e9e9df18", 0.466666, False)
"""默认时长: 0.47s"""
Open_Horizontally = Transition_meta("Open Horizontally", False, "6724492948144132621", "9A3770E3-2F40-479e-A344-09D9D7378362", "de63aa2d5225bb6a65b5bab8702aa1f5", 0.466666, False)
"""默认时长: 0.47s"""
Right_1 = Transition_meta("Right", False, "6726711296063967748", "C10E8EAA-41F8-49c4-86CE-BB4D65449A2C", "2712989c4cdece84c2979196c16186a6", 1.000000, True)
"""默认时长: 1.00s"""
Slide = Transition_meta("Slide", False, "6757982416649851399", "AF0D3666-48D3-4ff0-B836-EB93B174A74A", "b99916e2936aeb2e56892ca617888694", 0.466666, False)
"""默认时长: 0.47s"""
Slide_1 = Transition_meta("Slide", False, "6757982416649851399", "D3AA4635-FE90-48d7-9B0D-FD6C7E42939A", "b99916e2936aeb2e56892ca617888694", 0.466666, False)
"""默认时长: 0.47s"""
Wipe_Up = Transition_meta("Wipe Up", False, "6724849456891564557", "07E81171-A3FE-42e7-B4CD-E44CC367D61D", "5d4d41dbfec9fb012d964d124d546e20", 0.466666, True)
"""默认时长: 0.47s"""
Wipe_Left = Transition_meta("Wipe Left", False, "6724849999336706573", "954E4D5A-40DF-4b87-B4AA-F68DBA2657FA", "ea955d4c6033e6e3720a3c40eb2929bf", 0.466666, False)
"""默认时长: 0.47s"""
Wipe_Left_1 = Transition_meta("Wipe Left", False, "6724849999336706573", "592F8AA3-394C-4d61-908D-F3C09503CAFD", "ea955d4c6033e6e3720a3c40eb2929bf", 0.466666, False)
"""默认时长: 0.47s"""
Open_Vertically = Transition_meta("Open Vertically", False, "6726711903684399619", "92F83B7A-AD64-4514-A75A-D1D36686DB9A", "84f91be5a43cc6a9d03505a465418206", 0.466666, False)
"""默认时长: 0.47s"""
Curling_Wave = Transition_meta("Curling Wave", False, "6858191497280360973", "0873E31A-1DA7-48d1-9185-03E6F5AAAF79", "cf9bac91349a227a6155eca9d94a8af8", 0.466666, False)
"""默认时长: 0.47s"""
Flame = Transition_meta("Flame", False, "6777178765643485709", "439B818A-D20B-45a4-9D3F-0FAA3E74A6D6", "8e7c247c5ebd58aa5c3582273e9c840b", 0.466666, False)
"""默认时长: 0.47s"""
Cartoon_Swirl = Transition_meta("Cartoon Swirl", False, "6858191448827761160", "4CDDADDB-5C4E-4523-8FD6-EA442A5284D8", "fa7ba99b13036c0ff167ea3b7d5c31a2", 0.466666, False)
"""默认时长: 0.47s"""
Blue_Lines = Transition_meta("Blue Lines", False, "6858191605384352263", "456AA927-F3D0-4093-A043-5B600C23D44A", "d4d2996c3f6cf97fb8602f825d98a4da", 0.466666, False)
"""默认时长: 0.47s"""
Recorder = Transition_meta("Recorder", False, "7071174465245155841", "18B10157-8D51-4360-A35A-42008543438C", "bb0b9fa428e5a3fde828c03022b5082d", 0.466666, False)
"""默认时长: 0.47s"""
Like = Transition_meta("Like", False, "7071174465245172226", "A1ADAF22-363E-47f4-8D73-4A2E8D91E890", "945ee55ddc4b7c9762b55c0ee302bdce", 0.466666, False)
"""默认时长: 0.47s"""
Little_Devil = Transition_meta("Little Devil", False, "7078647070499803649", "CBD96057-053F-44f2-ABC8-9B34F37D6557", "c9a87dfafa58fbc0d401fc182fbaf6fc", 0.466666, False)
"""默认时长: 0.47s"""
Super_Like = Transition_meta("Super Like", False, "7071174465249350146", "F4996065-6334-46a8-A4F2-34C86D8072B0", "e0bd13b237d73eb121473c442c752a23", 0.466666, False)
"""默认时长: 0.47s"""
Lightning = Transition_meta("Lightning", False, "6777178696609436174", "4159AED7-E464-4949-9D8A-518653D13F22", "3fd5d0c7c48668ba5305c57ac0b5d596", 0.466666, False)
"""默认时长: 0.47s"""
Snow = Transition_meta("Snow", False, "7171709546262434306", "0170A589-AD1C-46c4-B195-9CE519FDFA18", "c5c7c3c9c9ea3ca576acefe8a278f6ed", 0.466666, False)
"""默认时长: 0.47s"""
White_Ink = Transition_meta("White Ink", False, "6858191556055142919", "2A26CD9F-F91F-4f4f-AD1A-FB539C06C156", "775ccf71576e2b8fb075f0e61e980923", 0.466666, False)
"""默认时长: 0.47s"""
Cloud = Transition_meta("Cloud", False, "6777178865119793678", "0A31EC48-C245-48ab-847C-EF25F17D8CA3", "e835cbc7fa7b15af90a2a7090bbf68c3", 0.466666, False)
"""默认时长: 0.47s"""
Wave_Right = Transition_meta("Wave Right", False, "6858191510865711629", "FDBBEE84-E35D-420c-8BE4-1662B76468CE", "e9301bacebc6dc444aa4e6f835dd4a31", 0.466666, False)
"""默认时长: 0.47s"""
Wave_Left = Transition_meta("Wave Left", False, "6858191524312650248", "D55F1CE9-BAED-45b6-A319-95149730CE6C", "6b6499879310b6d29e9595799829cb15", 0.466666, False)
"""默认时长: 0.47s"""
Dots_Right = Transition_meta("Dots Right", False, "6858191541706428941", "CFE7F1A0-ED26-4ca7-93FA-E72E8B148E49", "74c13e6250cdff7a4e860625d1098e0c", 0.466666, False)
"""默认时长: 0.47s"""
Circular_Slices_II = Transition_meta("Circular Slices II", False, "7320530650979635713", "0B97966C-1F8F-4d87-BD53-22902ABFEE62", "de6b1094111db6d63840edad9aacbe6d", 0.800000, True)
"""默认时长: 0.80s"""
Split_III = Transition_meta("Split III", False, "6973849570912506370", "1D0F1EE8-EC62-4138-AF85-C3E1141A0733", "942fd71d67ca576384b2cd068157ca45", 0.466666, False)
"""默认时长: 0.47s"""
Horizontal_Slice = Transition_meta("Horizontal Slice", False, "7090080817849831938", "8FA54E1C-722C-49d7-A47F-5CE5910D46AA", "aa0aa4a72fc236611d3fd4bf75a12ca3", 0.466666, True)
"""默认时长: 0.47s"""
Diagonal_Slices = Transition_meta("Diagonal Slices", False, "7090080734941024769", "5FC9CD57-67FB-4c37-B648-3FA60B4E9DD4", "6ae9eb3ee4b08afa67e3d079a2ece505", 0.466666, True)
"""默认时长: 0.47s"""
Split = Transition_meta("Split", False, "6973849417468088833", "648C5EF4-7516-4478-B5A5-84EDBF8605A6", "ca45695f29bacf2dc29a6eb959e9e968", 0.466666, False)
"""默认时长: 0.47s"""
Vertical_Slices = Transition_meta("Vertical Slices", False, "7090080890201575938", "DC0BFFDA-FF8D-4ace-B01D-E412DE76AE96", "7cc017d4e1b6ab58ec4b6900432522ff", 0.466666, True)
"""默认时长: 0.47s"""
Split_IV = Transition_meta("Split IV", False, "6973849689107993090", "FD4E4727-F7C9-446c-99CF-B8E6862352A4", "62d08c08542fe62e6a8429f9501e76fa", 0.466666, False)
"""默认时长: 0.47s"""
Vintage_Screening = Transition_meta("Vintage Screening", False, "7242576260310766082", "8E23FB8D-17B8-4f6a-BE23-2EEE4D3F159D", "d9589a91617889714a627160b4d314d9", 0.466666, True)
"""默认时长: 0.47s"""
Vintage_Screening_1 = Transition_meta("Vintage Screening", False, "7242576260310766082", "1A596F3D-1CCF-41cb-9F07-1053C46D8343", "d9589a91617889714a627160b4d314d9", 0.600000, True)
"""默认时长: 0.60s"""
Cube = Transition_meta("Cube", False, "7429600601161338117", "BF8E9B01-A671-4a5a-B617-A1F18500B76A", "be45578bb628a21eaae268a8d8df868f", 0.466666, False)
"""默认时长: 0.47s"""
Switch = Transition_meta("Switch", False, "6748313807031898627", "1CD4B550-A634-40bf-9FD4-B513FAE603A6", "0ee10b771dc0443c41a90bb9fd6b3c25", 0.466666, False)
"""默认时长: 0.47s"""
Open = Transition_meta("Open", False, "6750893890712113677", "AF82FDC0-9DDC-4a57-B947-BFA99B14A5B5", "d5f097e701ddaa984a590249896fc51a", 0.466666, False)
"""默认时长: 0.47s"""
Page_Turning = Transition_meta("Page Turning", False, "6747979085894390279", "5E3BB33E-87AD-4b41-9222-C32D9A6D9D57", "2f157ee5d78c197efc26f8ed37490573", 0.466666, False)
"""默认时长: 0.47s"""
Clock_wipe = Transition_meta("Clock wipe", False, "6851775006418932238", "2C82254C-9BDD-4190-9CA7-F2D2B7BB65D9", "0260ab98d7a840c3344cb5b3e70b7d4b", 0.466666, False)
"""默认时长: 0.47s"""
Windmill = Transition_meta("Windmill", False, "6748286529921094157", "44AE658A-5AE8-495b-8EAA-60B7C38C8DF6", "367b8b51b2eeb63eb2009bf5b356bc2f", 0.466666, False)
"""默认时长: 0.47s"""
Color_Glitch = Transition_meta("Color Glitch", False, "6724239785205961228", "6D20B259-B8A7-4d6a-8EB0-84B5D5480061", "9de90519d59e432b81c38423aa0393d7", 0.466666, False)
"""默认时长: 0.47s"""
Strobe = Transition_meta("Strobe", False, "7131930101599441410", "B5CF94E0-3497-4523-9157-51740D3FB822", "35a76b77dd0812f7012911109db35799", 0.466666, False)
"""默认时长: 0.47s"""
Blocks = Transition_meta("Blocks", False, "6724866346569437710", "5509169E-345F-471c-AF3A-7E6B045BCA8D", "357e865f3bb0c6529ee882ebf279d7c6", 0.466666, False)
"""默认时长: 0.47s"""
Glitch = Transition_meta("Glitch", False, "6724866446842663431", "E082978D-EAC4-49e3-A1FC-7BAB68290FA6", "71cabe836d9c88afd44f43654ba67fa7", 0.466666, False)
"""默认时长: 0.47s"""
Horizontal_Lines = Transition_meta("Horizontal Lines", False, "6724845810892149251", "E50E5529-4184-4166-B6EC-2D29ABBB14C0", "36c1c8edb0171ea082c98d38ffa8bd36", 0.466666, False)
"""默认时长: 0.47s"""
Horizontal_Lines_1 = Transition_meta("Horizontal Lines", False, "6724845810892149251", "E97845C2-AC7A-418c-84CE-7ADC6F0C8BF6", "36c1c8edb0171ea082c98d38ffa8bd36", 0.466666, False)
"""默认时长: 0.47s"""
Cutout_Flip = Transition_meta("Cutout Flip", False, "7387771481670816257", "49A3F710-11D3-4466-A046-80C3FF82C213", "290a8f067f8039b1060df3d1e8d07ca0", 0.800000, True)
"""默认时长: 0.80s"""
Color_Swirl = Transition_meta("Color Swirl", False, "7480765113809620279", "8DF1E594-FCB6-4744-8292-DCFC3C1E203F", "b015b3ecd87f1bc8d678cff4203fefc2", 1.000000, True)
"""默认时长: 1.00s"""
Shutter_II = Transition_meta("Shutter II", False, "7306783264209900034", "79EE4136-73D9-4bfe-99FE-D116AA989729", "6e0d086441ba1fa0cb6c905b4e1f8f01", 0.600000, True)
"""默认时长: 0.60s"""
Stretch_ll = Transition_meta("Stretch ll", False, "7260116495974273538", "57594755-3485-4864-8C7F-A180195E053D", "d28fee612c51edf28da804983d220f8d", 0.600000, True)
"""默认时长: 0.60s"""
Stretch = Transition_meta("Stretch", False, "7250006074781078017", "9BEE0F74-29E9-4ebe-A433-6C085B00451F", "4fd21b4a2e6382ee8851c51c8f65ed73", 1.200000, True)
"""默认时长: 1.20s"""
Shutter = Transition_meta("Shutter", False, "6885172292339372546", "DD95C8CA-D8BB-4167-8FAA-94576CB16563", "2df569fefb5004c041af5509c10d6c53", 0.466666, False)
"""默认时长: 0.47s"""
Whirlpool = Transition_meta("Whirlpool", False, "6851810799510360583", "66915A1D-F523-4844-9573-4FDFC7FAA7CC", "31d2de43e6711a9eeb831d60529d0393", 0.466666, False)
"""默认时长: 0.47s"""
Whirlpool_1 = Transition_meta("Whirlpool", False, "6851810799510360583", "35B07B78-653B-48c8-8AF0-7ADFBB03F371", "31d2de43e6711a9eeb831d60529d0393", 0.466666, False)
"""默认时长: 0.47s"""
Distortion = Transition_meta("Distortion", False, "7169838836304843265", "CC11E10F-A87D-442d-AD26-83C7037C728B", "f864724f43f1d853c15e1d4a1d11117d", 0.466666, False)
"""默认时长: 0.47s"""
Axis_Rotation = Transition_meta("Axis Rotation", False, "7237092761361453569", "2F53B8F6-E9A8-4382-9B9A-B75D850DCD8D", "924f9eeeedd359e19f7ec303e3f79d2b", 0.800000, True)
"""默认时长: 0.80s"""
Stretch_Right = Transition_meta("Stretch Right", False, "6989922560506860033", "4381E87C-4E8A-4bcc-BA0F-A429F852F7C2", "0742c22666c136224b39762d2ead4e63", 0.466666, False)
"""默认时长: 0.47s"""
Stretch_Left = Transition_meta("Stretch Left", False, "6989922429980119554", "02976636-1A8D-4181-870F-21339FD9CA38", "b0dd96c3c203104a2df46d83dd91b7bd", 0.466666, False)
"""默认时长: 0.47s"""
Squeeze = Transition_meta("Squeeze", False, "6751618376780485133", "22016FF4-FBC8-4844-9108-CFFBCFE4D590", "337d4cd9be4e1860bd1e7e50a9a93841", 0.466666, False)
"""默认时长: 0.47s"""
Squeeze_1 = Transition_meta("Squeeze", False, "6751618376780485133", "FA59E619-C9AD-4c39-9205-9998FC6C9B48", "337d4cd9be4e1860bd1e7e50a9a93841", 0.466666, False)
"""默认时长: 0.47s"""
-603
View File
@@ -1,603 +0,0 @@
"""滤镜效果元数据"""
from .effect_meta import Effect_enum
from .effect_meta import Effect_meta, Effect_param
class Filter_type(Effect_enum):
"""剪映自带的滤镜效果类型
出现重名而只保留了其中一个的滤镜奶杏布朗琥珀夜雾月吟漫夏
"""
_1980 = Effect_meta("1980", False, "7127828208690433311", "7127828208690433311", "d3595847ee8348c69c6037b8003a76e9", [])
ABG = Effect_meta("ABG", False, "7127679308897832206", "7127679308897832206", "d07b36b0b8e1893ce49df327ba926804", [])
Ditto = Effect_meta("Ditto", False, "7195816046077496635", "7195816046077496635", "09d18408ca0dee53716c3a4f41dd35e1", [])
KE1 = Effect_meta("KE1", False, "7127819154018536741", "7127819154018536741", "5ece7eff894e25a356b9111e78478c56", [])
KV5D = Effect_meta("KV5D", False, "7127578859217620254", "7127578859217620254", "57940599e2c8d85a7f73824c7360bfca", [])
VHS_III = Effect_meta("VHS III", False, "7127669764905782542", "7127669764905782542", "c8d7adad4773fccc2128d8eafa569572", [])
三洋VPC = Effect_meta("三洋VPC", False, "7127669338089311495", "7127669338089311495", "73c77a4b9c5085af6175a523d24bc7c6", [])
书意 = Effect_meta("书意", False, "7368493100127292723", "7368493100127292723", "3e20d8ccc31ca6a495b3f8e2ff116744", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
亮肤 = Effect_meta("亮肤", False, "7127655008715230495", "7127655008715230495", "2aaa463c5deee34e73384d549edc7c15", [])
仲夏绿光 = Effect_meta("仲夏绿光", False, "7127675970252754189", "7127675970252754189", "970f4b2c797e2890787f7420d8c0613b", [])
似锦 = Effect_meta("似锦", False, "7188014191834418493", "7188014191834418493", "869cb94d6bbec5c6b771092ec1ef8cfe", [])
低保真 = Effect_meta("低保真", False, "7304170509661506843", "7304170509661506843", "db39172ffff69e973886c2e8598dbc75", [])
侘寂灰 = Effect_meta("侘寂灰", False, "7127609569416711455", "7127609569416711455", "17547e013b45f87dc7e4e1f7059d7e62", [])
冬恋 = Effect_meta("冬恋", False, "7304573577255324967", "7304573577255324967", "995b1153346f3f3237099b4357b78374", [])
冰火 = Effect_meta("冰火", False, "7303812389177265447", "7303812389177265447", "61065880d8580b8b1a206de0b0773571", [])
冰肌 = Effect_meta("冰肌", False, "7199089344756370743", "7199089344756370743", "18c6b91685b82ef1cd3d7b7261f997ea", [])
冷气机 = Effect_meta("冷气机", False, "7263359186883366155", "7263359186883366155", "740c1bfa9cb365344bd8a51bf7ef037b", [])
冷白 = Effect_meta("冷白", False, "7127614731187178783", "7127614731187178783", "a47ab1d817480c87ff6de4c9ba10b204", [])
冷蓝 = Effect_meta("冷蓝", False, "7127618237117877518", "7127618237117877518", "accf4492064dabe05dce1c28457b6f89", [])
凝黛 = Effect_meta("凝黛", False, "7298279202350976282", "7298279202350976282", "7bad3476dce5691d9e8f90f50122ed33", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
初冷 = Effect_meta("初冷", False, "7297566793881734438", "7297566793881734438", "5a97174119b20bbbc86a6cfd62e148d5", [])
初恋 = Effect_meta("初恋", False, "7195812984306814267", "7195812984306814267", "9fdc53e8dab072725d9bb088b8930869", [])
千玺IXU = Effect_meta("千玺IXU", False, "7127824119294364959", "7127824119294364959", "12af151fa57d3226ee3781a070ae54a6", [])
千金妝 = Effect_meta("千金妝", False, "7370585884078443802", "7370585884078443802", "e814069ba1dea090eeb44b397eeac252", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
即刻春光 = Effect_meta("即刻春光", False, "7127675868641594654", "7127675868641594654", "ba343f6bb3720ba81a8662d669b6b743", [])
原木 = Effect_meta("原木", False, "7127675195812351239", "7127675195812351239", "a2cb1c6dd47c2ce4aeb0dd7303353438", [])
古罗马 = Effect_meta("古罗马", False, "7242212640498568503", "7242212640498568503", "3d438e293e65d63e71af3db73b03bc4e", [])
喜市 = Effect_meta("喜市", False, "7185440129442417931", "7185440129442417931", "5210a45933f4265e5f262d3018a78d64", [])
复古工业 = Effect_meta("复古工业", False, "7127608212483820837", "7127608212483820837", "cf8d236e185f6b174544151be3baba93", [])
夏日风吟 = Effect_meta("夏日风吟", False, "7127684611802418445", "7127684611802418445", "3120cfc3dd0f1fe2090749012d60a20b", [])
奈良 = Effect_meta("奈良", False, "7351684015906147621", "7351684015906147621", "2a7ada2a5ac7a8742b37c3bc794b07b0", [])
奥本海默 = Effect_meta("奥本海默", False, "7271142654505766183", "7271142654505766183", "2a1f03001d0db5f28f73bee7bc00ccf7", [])
# 奶杏 = Effect_meta("奶杏", False, "7297134192100379938", "7297134192100379938", "89ae84878534d61d0b7d62ba395fc8b7", [])
奶油 = Effect_meta("奶油", False, "7127618513048571173", "7127618513048571173", "dd39d5622353128e5f7c1de20020359a", [])
奶绿 = Effect_meta("奶绿", False, "7127684319300029733", "7127684319300029733", "8924565ec41520d2a8a88d846069768f", [])
姜饼红 = Effect_meta("姜饼红", False, "7127624030135389471", "7127624030135389471", "22925be3f36caa278eb5df6a0278c636", [])
安愉 = Effect_meta("安愉", False, "7190242827543022880", "7190242827543022880", "ed7e951505cbf70dee0f4d144d239828", [])
富士CC_II = Effect_meta("富士CC II", False, "7268561903721401641", "7268561903721401641", "cb92e0b13cd9b9a3aca8bb00b1a9c328", [])
寻荷 = Effect_meta("寻荷", False, "7295362817874480425", "7295362817874480425", "0230f2fb3e9ea72df20f8819542b4410", [])
小镇 = Effect_meta("小镇", False, "7127654151688965384", "7127654151688965384", "fc386676ee752b20918fb61c42c28a7b", [])
山系 = Effect_meta("山系", False, "7127662738884545806", "7127662738884545806", "d9d5332152b0f951229402d7d840263e", [])
巧克力 = Effect_meta("巧克力", False, "7363220647767592243", "7363220647767592243", "6e513d9dcb9357219e35097b945a3881", [])
布兰卡 = Effect_meta("布兰卡", False, "7242208887883992381", "7242208887883992381", "1774e2dd335a10a5f3174062c08403a2", [])
布朗 = Effect_meta("布朗", False, "7273777590102527290", "7273777590102527290", "b6bee72111d56fd16679adcf9543a05a", [])
# 布朗 = Effect_meta("布朗", False, "7127576913375153415", "7127576913375153415", "1f969e8f3e5e8545f41715cde1baf946", [])
希望 = Effect_meta("希望", False, "7271141541521968396", "7271141541521968396", "fdb975090cbdc5a5fb2e56ae982514a2", [])
幽蓝 = Effect_meta("幽蓝", False, "7330441280016715062", "7330441280016715062", "9db4cff7dd63bf1a17ced3728ca02e5e", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
彩果 = Effect_meta("彩果", False, "7175101541198679353", "7175101541198679353", "a86fb22ed3009ad44f9457f6eefdb9a7", [])
影叙 = Effect_meta("影叙", False, "7349953761059638555", "7349953761059638555", "72e02210098c120bbcddca245656aaca", [])
德古拉 = Effect_meta("德古拉", False, "7127678346472819982", "7127678346472819982", "f8bfba1ebdb6c5054eec4eb1e9433e72", [])
快照I = Effect_meta("快照I", False, "7143537677655100709", "7143537677655100709", "526ce6c2fd2228cda17fc5f64a7267cf", [])
忽风 = Effect_meta("忽风", False, "7330123964305378586", "7330123964305378586", "c455bc6760bd9829f2d467866527a1b1", [])
恋颂 = Effect_meta("恋颂", False, "7307103748076113188", "7307103748076113188", "2919ab042e2f8b431826f90ba9bb3e89", [])
敦刻尔克 = Effect_meta("敦刻尔克", False, "7127568601921408293", "7127568601921408293", "6b4a7017eecf10aa48e3f93586e04a6a", [])
料理 = Effect_meta("料理", False, "7127656350833806622", "7127656350833806622", "31ebabffaf3ed8653e0db318dfbeaa9d", [])
新闪 = Effect_meta("新闪", False, "7342395072199019803", "7342395072199019803", "9c3858dfbdd548bef8a012d55f795b47", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
日出 = Effect_meta("日出", False, "7325383700240256296", "7325383700240256296", "628b7f7c8a7fea3f89edaff21f4c9d25", [])
日系奶油 = Effect_meta("日系奶油", False, "7127664177870671135", "7127664177870671135", "8e779b2183d399fb192decf3616f8c27", [])
日落橘 = Effect_meta("日落橘", False, "7127669630667066655", "7127669630667066655", "1ff996d1537f8a485f193314861c6b5b", [])
旧乐园 = Effect_meta("旧乐园", False, "7239977329668263227", "7239977329668263227", "604ff64bec0ae328aa1d1c19fb89bfa2", [])
旧时代I = Effect_meta("旧时代I", False, "7232218563270954300", "7232218563270954300", "9532fcb213a6eb45c2441d8d0466f9ef", [])
明晰 = Effect_meta("明晰", False, "7367715162964446516", "7367715162964446516", "c622c908228fb2796e141f973b9746e9", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
星云 = Effect_meta("星云", False, "7127672042069036319", "7127672042069036319", "b73b7e9c33f8e387cbb579a5c11f01b9", [])
晴颜 = Effect_meta("晴颜", False, "7297968738131873035", "7297968738131873035", "97b54d7d49c75162656379068221e3a1", [])
暖食 = Effect_meta("暖食", False, "7127653100269210916", "7127653100269210916", "47b7c1b9f560b85b528c24f7cbbb6cd4", [])
暗夜 = Effect_meta("暗夜", False, "7127823728070659358", "7127823728070659358", "788c476ccf299db46035bd930d90c342", [])
暗雅 = Effect_meta("暗雅", False, "7127656352410848548", "7127656352410848548", "c5207d449099512b7efd9419c75378f7", [])
暮光 = Effect_meta("暮光", False, "7242211155131862332", "7242211155131862332", "b5e36cb0438d74eac97fb6c7ec66260f", [])
暮色 = Effect_meta("暮色", False, "7127594686541237535", "7127594686541237535", "adbf6d3bbbd6a6d4525300d78323a7d2", [])
月升之国 = Effect_meta("月升之国", False, "7127819487419567373", "7127819487419567373", "46638e887295beddd23c84206af26a1b", [])
月夜 = Effect_meta("月夜", False, "7143532202112912670", "7143532202112912670", "67cfe630584f194d007e3001052f5094", [])
月辉 = Effect_meta("月辉", False, "7213576268346838333", "7213576268346838333", "606cb40e4b0b4706855126dc82ed3e01", [])
未央 = Effect_meta("未央", False, "7340282260312182050", "7340282260312182050", "901d60cca1c56063279941926ed877be", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
松果棕 = Effect_meta("松果棕", False, "7127669342325443854", "7127669342325443854", "d68bcfc1e312f0e3e52f164a59cff686", [])
林间 = Effect_meta("林间", False, "7127663793827564808", "7127663793827564808", "c1ff0cd2a3eea239334b9604d31b4947", [])
枫糖咖 = Effect_meta("枫糖咖", False, "7305333618891574567", "7305333618891574567", "9ec78b71c47895ec6ff375a62b5b77d0", [])
柠檬青 = Effect_meta("柠檬青", False, "7127676358766923016", "7127676358766923016", "0437481ce079dd3f1160351c1038d628", [])
梦海 = Effect_meta("梦海", False, "7307544983454682431", "7307544983454682431", "09ce81fe256e044893d494f48532f66a", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
梨花白 = Effect_meta("梨花白", False, "7345493751416016166", "7345493751416016166", "fa20a675c5b9caa46f42809746ed3ff5", [])
梵时 = Effect_meta("梵时", False, "7341767383259942155", "7341767383259942155", "a8908ae23533d029ea98fd6c5d052143", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
棕咖 = Effect_meta("棕咖", False, "7273779209934245179", "7273779209934245179", "d661b0ee2e5417c12e824af664490161", [])
棕宥 = Effect_meta("棕宥", False, "7332348414933421366", "7332348414933421366", "d3dfad8c9cbc044369c528461bd79f57", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
棠梨 = Effect_meta("棠梨", False, "7329819965920398604", "7329819965920398604", "09c9a4e110dd011c2155a544ecfe4b89", [])
椰林 = Effect_meta("椰林", False, "7252674515287788856", "7252674515287788856", "d0e4bf788a131db36ccf98e09f6cf056", [])
椿和 = Effect_meta("椿和", False, "7341032461234654475", "7341032461234654475", "46b1e432d7075fe6dc2b31d98809dac5", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
椿来 = Effect_meta("椿来", False, "7347729407181704498", "7347729407181704498", "13780c3447b3326ab87365015d0d0cb9", [])
樱粉 = Effect_meta("樱粉", False, "7127632545272925470", "7127632545272925470", "a5411e69fdf93e03f1d0c29ee6822173", [])
比佛利 = Effect_meta("比佛利", False, "7127657040348040479", "7127657040348040479", "0b705ff4b8eb7fe5090848b588139e75", [])
气泡水 = Effect_meta("气泡水", False, "7127619120761212168", "7127619120761212168", "4a0b28181b76b9ba2dd4ccdf66aa905a", [])
气色 = Effect_meta("气色", False, "7127681015732014350", "7127681015732014350", "b0d684a9b8ac503bcc80efd5213c0e9e", [])
江浙沪 = Effect_meta("江浙沪", False, "7127838224344435981", "7127838224344435981", "9287d59bc7ff0bce6f4893b0383c4bfe", [])
浅岛 = Effect_meta("浅岛", False, "7281163331245821239", "7281163331245821239", "dc6d03248744c082a2929bb29184f820", [])
浮生 = Effect_meta("浮生", False, "7340687187194678569", "7340687187194678569", "f438386d5155971f6ecd2600126fcbb4", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
海街日记 = Effect_meta("海街日记", False, "7127615915004366116", "7127615915004366116", "8ac09d35b39a8b6f289ef5f4330a3d62", [])
海雾 = Effect_meta("海雾", False, "7189595107610447163", "7189595107610447163", "3099b6872219761db76f4c7cc86ea0e5", [])
海鸥DC = Effect_meta("海鸥DC", False, "7127830050786823437", "7127830050786823437", "8cd726548b6275553ce2668cca28f32e", [])
深褐 = Effect_meta("深褐", False, "7127615347703811336", "7127615347703811336", "e7e999ed75f9f3a0626cf946b08c4f35", [])
清明上河 = Effect_meta("清明上河", False, "7208495962887621899", "7208495962887621899", "9fa5e1e67f3217c48cb8e64c26469fc1", [])
清晰 = Effect_meta("清晰", False, "7127621434230213924", "7127621434230213924", "783e545788c2a60d5d85a160ee5371ae", [])
清澈 = Effect_meta("清澈", False, "7359419156619332902", "7359419156619332902", "a40f003f9ea1ff5570314e7fa1e0a289", [])
温述 = Effect_meta("温述", False, "7351580023742090535", "7351580023742090535", "207610064067f787d8339e8661a19d72", [])
港历 = Effect_meta("港历", False, "7346017304909581587", "7346017304909581587", "a60377ccb7d2eba39c9c9a54178f2869", [])
港风 = Effect_meta("港风", False, "7127830945243090184", "7127830945243090184", "44c277e7933012ecceaa669d4bc64452", [])
漫夏 = Effect_meta("漫夏", False, "7366616947703991571", "7366616947703991571", "3b090944724c8cc1a8d7a5d73be3358f", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
漫彩 = Effect_meta("漫彩", False, "7177269429972045089", "7177269429972045089", "71885c8e558e4b6fece843e3d4464e62", [])
漫步 = Effect_meta("漫步", False, "7263357613050563852", "7263357613050563852", "de874f8a3993f93bb067593f0dfcfa5a", [])
烘培 = Effect_meta("烘培", False, "7127675183246200072", "7127675183246200072", "55cb15f600fff6aa4bda19f490aa7548", [])
烟岚 = Effect_meta("烟岚", False, "7341204799590763788", "7341204799590763788", "33937d0f480f994e09bc32adfe352cbd", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
烟霞 = Effect_meta("烟霞", False, "7143533042978524424", "7143533042978524424", "e33d66d89891ebab00dabb91a4b4caee", [])
煦日 = Effect_meta("煦日", False, "7297144048903556388", "7297144048903556388", "0ccb49dc9361df2d3262786b6c43d8ee", [])
燃力 = Effect_meta("燃力", False, "7248571956860079395", "7248571956860079395", "f8deda9b7cb4ff2f4e6382795c7265a7", [])
牛皮纸 = Effect_meta("牛皮纸", False, "7127822013074263310", "7127822013074263310", "351a03b45cb0cd2e13911113e7b06ca5", [])
珠光蓝 = Effect_meta("珠光蓝", False, "7127657509501914399", "7127657509501914399", "2b91f0f9a4a9cac90b3cd1be50637f58", [])
珠落 = Effect_meta("珠落", False, "7213575938615872823", "7213575938615872823", "9ced1b064be8feb4c3c3b2989b61e286", [])
# 琥珀 = Effect_meta("琥珀", False, "7127620849372302629", "7127620849372302629", "3cda15f337b1fc8ce63bcc055926779c", [])
病娇 = Effect_meta("病娇", False, "7291179909718740259", "7291179909718740259", "5e1e1d48442e9e2fa3bab8e724bce4ad", [])
白皙 = Effect_meta("白皙", False, "7127668617147141413", "7127668617147141413", "d029402b10782b63f67967b4d1bc1c03", [])
盐岚 = Effect_meta("盐岚", False, "7359223280714239268", "7359223280714239268", "e517e2dd0dc2601874ce0ca63c9cc75d", [])
矿野 = Effect_meta("矿野", False, "7281162649314889015", "7281162649314889015", "7e645e33c8e3d019669e9cb5d03d6886", [])
砂红 = Effect_meta("砂红", False, "7300758676732677427", "7300758676732677427", "2f33ad8925eb2079b23900241fcf83a4", [])
砾绀 = Effect_meta("砾绀", False, "7340915058542759219", "7340915058542759219", "d0f6bbafe6d5b1d6d5100e99c79b9e9e", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
祈安 = Effect_meta("祈安", False, "7314682996131433766", "7314682996131433766", "2a9a992fc75889486745e8213a7047f8", [])
空灵 = Effect_meta("空灵", False, "7353555308448419098", "7353555308448419098", "341afbfb8058ac32a1994b2dc39be59c", [])
米棕 = Effect_meta("米棕", False, "7221477781043973413", "7221477781043973413", "e687f0134f6ee01f8f50198bd52ebd00", [])
粉瓷 = Effect_meta("粉瓷", False, "7127667757998411044", "7127667757998411044", "76eac8836f1ddd762af8c6317b1c8c73", [])
粉肤 = Effect_meta("粉肤", False, "7296493947625557286", "7296493947625557286", "1b4893feb8dac4eb014b6e3f52449786", [])
粹光 = Effect_meta("粹光", False, "7373693828328475941", "7373693828328475941", "a3b69c7718dab46fedcd6ceabcb7425b", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
素肌 = Effect_meta("素肌", False, "7127671162758270245", "7127671162758270245", "cfb819eefe90e08965021dfea52d402b", [])
红绿 = Effect_meta("红绿", False, "7127622617699290399", "7127622617699290399", "e20b3185492170b68d6c7944270e3f76", [])
绝对红 = Effect_meta("绝对红", False, "7127667361456426248", "7127667361456426248", "cc6084f69428c5a741ea4280ddbfe3c8", [])
绿妍 = Effect_meta("绿妍", False, "7127675252410223909", "7127675252410223909", "46a6f490249d7eabe3a9e8cd8e92cf2d", [])
老友记 = Effect_meta("老友记", False, "7127669912050420999", "7127669912050420999", "e45f9a4c50717a3585006591b41e3440", [])
胡桃木 = Effect_meta("胡桃木", False, "7127830961621847310", "7127830961621847310", "5eb7457d0d18cfdf0dcd99725acf2dd9", [])
自然 = Effect_meta("自然", False, "7127821314198342943", "7127821314198342943", "f4a371ed60b7448b146cd1b1c697a9e8", [])
自由 = Effect_meta("自由", False, "7271143155544739108", "7271143155544739108", "a202f96129bf04064a37cd92f5fda5b9", [])
臻金 = Effect_meta("臻金", False, "7306726303594564904", "7306726303594564904", "6cae1766e18f62be45ddcf4d169da037", [])
花园 = Effect_meta("花园", False, "7226990672190950713", "7226990672190950713", "b235531243327c4b03bdd5495f95d9c6", [])
花椿 = Effect_meta("花椿", False, "7127539889553427719", "7127539889553427719", "6502db5f541da3fdfbedf9161a79e53c", [])
苍岭 = Effect_meta("苍岭", False, "7310976403078434102", "7310976403078434102", "df38cb08feab82523e96b89856e4030d", [])
落日 = Effect_meta("落日", False, "7166494058305670432", "7166494058305670432", "a3909c6739bcfffce11c1ed328afdb39", [])
落日海岛 = Effect_meta("落日海岛", False, "7369501986401570099", "7369501986401570099", "0cefc26f8aa950c8934766ad229255bc", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
落日飞车 = Effect_meta("落日飞车", False, "7350133636890463498", "7350133636890463498", "c92ce87d49816b7c930d5c1a5f537536", [])
薄荷 = Effect_meta("薄荷", False, "7343782317820857641", "7343782317820857641", "eed11d695897d0068dc658d09a18f444", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
褪色 = Effect_meta("褪色", False, "7127668404764380447", "7127668404764380447", "13ed65a66841ee746146665f0aa18c6d", [])
西野 = Effect_meta("西野", False, "7331590962696834313", "7331590962696834313", "c5368d1617ac7b8af8b616782b388557", [])
西餐 = Effect_meta("西餐", False, "7127668806398315806", "7127668806398315806", "c447f798e1aaf5a776b40432571e9ee8", [])
谧歌 = Effect_meta("谧歌", False, "7301212776532380966", "7301212776532380966", "229eed4ae519e0c29efe23a2f07ba644", [])
贝松绿 = Effect_meta("贝松绿", False, "7127668616991952158", "7127668616991952158", "5820a95014d61c7b5a45d23ba045d0e1", [])
质感暗调 = Effect_meta("质感暗调", False, "7127653798155209997", "7127653798155209997", "80cc0198c081d823bfbfa08fd5e0c3c6", [])
赛博朋克 = Effect_meta("赛博朋克", False, "7127657979838516494", "7127657979838516494", "fe6d8ddb41fd8ea4f184ff5d9ca0b77e", [])
赤陀 = Effect_meta("赤陀", False, "7226251886360300837", "7226251886360300837", "f44a2fd63bcdb30bd1cdfd1120ced1e1", [])
赫本 = Effect_meta("赫本", False, "7127663117508660517", "7127663117508660517", "589b59735865a200db3ac561640ed299", [])
赫石 = Effect_meta("赫石", False, "7302823953406446899", "7302823953406446899", "4be5b26f8b932f7fe7a3f8033d5549b2", [])
轻食 = Effect_meta("轻食", False, "7127621137705618724", "7127621137705618724", "27fbb36cf04af9886d4d9e6abcd3691b", [])
达芬妮 = Effect_meta("达芬妮", False, "7300602459356040484", "7300602459356040484", "e9556101678a74dc573133da00401854", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
迈阿密 = Effect_meta("迈阿密", False, "7127684611450178823", "7127684611450178823", "f9f32708f0029a5b043736e64133324f", [])
酷白 = Effect_meta("酷白", False, "7127676762514885919", "7127676762514885919", "e62e07d9ed430226e6afaa96dba3844a", [])
金属 = Effect_meta("金属", False, "7127654151688949000", "7127654151688949000", "7aaae4aad5195f4df6929d9cb2f77fc9", [])
闪光灯 = Effect_meta("闪光灯", False, "7364705637931994405", "7364705637931994405", "5b6fd1621826d837d88c71de0ced5f76", [])
闻香识人 = Effect_meta("闻香识人", False, "7127823728267775263", "7127823728267775263", "56693fef51ca05d7631f1bf3ae47c3cc", [])
阿尔菲 = Effect_meta("阿尔菲", False, "7299130097632627979", "7299130097632627979", "5225172497e1cd5bd3a8e1162a9c25d0", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
雪鹿 = Effect_meta("雪鹿", False, "7302796570947243264", "7302796570947243264", "10ff7e7bc0accc06c5ce3b9c09114b18", [])
雾瓷 = Effect_meta("雾瓷", False, "7169239634076060960", "7169239634076060960", "03e7a58f2d18954a4ced7fec8371cd5e", [])
青橙 = Effect_meta("青橙", False, "7127615575865478430", "7127615575865478430", "58b4c939e727d94fb074ca0a1c0400ad", [])
青红夜 = Effect_meta("青红夜", False, "7281575818621455628", "7281575818621455628", "7b439160a4134076dc70571813ec9cbb", [])
风铃 = Effect_meta("风铃", False, "7211001257996127547", "7211001257996127547", "48d79f8501ade6fd7a33055b83947eb8", [])
高饱和 = Effect_meta("高饱和", False, "7127653121966230814", "7127653121966230814", "a0533d46f3bc544f36e00965b2644067", [])
鬼魅 = Effect_meta("鬼魅", False, "7291201164027252024", "7291201164027252024", "20fd9ce9674e1e0137955e2d74ce252a", [])
黑胶唱片 = Effect_meta("黑胶唱片", False, "7221805176410180921", "7221805176410180921", "97fc59d95cbb611d888bf10da5a1c015", [])
黑豹 = Effect_meta("黑豹", False, "7202475126485503236", "7202475126485503236", "9f33e8c52e07d1af8ff00781f7645124", [])
默片 = Effect_meta("默片", False, "7127655037026848031", "7127655037026848031", "81be2b9491c4c805cb4f70a595ab46a6", [])
_160C = Effect_meta("160C", True, "7190249807682800954", "7190249807682800954", "7505f10b71bc6e346a1696544121ac9e", [])
_2077 = Effect_meta("2077", True, "7131347316111314189", "7131347316111314189", "a85f790077f307193b1c70ed94e4aa41", [])
_400H = Effect_meta("400H", True, "7190236487152127269", "7190236487152127269", "20817f9b1ed37a720c02abea87714655", [])
_800Z = Effect_meta("800Z", True, "7190237757552348471", "7190237757552348471", "53acbe492462a72db57c3f5ed7de9345", [])
_90s = Effect_meta("90s", True, "7131366613823114503", "7131366613823114503", "67f1677d3b2033d0ab1101789fd833cb", [])
City_Walk = Effect_meta("City Walk", True, "7263360572404550931", "7263360572404550931", "9a183540a03b391b3a17b67970ddc93a", [])
FXN = Effect_meta("FXN", True, "7332480052392774975", "7332480052392774975", "01cd75f7c9b5fb3b05bbcb54e53400d4", [])
GR正片 = Effect_meta("GR正片", True, "7168098796860148995", "7168098796860148995", "1f28a387f3f22baff4b1410530d2750f", [])
GR绿 = Effect_meta("GR绿", True, "7168121440141708576", "7168121440141708576", "5ad1db915106f04413a025928b28cdf5", [])
GR蓝 = Effect_meta("GR蓝", True, "7168097661160131879", "7168097661160131879", "c191e003d6d9f39dd5e9b770fb21ac29", [])
IG白 = Effect_meta("IG白", True, "7221479156318489893", "7221479156318489893", "02a7a3a08ed9756bb1ae7b924213c33d", [])
INS暗 = Effect_meta("INS暗", True, "7223645151820877093", "7223645151820877093", "29c393013eddca0fdd0ee0087100915e", [])
中性 = Effect_meta("中性", True, "7127621445806525704", "7127621445806525704", "8168144d29c35cf186eccb03ec9f3d93", [])
中性II = Effect_meta("中性II", True, "7312646907908607244", "7312646907908607244", "ad71ff12ac0afd02cb6c583d0ee69d8a", [])
丹枫 = Effect_meta("丹枫", True, "7297138825359281423", "7297138825359281423", "a97673c2524eba984b75396530501fa8", [])
乐游 = Effect_meta("乐游", True, "7193982146363673856", "7193982146363673856", "2a215f5fe9ff6c1a8effea9135bbe3bb", [])
云暖 = Effect_meta("云暖", True, "7314883649999015231", "7314883649999015231", "7819364ae09bf6c6771fce646cde6ec9", [])
人生之事 = Effect_meta("人生之事", True, "7148844086869396743", "7148844086869396743", "3dfc5764bccb9e7ec2e3f15e59edd563", [])
仲夏夜 = Effect_meta("仲夏夜", True, "7281166048273943867", "7281166048273943867", "0773453b9c513222ed0b2a629b141b38", [])
余晖 = Effect_meta("余晖", True, "7278616064018107707", "7278616064018107707", "19e8ac930af976579c60df1ad6f4c4fe", [])
佳能G7X_II = Effect_meta("佳能G7X II", True, "7291597100389862707", "7291597100389862707", "e9aef9a32a0ed9ebf39c9f23340fd408", [])
佳能G7X_III = Effect_meta("佳能G7X III", True, "7291595038688136474", "7291595038688136474", "3c89208f4754d78ad97df171a1cc1ffc", [])
俱乐部 = Effect_meta("俱乐部", True, "7239235794744003851", "7239235794744003851", "1f6a4516fb91c8e68217123191dc38ea", [])
倾森 = Effect_meta("倾森", True, "7332714336315526409", "7332714336315526409", "2b0731e9eacb5098ad43bd99ae6f23d7", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
光流 = Effect_meta("光流", True, "7233732009070300473", "7233732009070300473", "351346b807ca9bfa063e517f10d96f95", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
冬禧 = Effect_meta("冬禧", True, "7190250133672578316", "7190250133672578316", "6423fd745c7ba83613feea71977763fb", [])
冰原 = Effect_meta("冰原", True, "7171615136271060236", "7171615136271060236", "4664881945ad10f8e3de28f2ccd47e56", [])
冰瀑 = Effect_meta("冰瀑", True, "7196927862056701240", "7196927862056701240", "9691bde0838975e3573faad0791d3cdf", [])
冰茶 = Effect_meta("冰茶", True, "7131399016771800357", "7131399016771800357", "ab44066c23ab6639ca6ff5eb2b850582", [])
冰雪世界 = Effect_meta("冰雪世界", True, "7328364342146059531", "7328364342146059531", "6df501f5b6c1cdba49ded903a5d6a28c", [])
冷叙 = Effect_meta("冷叙", True, "7159132840179895590", "7159132840179895590", "c60635dea7f7a6df2ba9b1e08fee006e", [])
冷墨 = Effect_meta("冷墨", True, "7300751893813366053", "7300751893813366053", "e6d9891ef7f02898055a16f11a8750bc", [])
冷寂 = Effect_meta("冷寂", True, "7171628827477642535", "7171628827477642535", "9a932b548dfab1964a2d70ef27717d43", [])
冷月夜 = Effect_meta("冷月夜", True, "7281165355353951543", "7281165355353951543", "0a9aaba6174a6b1a46d78365bd7fa0c4", [])
冷透 = Effect_meta("冷透", True, "7127824802819116302", "7127824802819116302", "06655076bb1cf6ce7c6e3b23d027496f", [])
净白 = Effect_meta("净白", True, "7127667352782572807", "7127667352782572807", "c13995808d8fbfdf9ed2b9f2873dfea7", [])
净透 = Effect_meta("净透", True, "7127666004477414687", "7127666004477414687", "bc8357fb00d1824e2ceaed463bc611b6", [])
凛风 = Effect_meta("凛风", True, "7189593678816513340", "7189593678816513340", "c270ecab8fc6c7db7bbf30da6ea69ecd", [])
初雪 = Effect_meta("初雪", True, "7166473491737283873", "7166473491737283873", "50cf99c6a27c0a6e284fcc34afbe5e13", [])
初雪II = Effect_meta("初雪II", True, "7307159461724966185", "7307159461724966185", "348ff04e81ba87ea2638a5aa8282ff05", [])
劲闯 = Effect_meta("劲闯", True, "7248568097660013864", "7248568097660013864", "9822ae48045e256dfb2ca2369c368d47", [])
原生肤 = Effect_meta("原生肤", True, "7366582938638503187", "7366582938638503187", "8dc66d930e2420c9c035182ddbd3d627", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
去灰 = Effect_meta("去灰", True, "7127559231062002951", "7127559231062002951", "21c377ab968576732daa1643051b735c", [])
去灰II = Effect_meta("去灰II", True, "7226991425160858937", "7226991425160858937", "e58c1b8d3539cb1e89c37dc56b934369", [])
去黄 = Effect_meta("去黄", True, "7302338306849656127", "7302338306849656127", "f4fcb8afc69acb229dec8764320e42a3", [])
古早记忆 = Effect_meta("古早记忆", True, "7366562482812456255", "7366562482812456255", "3a6086410283e0166d65d7935faa3809", [])
古筑 = Effect_meta("古筑", True, "7226238008201104698", "7226238008201104698", "77e37950cce407b97cc09888476d64cc", [])
古都 = Effect_meta("古都", True, "7127615616525126949", "7127615616525126949", "ce6f674fe7eebb2be94a3784496d2d4f", [])
吉宵 = Effect_meta("吉宵", True, "7190241639070174503", "7190241639070174503", "14910132a5caef71f9fa0a1076098026", [])
向晚 = Effect_meta("向晚", True, "7226254370084490554", "7226254370084490554", "f16c7f86eb94ede08374f3485d9de7f6", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
味蕾 = Effect_meta("味蕾", True, "7281166220794055997", "7281166220794055997", "04205b3010d2adedb961380ceb679a6b", [])
哈苏I = Effect_meta("哈苏I", True, "7291596720956329266", "7291596720956329266", "df3882769e455938b11f5596ac569e49", [])
哈苏II = Effect_meta("哈苏II", True, "7291560741885480250", "7291560741885480250", "498b45335903ffa59cef94ac0376fd38", [])
哈苏蓝 = Effect_meta("哈苏蓝", True, "7361792059109313811", "7361792059109313811", "45392b51287027d5fa5249495c6a9007", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
哥谭 = Effect_meta("哥谭", True, "7337928347118275890", "7337928347118275890", "25575caefd72dfcac744d7aa717d4c1f", [])
增色 = Effect_meta("增色", True, "7283013745788357925", "7283013745788357925", "c1dffcebde80cca62c000f8f023065c8", [])
墨林 = Effect_meta("墨林", True, "7271284653816843554", "7271284653816843554", "a311fa20eacf38b912c183627e008ff5", [])
夏日粉 = Effect_meta("夏日粉", True, "7261469707138518283", "7261469707138518283", "b667443ab8554ad725bd72bb9cabab2b", [])
多巴胺 = Effect_meta("多巴胺", True, "7237441824611224889", "7237441824611224889", "83ec0f2e61d762e17830bd55ca08e8d3", [])
夜景增色 = Effect_meta("夜景增色", True, "7341302999068757259", "7341302999068757259", "f144c6f9e9accae6cb76c2b11b9549b2", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
夜雾 = Effect_meta("夜雾", True, "7168110568673479948", "7168110568673479948", "e6b2ff75ac938639d840ec586264c2f5", [])
# 夜雾 = Effect_meta("夜雾", True, "7132866902367423748", "7132866902367423748", "e6b2ff75ac938639d840ec586264c2f5", [])
奥林巴斯 = Effect_meta("奥林巴斯", True, "7361792068475325735", "7361792068475325735", "a523adb5976eb5a39d963683f520551f", [])
奶昔 = Effect_meta("奶昔", True, "7172169921726565670", "7172169921726565670", "ca0cc9a987f8eca36ac97a5b5d6a5327", [])
奶杏 = Effect_meta("奶杏", True, "7127670311775898917", "7127670311775898917", "bc9612d23f668596ecc50c1e636ed7e8", [])
好莱坞I = Effect_meta("好莱坞I", True, "7226994281414692155", "7226994281414692155", "b255b7959f2c621cdbc5aa7cda9e7583", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
好莱坞II = Effect_meta("好莱坞II", True, "7226995248814165308", "7226995248814165308", "41348d00e1ab4f1dbe6832f8b6224c13", [])
好莱坞III = Effect_meta("好莱坞III", True, "7312617341710372107", "7312617341710372107", "59b8ade3560f637686d6e4b0f56f97fe", [])
好莱坞IV = Effect_meta("好莱坞IV", True, "7312647197462367524", "7312647197462367524", "12657ebf4545c621bc0ca38944b9712c", [])
嫩肤 = Effect_meta("嫩肤", True, "7300523145818148096", "7300523145818148096", "f79fa85e5e9238570b84b95505406213", [])
子弹列车 = Effect_meta("子弹列车", True, "7202480777387445507", "7202480777387445507", "ee8aa0105ea992ace4fc114c34b08adc", [])
家宴 = Effect_meta("家宴", True, "7330584144524643595", "7330584144524643595", "1cb453a49c768a3f9c086b047321c233", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
宿营 = Effect_meta("宿营", True, "7127822311708691726", "7127822311708691726", "e8ad70a709e7a37282ee64779c874732", [])
富士CC_I = Effect_meta("富士CC I", True, "7268561936344780086", "7268561936344780086", "069ae1d53dc300c85b017cdf6df18550", [])
富士NC_I = Effect_meta("富士NC I", True, "7159156535640296737", "7159156535640296737", "bdce583bf77430b24e9f7d78d40a69eb", [])
富士NC_II = Effect_meta("富士NC II", True, "7159408376378559747", "7159408376378559747", "0fce68168c67f99c11bf1e05e933eb79", [])
富士NC_III = Effect_meta("富士NC III", True, "7159134459088899339", "7159134459088899339", "25f1e0d1d5997b56577a96de8de2005d", [])
富士蓝 = Effect_meta("富士蓝", True, "7246720031118101816", "7246720031118101816", "ca146f44fb50a5c1335149b2c1bd0079", [])
富士蓝II = Effect_meta("富士蓝II", True, "7226994246471945530", "7226994246471945530", "43bee1438c8372b1f4a8857650fab808", [])
富士青 = Effect_meta("富士青", True, "7226994214029184313", "7226994214029184313", "77bfdff2d848539626acd538429cc660", [])
小麦肌 = Effect_meta("小麦肌", True, "7131507906737917220", "7131507906737917220", "0498d2f3ee88c8073f774e908ade3400", [])
小麦色 = Effect_meta("小麦色", True, "7362076973981584691", "7362076973981584691", "ea639b8e75457d08c026eb753f8704e5", [])
尘烟 = Effect_meta("尘烟", True, "7148958479326153991", "7148958479326153991", "d649f05e5cc2f0f7a93d703418a4d7ee", [])
山晴 = Effect_meta("山晴", True, "7246723856222719269", "7246723856222719269", "acbd5fdb5b04114a6eedffdf716ed6b3", [])
山本 = Effect_meta("山本", True, "7156638423191784735", "7156638423191784735", "9bf35c896fe6637a3cd8017f5fc8eaed", [])
岚夏 = Effect_meta("岚夏", True, "7260771472107441471", "7260771472107441471", "5d9760bfa20e1745f2da9d0dddc1f8f3", [])
岩灰 = Effect_meta("岩灰", True, "7221472488079904060", "7221472488079904060", "fdd078505b4a102962d962cf461e9544", [])
底特律 = Effect_meta("底特律", True, "7336763348492553499", "7336763348492553499", "d1bcdfe293f329d701a0df1ef4ab5e16", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
彩光 = Effect_meta("彩光", True, "7127824109093866760", "7127824109093866760", "0aeae3c00b2ff3d26f0bba78a0f0cda5", [])
影部 = Effect_meta("影部", True, "7168136171673963787", "7168136171673963787", "57ebfdd7bdad96f19879e1635d823fb8", [])
徕卡I = Effect_meta("徕卡I", True, "7268562944093408523", "7268562944093408523", "91730e54e94b7eeb40bcfbd8f7c9a3cf", [])
徕卡II = Effect_meta("徕卡II", True, "7268563047776587020", "7268563047776587020", "a75e26160d19e9db7d9be10f6e8056b7", [])
心动夏 = Effect_meta("心动夏", True, "7261461692096220428", "7261461692096220428", "daffbda5fec8238d91024cb36610023d", [])
忆山 = Effect_meta("忆山", True, "7271278427309755688", "7271278427309755688", "919dd48c0590b884f6aabc4f46f63b3f", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
快照II = Effect_meta("快照II", True, "7143760738765655310", "7143760738765655310", "94a1e1cdca9b003126ac25d1df655263", [])
怦然心动 = Effect_meta("怦然心动", True, "7195889899738909990", "7195889899738909990", "48ce7e2b8db89c5f411f53d6d7750cb7", [])
恍光 = Effect_meta("恍光", True, "7237446176629345593", "7237446176629345593", "9c7e3ff19468cb967d0ff9b0d79ea23d", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
慕斯 = Effect_meta("慕斯", True, "7261185427703418169", "7261185427703418169", "038504b6474c25b4ce735d1d165c4198", [])
捕风 = Effect_meta("捕风", True, "7248566556593098024", "7248566556593098024", "2ebec31165718f44bbd2ecbc338c175a", [])
摩登 = Effect_meta("摩登", True, "7131219052021779719", "7131219052021779719", "178dab15fb53b396f20c89ccaec799a2", [])
攀岩 = Effect_meta("攀岩", True, "7195930274918567180", "7195930274918567180", "928cb605e08b3e72110837d55afaa9d9", [])
日和 = Effect_meta("日和", True, "7338311462277991718", "7338311462277991718", "70b43e53688e11ab0f849a5768cf6f6f", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
旧时代II = Effect_meta("旧时代II", True, "7232217903536409893", "7232217903536409893", "779a72d4b71cd42f470008749a165d93", [])
旧时来信 = Effect_meta("旧时来信", True, "7366562830486621459", "7366562830486621459", "1680dbb9fafa20e0a3c81e56b038508f", [])
旧金山 = Effect_meta("旧金山", True, "7159161900389977382", "7159161900389977382", "22f238fa32975ad165c124316008ab31", [])
旷野 = Effect_meta("旷野", True, "7275698024892943655", "7275698024892943655", "5d52166c545e774971e36e50cb218f04", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
旷野蓝 = Effect_meta("旷野蓝", True, "7131513310733765918", "7131513310733765918", "80b306543cb7373bc89f06ae76629ebe", [])
明肤 = Effect_meta("明肤", True, "7302334059890478347", "7302334059890478347", "db19d8273ad16417298afc8b9038778a", [])
春风 = Effect_meta("春风", True, "7148963827239963918", "7148963827239963918", "ae9468b81643a706f5cae5761eff19b8", [])
昭和 = Effect_meta("昭和", True, "7195780237790154042", "7195780237790154042", "211b05e6793f255052a1cc463864ed3d", [])
晚宴 = Effect_meta("晚宴", True, "7302041028205333786", "7302041028205333786", "af499ef2d522dda0857f2be9c7db00d0", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
晚晴 = Effect_meta("晚晴", True, "7297143895408839947", "7297143895408839947", "987e48eb485c58a239d5d67d01b9c76a", [])
晚樱 = Effect_meta("晚樱", True, "7127609541839129886", "7127609541839129886", "c30e126bfe5accdb5902c5ba63c8579e", [])
晚霞 = Effect_meta("晚霞", True, "7278616055470165285", "7278616055470165285", "4964c30b3df8eb4cca5831bffa864ecb", [])
晚霞增色 = Effect_meta("晚霞增色", True, "7392898170524618023", "7392898170524618023", "ed6efd67ec78c21a530046b4a6cfbb66", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
普林斯顿 = Effect_meta("普林斯顿", True, "7127615578705104135", "7127615578705104135", "ab9e14d92af596b94e91fd6253b510cd", [])
晴冬 = Effect_meta("晴冬", True, "7307159401838726441", "7307159401838726441", "d8264137bd37822e87e482593926f0a6", [])
晴好 = Effect_meta("晴好", True, "7281163707227344189", "7281163707227344189", "8ab42295fd5c3f9671dc860cab4cf822", [])
晴好假日 = Effect_meta("晴好假日", True, "7374709776623635724", "7374709776623635724", "9747e32d2ec1f251aee54d080ec5fc84", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
晴春 = Effect_meta("晴春", True, "7346542846863887635", "7346542846863887635", "ed510f73b526d21d1fcabfc410f664b8", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
晴空 = Effect_meta("晴空", True, "7127558139058179342", "7127558139058179342", "5b5899ce01e0aac5b8f15a2f77c4ee62", [])
晴肤 = Effect_meta("晴肤", True, "7365842976691604763", "7365842976691604763", "c3d640b01c7bb7f6ab7ebd598bf92811", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
晶透 = Effect_meta("晶透", True, "7199095242476293435", "7199095242476293435", "17e30bbde014d6688a3b00203a7a8ea8", [])
暖冬 = Effect_meta("暖冬", True, "7171607744900877600", "7171607744900877600", "ebfd26418a2c446b0d9a03d43b6c1f09", [])
暖晨 = Effect_meta("暖晨", True, "7312646382395936010", "7312646382395936010", "03737fce45a4ba22d225edbe7e36a04c", [])
暖黄 = Effect_meta("暖黄", True, "7127830631601458440", "7127830631601458440", "7c7c4a40d7c44698a9db145eb8260156", [])
暗匣 = Effect_meta("暗匣", True, "7159163878822153483", "7159163878822153483", "00729c25c8b262db946bb5ac80b8d1dc", [])
暗夜明肤 = Effect_meta("暗夜明肤", True, "7328364126449765671", "7328364126449765671", "9fe0da0817604428adb38249ecae911c", [])
暗影 = Effect_meta("暗影", True, "7291203298630159676", "7291203298630159676", "21f3af497daf847e50efadc241f88a1a", [])
暗曛 = Effect_meta("暗曛", True, "7281163501047991608", "7281163501047991608", "893d483cd405343c9420015066e56096", [])
暗银 = Effect_meta("暗银", True, "7177725752513793284", "7177725752513793284", "ad378d530ac056cb2b2e0b0ab171ede8", [])
暗银II = Effect_meta("暗银II", True, "7223630575888780602", "7223630575888780602", "33f209efb496924d6da0c7ad89bea81f", [])
暮川 = Effect_meta("暮川", True, "7262351934785408267", "7262351934785408267", "187450ba96a5e11233e9d38396274d87", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
暮色约会 = Effect_meta("暮色约会", True, "7332396398157090089", "7332396398157090089", "920f4d54eb383be7327d76689d96f1a5", [])
月吟 = Effect_meta("月吟", True, "7168108694285159719", "7168108694285159719", "98ee4013998d056bf434a4d2c62cf548", [])
# 月吟 = Effect_meta("月吟", True, "7132787977171766539", "7132787977171766539", "465157acdab059cfa20046ba607ae618", [])
松绿 = Effect_meta("松绿", True, "7246723559047941433", "7246723559047941433", "1aca4ded18b11bff899309955ed07c5c", [])
果酥 = Effect_meta("果酥", True, "7160594387594972446", "7160594387594972446", "f68ff633bab02132880a03034894d378", [])
柔焦 = Effect_meta("柔焦", True, "7345412316621442354", "7345412316621442354", "e9449745f95a354e4d835961cbb0e674", [])
柔绀 = Effect_meta("柔绀", True, "7189592131118320954", "7189592131118320954", "ab2c4bebda2329ec36efd65b725a37cb", [])
栩栩 = Effect_meta("栩栩", True, "7177259623819316519", "7177259623819316519", "09c34a30d79f4c7332267b16eaca664e", [])
格金 = Effect_meta("格金", True, "7348301778909252879", "7348301778909252879", "256144ddabaf723badea240301660868", [])
桃木 = Effect_meta("桃木", True, "7252673818035064124", "7252673818035064124", "7e5d4fb53f764eaa07d6e465fd60588e", [])
桃粉 = Effect_meta("桃粉", True, "7297131749346135331", "7297131749346135331", "80b55b69c2b4662c65835f49ee46ad97", [])
桐影 = Effect_meta("桐影", True, "7275699191253339455", "7275699191253339455", "b77671ede2639384b704eb73722e928a", [])
梦境 = Effect_meta("梦境", True, "7127675251604917517", "7127675251604917517", "12627ad5e79adab77540c65ea8ee7cc2", [])
梦幻雪乡 = Effect_meta("梦幻雪乡", True, "7328364320276876598", "7328364320276876598", "e39ddb22d6d8da4f2dea3f9025c0f92f", [])
梦核紫 = Effect_meta("梦核紫", True, "7261463763344248103", "7261463763344248103", "41ed7e729f06a288363ca93a928f8a90", [])
棕榈 = Effect_meta("棕榈", True, "7252676190073392444", "7252676190073392444", "113b463fa3945ef37700c7c52dfc6bb9", [])
森山 = Effect_meta("森山", True, "7242215081663008056", "7242215081663008056", "0dc17be521cf783590bebcf2a5c888df", [])
森秋 = Effect_meta("森秋", True, "7274575376095923497", "7274575376095923497", "b055e64a58bd8d9b882477c9be6ef3a6", [])
榄白 = Effect_meta("榄白", True, "7169350167903112451", "7169350167903112451", "6068c4a2ea7f0854027347a938115dae", [])
橙蓝 = Effect_meta("橙蓝", True, "7127561047048850718", "7127561047048850718", "4dd590015f2e14265dd5456a91ec86a6", [])
殷粉 = Effect_meta("殷粉", True, "7169357894868061478", "7169357894868061478", "91d27d5647faec40a747359ec6dd6eb4", [])
沙砾 = Effect_meta("沙砾", True, "7160580722774920461", "7160580722774920461", "a796471629be7b3bfbd649deafca3ddb", [])
法餐 = Effect_meta("法餐", True, "7127655700532186398", "7127655700532186398", "b8b6d5ae88e12e25be14a2dd85b7cbc6", [])
浅茶 = Effect_meta("浅茶", True, "7221481120083283257", "7221481120083283257", "6acf81ddf75fc8c5ddb20f3a927dcaa3", [])
浅草 = Effect_meta("浅草", True, "7195783041376111932", "7195783041376111932", "8c4eb75992a7f07bd07e56c16b388d87", [])
润光 = Effect_meta("润光", True, "7199093300526173501", "7199093300526173501", "3916e1d5dc3a3522f4b883c3b1f2b43a", [])
润白 = Effect_meta("润白", True, "7366518614729493799", "7366518614729493799", "1686ce704f4899b9e9a1e42693f24037", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
淡奶油 = Effect_meta("淡奶油", True, "7127668617101020423", "7127668617101020423", "e53103dabd1bbb6ab4481b18a4c42b2c", [])
清新润颜 = Effect_meta("清新润颜", True, "7383551596023663882", "7383551596023663882", "738937971c198e9952e91f08adaa8227", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
清晰ll = Effect_meta("清晰ll", True, "7127669764792634637", "7127669764792634637", "7b2ad7edaed946467ab161d016cfca93", [])
清爽 = Effect_meta("清爽", True, "7392897785755897100", "7392897785755897100", "c012321a086ec42b7570338f557a713e", [])
漠土 = Effect_meta("漠土", True, "7347670931646549282", "7347670931646549282", "9dfde36f1fab0e85773d04fadeb30650", [])
# 漫夏 = Effect_meta("漫夏", True, "7210756366317686054", "7210756366317686054", "9517c7a5e9f82a3964dd3967a2b6273f", [])
漫樱 = Effect_meta("漫樱", True, "7356883843376221475", "7356883843376221475", "1799ab3b4a9bf0957995b69d27195229", [])
漫空 = Effect_meta("漫空", True, "7210749292888280359", "7210749292888280359", "cd88f8152fffe8033bb5057fc2539319", [])
漫荫 = Effect_meta("漫荫", True, "7210758351595048195", "7210758351595048195", "fc46efdc25a15ca3958126a8c72c1cd8", [])
漱石 = Effect_meta("漱石", True, "7145394477249678606", "7145394477249678606", "ac50156682af7d7ce4e76eb731a5a832", [])
潘多拉 = Effect_meta("潘多拉", True, "7127620215290039566", "7127620215290039566", "36e7d537966ee59eb61c326598546cb0", [])
灯会 = Effect_meta("灯会", True, "7145394908608662814", "7145394908608662814", "21472133401674a3e5645f79e9d30ae9", [])
灰麻 = Effect_meta("灰麻", True, "7312645421271158070", "7312645421271158070", "38ff7fc68c3ad9d76d9527a6d0b560cb", [])
炊烟 = Effect_meta("炊烟", True, "7194083900333755704", "7194083900333755704", "924d2235bf0485217a6897fb9504b456", [])
烈空 = Effect_meta("烈空", True, "7246722333010824508", "7246722333010824508", "849e979a487594a0da039ddd33e43c6b", [])
烘挞 = Effect_meta("烘挞", True, "7160598329817091364", "7160598329817091364", "8df6f056381a16178b36fa8ad6e559bf", [])
烟橙 = Effect_meta("烟橙", True, "7131582482608164132", "7131582482608164132", "e958619538087c86308f718045b292f2", [])
烟花璀璨 = Effect_meta("烟花璀璨", True, "7328363415313993001", "7328363415313993001", "0d2282c9172ed09758f861849916ab4b", [])
热带季风 = Effect_meta("热带季风", True, "7377368986276646171", "7377368986276646171", "2879146129f3375e8fefc940fe970397", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
焕肤 = Effect_meta("焕肤", True, "7127674287238008078", "7127674287238008078", "073940956259c1077acaec764f52f31c", [])
焰色 = Effect_meta("焰色", True, "7131539023817936158", "7131539023817936158", "a5496033c5eac6ada1c761f1f5e6fcd0", [])
爱之城 = Effect_meta("爱之城", True, "7131656881805741325", "7131656881805741325", "3531cd81550d23dd7d10b4b8ec90ba9f", [])
爱之城II = Effect_meta("爱之城II", True, "7337929076042222899", "7337929076042222899", "1635b6718619a9832177e25c33f1968b", [])
牙白 = Effect_meta("牙白", True, "7172285234296278309", "7172285234296278309", "1c6bd0a57d892c86c845666b44a8f547", [])
牧野 = Effect_meta("牧野", True, "7194090104317594938", "7194090104317594938", "aa1bf1455ec02e406df6821e6bb3c4f8", [])
独行侠 = Effect_meta("独行侠", True, "7202485617026977056", "7202485617026977056", "50fc4f48bab6acc0b86f42c68a44e3dc", [])
玩趣 = Effect_meta("玩趣", True, "7177267248753610023", "7177267248753610023", "3dd9c3beaf276b96f226c49ac2bcbdd0", [])
琥珀 = Effect_meta("琥珀", True, "7295599414180138250", "7295599414180138250", "4a9ef682fbe7b4214e681796d4b4c77d", [])
画报 = Effect_meta("画报", True, "7239979137404833083", "7239979137404833083", "267ef83e978e1b8282afa81c88e8dfd4", [])
登高 = Effect_meta("登高", True, "7195925533031435558", "7195925533031435558", "688df92b416581b9cf33e543ae7ae03b", [])
白富美 = Effect_meta("白富美", True, "7302336985513970963", "7302336985513970963", "9fb4286e708d3bbf2b6bc6af85120be2", [])
白桃 = Effect_meta("白桃", True, "7300522962937990415", "7300522962937990415", "2c277b4b642fa2a5d7ddd7bff681ff91", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
白色恋人 = Effect_meta("白色恋人", True, "7307158934735883583", "7307158934735883583", "6f7d0dd5f3463b557ed59b993303603d", [])
百川 = Effect_meta("百川", True, "7210616269597314362", "7210616269597314362", "cd1f1360bd1891f9b31c63542689d8ea", [])
皓影 = Effect_meta("皓影", True, "7303917567058414911", "7303917567058414911", "13892bfe5e6f6b0c0283a4d3e9034778", [])
盐系 = Effect_meta("盐系", True, "7127823742830398757", "7127823742830398757", "9d48681f2c1f584e9b93fa37485693d1", [])
石山 = Effect_meta("石山", True, "7194091413728922941", "7194091413728922941", "a9faf4808c5ec06b8d2ecc944a3682c6", [])
砂金 = Effect_meta("砂金", True, "7131655685321821477", "7131655685321821477", "28c53cc31c04a9a1e714c3c18038af09", [])
破晓 = Effect_meta("破晓", True, "7348707347419712794", "7348707347419712794", "0f73c6cf0189f4c0e462e76102e46084", [])
硬朗 = Effect_meta("硬朗", True, "7127663097162075399", "7127663097162075399", "7f33d22c16b09c852f48314404c2b532", [])
碳烤 = Effect_meta("碳烤", True, "7363537225620983067", "7363537225620983067", "596d7d07b942eff22e9f8aaa47918711", [])
私语 = Effect_meta("私语", True, "7127674303306419464", "7127674303306419464", "7f8596dc2626cd91e642c6a17c953390", [])
秋池 = Effect_meta("秋池", True, "7145391965717253406", "7145391965717253406", "3a908de0c7ba051b7838f5515d523a2c", [])
秋波 = Effect_meta("秋波", True, "7196920471043050812", "7196920471043050812", "0ce8c8224ab832699cae7ebdbd7034e9", [])
简餐 = Effect_meta("简餐", True, "7127561998556073247", "7127561998556073247", "0c4b5c50cb8bd668c241a262984f940b", [])
粉橘 = Effect_meta("粉橘", True, "7131467442789846285", "7131467442789846285", "30b24cc05d8768de3943d9323af8dc2e", [])
粉白 = Effect_meta("粉白", True, "7156647258342034702", "7156647258342034702", "e852a972957c3dadc478d3215639e0e1", [])
素净 = Effect_meta("素净", True, "7351018816215764233", "7351018816215764233", "3c792ad3327a3b6774aa89990dacf093", [])
素简 = Effect_meta("素简", True, "7300968790391606567", "7300968790391606567", "091f103fae7c3a0480f05be172a0c904", [])
素银 = Effect_meta("素银", True, "7307158197675117863", "7307158197675117863", "fca7c6917f26482a6453ffba5fd167c2", [])
繁花似锦 = Effect_meta("繁花似锦", True, "7322666518536359204", "7322666518536359204", "f5d1f324f0f06bf4fc783095efd7dc1e", [])
繁花如梦 = Effect_meta("繁花如梦", True, "7322665314980859177", "7322665314980859177", "d8bcaf063ca3ef2cd8d5f1642204a35f", [])
繁花璀璨 = Effect_meta("繁花璀璨", True, "7322665617373351231", "7322665617373351231", "98b0d8c15909c10ef71f187df3e36c9f", [])
红运 = Effect_meta("红运", True, "7325421708809096467", "7325421708809096467", "31a7c3905e75dda75c86e104dcb5d222", [])
纱雾 = Effect_meta("纱雾", True, "7260772961462799627", "7260772961462799627", "acde0ae9bd3ee0a6684457d562f35e25", [])
美拉德 = Effect_meta("美拉德", True, "7273782607257685309", "7273782607257685309", "f22f3b6e1ef2d6f6e5b7a9e3b753fe18", [])
美高 = Effect_meta("美高", True, "7239236880858877217", "7239236880858877217", "29446ccd642910767b50978b2fe45f4b", [])
羽梦 = Effect_meta("羽梦", True, "7213573482850880827", "7213573482850880827", "ee8c5d6e7808f4e6662d42298104b87b", [])
聚焦 = Effect_meta("聚焦", True, "7320428711487098153", "7320428711487098153", "54fcd82f212e40df18ac882bd748f59c", [])
艾丽莎 = Effect_meta("艾丽莎", True, "7269240546810400011", "7269240546810400011", "720b5b57295f927d983152d9bffcf33c", [])
花间 = Effect_meta("花间", True, "7211008985187487036", "7211008985187487036", "6acce0fe02d2e0328e597abcb1043de3", [])
花间II = Effect_meta("花间II", True, "7356877435184450851", "7356877435184450851", "78e26d36522db19bd16b83f52ae81593", [])
花食 = Effect_meta("花食", True, "7261180740283403578", "7261180740283403578", "37b2683488f5e586c98256dab864ab84", [])
苍橘 = Effect_meta("苍橘", True, "7131605817958075685", "7131605817958075685", "43666fcf1f38cb2036f87b7e496ccec4", [])
茶酪 = Effect_meta("茶酪", True, "7160603159486827783", "7160603159486827783", "3115e57bcd131acf89d8bdef6cd11cbd", [])
莫吉托 = Effect_meta("莫吉托", True, "7131419324622982408", "7131419324622982408", "c1a69c9148f223e97a862268a91c3e95", [])
落日派对 = Effect_meta("落日派对", True, "7374708995501739305", "7374708995501739305", "e00847299fab64d98f8ae309c62b98aa", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
落日粉 = Effect_meta("落日粉", True, "7368141858603666698", "7368141858603666698", "66dd18db6e7d8f042e7cf8cd02e64af4", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
落日鎏金 = Effect_meta("落日鎏金", True, "7374251948058447158", "7374251948058447158", "f5154a29054db9946d66ed823cb58006", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
蓝梦核 = Effect_meta("蓝梦核", True, "7237440664139484473", "7237440664139484473", "0d12a669f41b3b92d1a892f42b9e0d9b", [])
蓝橙II = Effect_meta("蓝橙II", True, "7337929426493132058", "7337929426493132058", "40056bb94f392bdc1ab305683e265b2b", [])
蓝灰 = Effect_meta("蓝灰", True, "7127667757839076645", "7127667757839076645", "aa8ef49b3edba824d41f097effe534c0", [])
蓝调 = Effect_meta("蓝调", True, "7127664822921022734", "7127664822921022734", "3f0f50b54a2486b3fe5cfbb68dfaeaae", [])
蓝调时刻 = Effect_meta("蓝调时刻", True, "7392898023505792319", "7392898023505792319", "1bcdd5c706e257d4935503a026ee6b20", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
蓝调烟火 = Effect_meta("蓝调烟火", True, "7328363887542209828", "7328363887542209828", "fe2367155cae2d1d5c07c10a64e3b6ef", [])
蓝调舞曲 = Effect_meta("蓝调舞曲", True, "7366562845120646463", "7366562845120646463", "95d43f9239219401b66eae286f0ccc1c", [])
蓝都 = Effect_meta("蓝都", True, "7166470141494955297", "7166470141494955297", "1bd22b8a07bc26b8bbd598414f67a13b", [])
蓝金 = Effect_meta("蓝金", True, "7341300292148907327", "7341300292148907327", "4107fa238d7b56801c9cc3a4a3a15c32", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
裸粉 = Effect_meta("裸粉", True, "7127671519450303775", "7127671519450303775", "cea47ac2c5469b0c7630c2bcd83e3e87", [])
西冷 = Effect_meta("西冷", True, "7131899038625975559", "7131899038625975559", "582a118ed87f8ddfbf2bab6ce6ccbba2", [])
西西里 = Effect_meta("西西里", True, "7131488780451663140", "7131488780451663140", "36c35e9b449bd69a2d186c044c8032c8", [])
西雅图 = Effect_meta("西雅图", True, "7159175960414194982", "7159175960414194982", "d89963be26099b79db297b25e18011a6", [])
诗诺 = Effect_meta("诗诺", True, "7330543523042708790", "7330543523042708790", "ddc9145845f6f5548aba0c4f5ceb76ed", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
象牙白 = Effect_meta("象牙白", True, "7234799040184012092", "7234799040184012092", "f73f4e38a3028c844f4a3d87cfe5d30b", [])
贝果 = Effect_meta("贝果", True, "7131656881805856013", "7131656881805856013", "21f8c68e7dd3fe22071ed06d21cc328a", [])
赏味 = Effect_meta("赏味", True, "7127608379056459015", "7127608379056459015", "d29bc8b2ddd9d018da1309ba9a467517", [])
赤墙 = Effect_meta("赤墙", True, "7226238039155150139", "7226238039155150139", "13130d2c72bde7a34001d2ff74ea9ac1", [])
超白 = Effect_meta("超白", True, "7302338645938261287", "7302338645938261287", "08f7a0eb8cd3535a23b4360acc4cc2f0", [])
越岭 = Effect_meta("越岭", True, "7193989203930123554", "7193989203930123554", "80634d76c41bb167ee4c2bec4172235b", [])
越野 = Effect_meta("越野", True, "7195931118166609190", "7195931118166609190", "f8f340ecb359e2dd7f155da84b06f013", [])
过期电影卷 = Effect_meta("过期电影卷", True, "7361791960652238143", "7361791960652238143", "7b98e4262666c36aeb965842cd14d10a", [])
迷幻 = Effect_meta("迷幻", True, "7233731748545203493", "7233731748545203493", "6eb7969f4e1becb256c90950b3cb8eb3", [])
迷雾 = Effect_meta("迷雾", True, "7160594413847203085", "7160594413847203085", "5143fc0b35bca33c7b010458ffe8f1d7", [])
逆光提亮 = Effect_meta("逆光提亮", True, "7366260047401323811", "7366260047401323811", "8990c9bac399f2eaedfd706d99dbdd4e", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
透亮 = Effect_meta("透亮", True, "7127620232104955150", "7127620232104955150", "62319c31caf875d0041e0bfa50d1b9d7", [])
邂逅 = Effect_meta("邂逅", True, "7271145889119440147", "7271145889119440147", "6b6957bc110b65e03bc5d9ae65de6d66", [])
郁金香 = Effect_meta("郁金香", True, "7343831195924303123", "7343831195924303123", "15e11e4352b9891fd1a1969ff7841b6b", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
都卡 = Effect_meta("都卡", True, "7341296364598480178", "7341296364598480178", "fac476280a61adbc7a731a9ee538b0b1", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
都市 = Effect_meta("都市", True, "7312646683672825100", "7312646683672825100", "486a70b4dc6b3cbedf1ad34461022d78", [])
酚蓝 = Effect_meta("酚蓝", True, "7131322091839753502", "7131322091839753502", "483ca6c547361c0868c8922cebebd893", [])
醒春 = Effect_meta("醒春", True, "7211006465358843196", "7211006465358843196", "3544111511d3c365e3068023059ed83e", [])
里昂 = Effect_meta("里昂", True, "7131643870714006821", "7131643870714006821", "634a11a0d1a1b69aa4ac2770aa47c7dc", [])
野趣 = Effect_meta("野趣", True, "7193983160231742772", "7193983160231742772", "dc9a0e3b25c1b462e5c684ac64bbb1b7", [])
金喜 = Effect_meta("金喜", True, "7323022101735083315", "7323022101735083315", "184ae43f227bd4d20edab495a6574610", [])
金姜 = Effect_meta("金姜", True, "7233733326517832995", "7233733326517832995", "5116f63c46a435d34ccb83fd58b3d009", [])
金色韶华 = Effect_meta("金色韶华", True, "7376141023656873254", "7376141023656873254", "6fe8d7f355b0895a9b4bd4110d7f58d4", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
银蓝 = Effect_meta("银蓝", True, "7145394266209127694", "7145394266209127694", "e1f2f32043ab9fd801bfdbc9a9f708d3", [])
镜粉 = Effect_meta("镜粉", True, "7145390299370638600", "7145390299370638600", "26b6e129d49359d3112438c001f22926", [])
闪星 = Effect_meta("闪星", True, "7346450662185569555", "7346450662185569555", "f9bdd96e9282b3783dcc174484aa5fc6", [])
阳光肤 = Effect_meta("阳光肤", True, "7234795543178775868", "7234795543178775868", "116a1adcf464b736d76bf31d679b3d72", [])
陶瓷肌 = Effect_meta("陶瓷肌", True, "7234793127867878712", "7234793127867878712", "e7b66853ca5dbdb1c049d45225b355cb", [])
随性 = Effect_meta("随性", True, "7271140658071588132", "7271140658071588132", "6619560c233df84381e8c371b7387faa", [])
雨空 = Effect_meta("雨空", True, "7196917591909109052", "7196917591909109052", "ffe686005136a692517b6e19e4e490e7", [])
雪挞 = Effect_meta("雪挞", True, "7262376135202327871", "7262376135202327871", "319cab31ed6a056c3f5256a357eb9b96", [])
雪肤 = Effect_meta("雪肤", True, "7307211406590364955", "7307211406590364955", "03a6b1da7a8fac8dbab32754d9d6655d", [])
雾都 = Effect_meta("雾都", True, "7312646650202262820", "7312646650202262820", "00b8522f76bf9a991e0a6090f63747ee", [])
雾野 = Effect_meta("雾野", True, "7127823362356727077", "7127823362356727077", "6fbd00682d2a15e079bc242301e9b757", [])
青提 = Effect_meta("青提", True, "7131290518838938887", "7131290518838938887", "8ddee3f2a95239705898ac4892cdc803", [])
青灰 = Effect_meta("青灰", True, "7127671508264078599", "7127671508264078599", "a9b480c9b5bf91d2aa0b5e8388f53746", [])
青蒲 = Effect_meta("青蒲", True, "7145393992673414407", "7145393992673414407", "7cd919e92b66b19e00c95b9f3db9def8", [])
青黄 = Effect_meta("青黄", True, "7127541821332409630", "7127541821332409630", "e777bf266933df88bfc019a84e6dd792", [])
青黄II = Effect_meta("青黄II", True, "7337932621046910262", "7337932621046910262", "059b7e40c1fe52a2451c35bd82e329e5", [])
风味 = Effect_meta("风味", True, "7330579916272012580", "7330579916272012580", "7abbb099b234e92b6a7169f2ae6232b6", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
风铃II = Effect_meta("风铃II", True, "7356885346841349410", "7356885346841349410", "7e36a3f345976371e7a668d1e96c7905", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
风铃蓝 = Effect_meta("风铃蓝", True, "7261466919688015140", "7261466919688015140", "5bf0d1478c19629df96ad85b3301ec35", [])
飒意 = Effect_meta("飒意", True, "7248568718265978112", "7248568718265978112", "25a705fe908fad028d75a5b9bf30e4b7", [])
食色 = Effect_meta("食色", True, "7131644140340776205", "7131644140340776205", "8540ba0ddb988c6f5f4b69742ca94136", [])
香浓 = Effect_meta("香浓", True, "7330588808666156307", "7330588808666156307", "480c2599aaaf7be5a800c269dada7cdd", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
驮月 = Effect_meta("驮月", True, "7145394213339860261", "7145394213339860261", "ba8a3a6272282d63ee8b46c2e228e09b", [])
高清 = Effect_meta("高清", True, "7320436048134147340", "7320436048134147340", "a33cc5e4879a6f4d03e2f4f7535c96b2", [])
高清II = Effect_meta("高清II", True, "7325426821267295551", "7325426821267295551", "17a86357c081e0d080c9d501a66382d0", [])
魅影 = Effect_meta("魅影", True, "7175076304058895619", "7175076304058895619", "361328c4bc995c85053ea003268aefbf", [])
魔都 = Effect_meta("魔都", True, "7166480345666260263", "7166480345666260263", "cf4adfafcc5e59b9bddd8eeb4d20f44e", [])
鲜亮 = Effect_meta("鲜亮", True, "7127615338035858702", "7127615338035858702", "329252a715f5e0f9727810511e0e9832", [])
鲜明 = Effect_meta("鲜明", True, "7320434750018047251", "7320434750018047251", "ba8b7cbf504c97a30c923d0d6a6c2b44", [])
鲜明II = Effect_meta("鲜明II", True, "7361400073533820196", "7361400073533820196", "350ff543fdd150a6f7e571aa3f467640", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
鲜美 = Effect_meta("鲜美", True, "7330581892510649636", "7330581892510649636", "0f2146e69f0cf22a0e0aa733be623bd4", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
黄昏 = Effect_meta("黄昏", True, "7272330168717430075", "7272330168717430075", "eebcc8f84ff895bd0d66535d9ad44275", [])
黑冰 = Effect_meta("黑冰", True, "7131522303082466597", "7131522303082466597", "d03c03e8f1e67f5cff0a5671fe96dfb9", [])
黑曜 = Effect_meta("黑曜", True, "7223712396769119545", "7223712396769119545", "3b81efb578ddec8efa40dd0c5b754056", [])
黑金 = Effect_meta("黑金", True, "7127670164996295972", "7127670164996295972", "bfd8bd193bf24f5de2bd719516ef230d", [])
黑金红 = Effect_meta("黑金红", True, "7341266486536768831", "7341266486536768831", "66796ec5de5e85b2cf461fa49b4c0225", [
Effect_param("effects_adjust_filter", 1.000, 0.000, 1.000)])
"""滤镜强度可调"""
龙舌兰 = Effect_meta("龙舌兰", True, "7252674245396942139", "7252674245396942139", "254083154fd15d41d41cc3763eda9f40", [])
-341
View File
@@ -1,341 +0,0 @@
"""记录剪映的字体元数据, 此文件的内容主要由程序生成"""
from .effect_meta import Effect_enum
from .effect_meta import Effect_meta
class Font_type(Effect_enum):
CC_Captial = Effect_meta("CC-Captial", True, "7418508570066424330", "84086581", "8ba811d327acd1516615259819da72a2")
CC_Moderno = Effect_meta("CC-Moderno", True, "7444152681741947403", "94915234", "3bd5f42349aa8b0d3d211b6d2a6c31d4")
JYruantang = Effect_meta("JYruantang", True, "7451897289527792178", "98222876", "af78243f78f27dfa80aca4e82c77eb1d")
JYshiduo = Effect_meta("JYshiduo", True, "7451897058371310117", "98222874", "24fdaeb998c36d329b423561398ba4e3")
JYzhuqingting = Effect_meta("JYzhuqingting", True, "7451897479320048166", "98222875", "921ba2b753807a5fb0d56a967225a352")
Merry_Christmas = Effect_meta("Merry Christmas", True, "7451574186692055578", "98103035", "2a8b0f3ec8be1bde50969620603553af")
MyFont凌渡哥哥简 = Effect_meta("MyFont凌渡哥哥简", True, "7316825302406009395", "36880890", "cc22c869da3e5aecae2c1ffaf27d3eda")
ZY_Balloonbillow = Effect_meta("ZY Balloonbillow", True, "7353574360667394561", "55106512", "f6405bfdefb032ab060c05d9a1a7038a")
ZY_Blossom = Effect_meta("ZY Blossom", True, "7304640684311450113", "30910322", "0435212aa54de0bbd8797b877eed75b4")
ZY_Brief = Effect_meta("ZY Brief", True, "7311977774799917570", "34200651", "85952d2387016574cb2630d7f6760f4a")
ZY_Courage = Effect_meta("ZY Courage", True, "7304640798488793602", "30910326", "902c396d8481367784495d73620b1a90")
ZY_Daisy = Effect_meta("ZY Daisy", True, "7302355415038169601", "30000858", "5694276489bf9e70db025e6f19277508")
ZY_Elixir = Effect_meta("ZY Elixir", True, "7302355533313348097", "30000844", "ebd4e8ef85eacc25860cd9c4c7d63d72")
ZY_Fabulous = Effect_meta("ZY Fabulous", True, "7302355634538680833", "30000832", "2f673e5e2e8d956e6a0c6d8b28203d05")
ZY_Fantasy = Effect_meta("ZY Fantasy", True, "7350189137770582529", "53177510", "09af030c4b206c3b895502f715c80d79")
ZY_Flourishing_Italic= Effect_meta("ZY Flourishing-Italic", True, "7330606083335000577", "43287756", "dca57209a301d9119b911bff090262a8")
ZY_Fortitude = Effect_meta("ZY Fortitude", True, "7330160852353421825", "43041469", "2db56cf21059b8a0c192f801555df245")
ZY_Kindly_Breeze = Effect_meta("ZY Kindly Breeze", True, "7407289076090409489", "80464440", "a4e22dd23bf2aa6ae8ceda12400eb900")
ZY_Loyalty = Effect_meta("ZY Loyalty", True, "7371704099433091600", "66322554", "1e9b242443a9943a43ccf30604243978")
ZY_Modern = Effect_meta("ZY Modern", True, "7347670651626328577", "51844020", "5f5649ec5cd96f1311271d7f84e6151b")
ZY_Multiplicity = Effect_meta("ZY Multiplicity", True, "7371704261878485521", "66322523", "f9714cd361ad6ddb6ee5b255d1e8ee21")
ZY_Panacea = Effect_meta("ZY Panacea", True, "7302355742936273410", "30000850", "dc33e6efcf20202d53ab1818c50216e2")
ZY_Relax = Effect_meta("ZY Relax", True, "7311977487469122049", "34200615", "4ac466f1249ffceb8ef9b6f366d42384")
ZY_Slender = Effect_meta("ZY Slender", True, "7311977578821063170", "34200655", "bd7e086e303630912f12c4b75f93d139")
ZY_Spunk = Effect_meta("ZY Spunk", True, "7304640886703395329", "30910324", "8942384a7e78d2be8b650b0791afdd56")
ZY_Squiggle = Effect_meta("ZY Squiggle", True, "7371704357009494529", "66322535", "7b461311c3dae5726d9768969ff26ecf")
ZY_Starry = Effect_meta("ZY Starry", True, "7304640983893807618", "31942077", "8558a845c7f82bf81e5b27c654b413e2")
ZY_Timing = Effect_meta("ZY Timing", True, "7304641084833927682", "30910320", "95032638412a83a08c311a83bbcc85bb")
ZY_Trend = Effect_meta("ZY Trend", True, "7347670845185069569", "51844010", "0f62f8bfab9d76a74dc281c7f248ac23")
ZYLAA_Demure = Effect_meta("ZYLAA Demure", True, "7313895257991549442", "35459490", "ce4f98f6b9b57daa44336c2489eff940")
Amigate = Effect_meta("Amigate", False, "7042231710112551431", "1485328", "1496029e87060f4208d5fbc127ed5f2c")
Anson = Effect_meta("Anson", False, "7312373886476096001", "37083210", "1f6c4b124f1cc0c8dc64e9a8d5d5db1c")
BlackMango_Black = Effect_meta("BlackMango-Black", False, "7306445059216380417", "41472089", "8fe0a5dfb979cfff2e326617c543b4ab")
BlackMango_Regular = Effect_meta("BlackMango-Regular", False, "7306445155244970497", "41472093", "8f91492140c961395923bc1edd9abae8")
Bungee_Regular = Effect_meta("Bungee-Regular", False, "7314592672792973826", "37039650", "26f72c42742cd487ebafebfa8bc45c4f")
Cabin_Rg = Effect_meta("Cabin-Rg", False, "7314592369867756034", "37039690", "05fa78c9e0cb4de012ad8f4ca7cf589f")
Caveat_Regular = Effect_meta("Caveat-Regular", False, "7277872672304796217", "22621892", "2ad4a79314b4fe122e8ff7599133cf4a")
Climate = Effect_meta("Climate", False, "7080115867823903246", "1654361", "4ef55e67791e1386833d55964cce115d")
Coiny_Regular = Effect_meta("Coiny-Regular", False, "7203293403990200834", "27240316", "027b0038d0184ca86288c22298b82600")
DMSans_BoldItalic = Effect_meta("DMSans-BoldItalic", False, "7314592197238592002", "37039676", "5a490fc0c878dbecc7233de1dc7decae")
Exo = Effect_meta("Exo", False, "7003588519440421413", "1349503", "c7861a7748efe6c7f69b2d864881eeb3")
Gallery = Effect_meta("Gallery", False, "7030677248797577765", "1441466", "c6c8e230a16440a4df49ae96893c8211")
Giveny = Effect_meta("Giveny", False, "7030676531156357645", "1441468", "7499748cd12c31b8e3e5c30fb7184a54")
Grandstander_Regular= Effect_meta("Grandstander-Regular", False, "7277873129915945509", "22621895", "216f5b3c84a59d4e87860c9ff9f562bd")
Gratefulness = Effect_meta("Gratefulness", False, "7290877195218588216", "26148240", "7ebf75e53a99790894af0e35a8752103")
HarmonyOS_Sans_SC_Bold= Effect_meta("HarmonyOS_Sans_SC_Bold", False, "7265594890002633272", "20374146", "43f72102bcc9cf55d485857e81a4b1d0")
HarmonyOS_Sans_SC_Medium= Effect_meta("HarmonyOS_Sans_SC_Medium", False, "7265595177916437050", "20374140", "b6636326c0e4bd6b7d163210313e36b1")
HarmonyOS_Sans_SC_Regular= Effect_meta("HarmonyOS_Sans_SC_Regular", False, "7265595305163231781", "20374142", "ae33e48fc99aa4c8bdf259ec8aa7b768")
HarmonyOS_Sans_TC_Bold= Effect_meta("HarmonyOS_Sans_TC_Bold", False, "7265530043495879226", "20356569", "ed1b8e7841ccba0c1a530d4d975a3651")
HarmonyOS_Sans_TC_Light= Effect_meta("HarmonyOS_Sans_TC_Light", False, "7265530445658329661", "20356571", "f43d72b12b7ac433a6b9efd13b00e44c")
HarmonyOS_Sans_TC_Medium= Effect_meta("HarmonyOS_Sans_TC_Medium", False, "7265530519687795255", "20356573", "116d59aa44e88bda1c3b4652ccc42bc5")
HarmonyOS_Sans_TC_Regular= Effect_meta("HarmonyOS_Sans_TC_Regular", False, "7265530629050077754", "20356575", "57cdc99508ebf188ee9107f21c558e1d")
HeptaSlab_ExtraBold = Effect_meta("HeptaSlab-ExtraBold", False, "7277873528643260988", "22621893", "5e58c6a212bb55f2bc2080bbd5a37c9b")
HeptaSlab_Light = Effect_meta("HeptaSlab-Light", False, "7277873865001275964", "22621897", "3fd3c1d463fc7ae1918dff1ce91544ae")
Huben = Effect_meta("Huben", False, "7094914692975432206", "1821402", "5b65bd72e11b60b1fdb629f3e91e285a")
Ingram = Effect_meta("Ingram", False, "7094910999198700040", "1821404", "9e70d8f68947dbfc3892cf00387b565e")
Integrity = Effect_meta("Integrity", False, "7290877266458841637", "26148241", "e3273b53a35140c0c07e5a48f5e6ae1f")
Inter_Black = Effect_meta("Inter-Black", False, "7314592567717270018", "37039685", "eb649dd550216792ea32f9f403064787")
Kanit_Black = Effect_meta("Kanit-Black", False, "7341281166273548801", "48512052", "ee7a81d5e88996772c36264aba14d17b")
Kanit_Regular = Effect_meta("Kanit-Regular", False, "7341281459799331330", "48512024", "8c53bab543a483f4aea69870952e15b5")
Koulen_Regular = Effect_meta("Koulen-Regular", False, "7341281656319250945", "48512036", "7b5c8caefbc8f8c2cf6834e65d10c48a")
LXGWWenKai_Bold = Effect_meta("LXGWWenKai-Bold", False, "7265591538472718903", "20373127", "562011555df237de57ff2da20dde5ecc")
LXGWWenKai_Light = Effect_meta("LXGWWenKai-Light", False, "7265592227118715448", "20373111", "302ec5cdf24cd8ed486ffdcfc1431c39")
LXGWWenKai_Regular = Effect_meta("LXGWWenKai-Regular", False, "7265591946897265212", "20373101", "7bac545cc43d16cfc89b681ba37b06e7")
Love = Effect_meta("Love", False, "6766522308593979917", "459276", "a329a038511121412865fa841f51dfc3")
Luxury = Effect_meta("Luxury", False, "7291876268541219329", "41472051", "8b2c690dc8c0a5124b5536aab2915747")
MiSans_Heavy = Effect_meta("MiSans-Heavy", False, "7265595579864977980", "20374145", "2dfa84b84a63cf62ec91e41dafce6f0d")
MiSans_Regular = Effect_meta("MiSans-Regular", False, "7265596106581479991", "20374141", "d1d134c67f9de5c83a18871150a9a2c1")
Modern = Effect_meta("Modern", False, "6740498577912500749", "349479", "3bd3fe9a9464df4555335393bb266aba")
Nunito = Effect_meta("Nunito", False, "6807743644842332685", "643589", "5243915a1b14f5fe467f4d5f10d2ba38")
OldStandardTT_Regular= Effect_meta("OldStandardTT-Regular", False, "7277874282493907512", "22621894", "24b6280d5832d9d6cbfada464f5c5a61")
Pacifico_Regular = Effect_meta("Pacifico-Regular", False, "7312374088477970945", "37083032", "1416d2ec4431154045a8e6eff0df0a52")
PlayfairDisplay_Bold= Effect_meta("PlayfairDisplay-Bold", False, "7314592810684912130", "41472127", "7dc783e1cc6be2ca8bd21a837b7bd0cc")
Plunct = Effect_meta("Plunct", False, "7035916496484176421", "1459552", "ba351b572d684c0f8ea9b7d6cab9f500")
Polly = Effect_meta("Polly", False, "7078971156350374431", "1648730", "02fb23bcda9f281d4029ef482bb3c1fb")
Poppins_Bold = Effect_meta("Poppins-Bold", False, "7312373689708712449", "41472095", "d090413fb1d5672cdf7177fea62fbccd")
Poppins_Regular = Effect_meta("Poppins-Regular", False, "7202912523383738881", "41472101", "62f9677bff07407d954efbb810d8273e")
RedHatDisplay_BoldItalic= Effect_meta("RedHatDisplay-BoldItalic", False, "7341281783637348865", "48512032", "c24c458d3099c3e7f327635326ba78ce")
RedHatDisplay_Light = Effect_meta("RedHatDisplay-Light", False, "7341282109987754497", "48512058", "319e4fda3248900720841a4475234a89")
ResourceHanRoundedCN_Md= Effect_meta("ResourceHanRoundedCN-Md", False, "7265596408491676197", "20374131", "b21249fcbc5e1d96505fdeb21c1f7e8f")
ResourceHanRoundedCN_Nl= Effect_meta("ResourceHanRoundedCN-Nl", False, "7265596514955694649", "20374148", "5df531b829fa804cb520148c5d1e7c85")
Roboto_BlkCn = Effect_meta("Roboto-BlkCn", False, "7316424848622752257", "37039748", "c2d075ff415d9a8d09982c955f59d25f")
SansitaSwashed_Regular= Effect_meta("SansitaSwashed-Regular", False, "7314592065168347650", "37108558", "136c05da10e6016965dccd20b017a0ad")
SecularOne_Regular = Effect_meta("SecularOne-Regular", False, "7312374157725929986", "37082988", "6b3bb5fe24e5b1df5ed82af22a1b45bd")
Signature = Effect_meta("Signature", False, "7042230917837885965", "1485330", "4e29c132141a12bbbffb4a6c5b35bac2")
Soap = Effect_meta("Soap", False, "7076269202771808804", "1632684", "853e5b6b92915f439228d36ae9be0ddf")
Sora_Bold = Effect_meta("Sora-Bold", False, "7341282687497277953", "48511978", "294e57942fb9b6e6a381bab3f04d0227")
Sora_Regular = Effect_meta("Sora-Regular", False, "7341282789431448065", "48512020", "1da0cc77ecfb548eb9b9e0f969585850")
SourceHanSansCN_Bold= Effect_meta("SourceHanSansCN-Bold", False, "7265596643066516029", "20374122", "fb70a3667211b2962782b5a2c127b2a6")
SourceHanSansCN_Light= Effect_meta("SourceHanSansCN-Light", False, "7265596753926165050", "20374126", "1e5cecf2d7f404937e579b691dd824c5")
SourceHanSansCN_Medium= Effect_meta("SourceHanSansCN-Medium", False, "7265596846465094199", "20374144", "6ae9ea8211a7b2df59519cc25bf0e4d3")
SourceHanSansCN_Normal= Effect_meta("SourceHanSansCN-Normal", False, "7265596944867660346", "20374137", "0875520d11130e75a7c55db404269fef")
SourceHanSansCN_Regular= Effect_meta("SourceHanSansCN-Regular", False, "7265597035946971705", "20374128", "ab9425633f936ad3aee8ce6776a8d785")
SourceHanSansTW_Bold= Effect_meta("SourceHanSansTW-Bold", False, "7265530703364756026", "20356585", "068f075fb3e12a9e7d866485e4ec90fd")
SourceHanSansTW_Light= Effect_meta("SourceHanSansTW-Light", False, "7265530900580930085", "20356587", "3c658b896e04038f1e64a7b482c09f2e")
SourceHanSansTW_Medium= Effect_meta("SourceHanSansTW-Medium", False, "7265530989479203389", "20356589", "3db3cffea241e097cfef7bcef2334d90")
SourceHanSansTW_Normal= Effect_meta("SourceHanSansTW-Normal", False, "7265531070680928828", "20356591", "7e3007f207de8eeb029b534fbaf9a13f")
SourceHanSansTW_Regular= Effect_meta("SourceHanSansTW-Regular", False, "7265531198548480568", "20356593", "9a228f45a856db7e2acc9844fe12de42")
SourceHanSerifCN_Light= Effect_meta("SourceHanSerifCN-Light", False, "7265597259708895803", "20374143", "f8733631870deaba746afcb65ef30389")
SourceHanSerifCN_Medium= Effect_meta("SourceHanSerifCN-Medium", False, "7265597365539574329", "20374123", "6b1255756261d5ddb9ac40216ee5a2f0")
SourceHanSerifCN_Regular= Effect_meta("SourceHanSerifCN-Regular", False, "7265597449262076474", "20374152", "47dc066be4a347aa81c347554fa376a9")
SourceHanSerifCN_SemiBold= Effect_meta("SourceHanSerifCN-SemiBold", False, "7265598654294004281", "20374118", "f1b0ad6ceca5ec6bd47b0dacae9fbf97")
SourceHanSerifTW_Bold= Effect_meta("SourceHanSerifTW-Bold", False, "7265534770845585980", "20356595", "7de7afb3383bc3c71064e694a8437fed")
SourceHanSerifTW_Light= Effect_meta("SourceHanSerifTW-Light", False, "7265535017625850429", "20356597", "78bd0a481bca529b29dadce742f93d4b")
SourceHanSerifTW_Medium= Effect_meta("SourceHanSerifTW-Medium", False, "7265535154775396919", "20356599", "13289edc534678e1ac9846ffea550910")
SourceHanSerifTW_Regular= Effect_meta("SourceHanSerifTW-Regular", False, "7265535307322233399", "20356601", "8850278849317c50eefc844c086dd455")
SourceHanSerifTW_SemiBold= Effect_meta("SourceHanSerifTW-SemiBold", False, "7265535436594876984", "20356603", "2420aafb990c49f9266bfd0bd3d79149")
Staatliches_Regular = Effect_meta("Staatliches-Regular", False, "7312373990083793409", "37083204", "eb3e70b0668eb3e03499cd5162bbf8e3")
Sunset = Effect_meta("Sunset", False, "6807743703436759566", "643591", "01365a30a2569e10b160f7bd46e2c8c8")
Thrive = Effect_meta("Thrive", False, "7290877082660246071", "26148239", "09aecfbb88990df392ae7dfa53e56b6e")
Thunder = Effect_meta("Thunder", False, "7050422198724465189", "1511612", "f68ab331feafe5deac4c9484df686557")
Tronica = Effect_meta("Tronica", False, "7094911278426100238", "1821403", "5209e1bc26f3e59c67705c3fea393cbe")
Vintage = Effect_meta("Vintage", False, "6740438522861195789", "349327", "7c7bef7e0d226e4a0913b2d9de0ef06e")
ZY_Dexterous = Effect_meta("ZY Dexterous", False, "7320169657841750529", "38698692", "fadee671a67e0e552e0d61f480e78348")
ZY_Earnest = Effect_meta("ZY Earnest", False, "7322744268987044354", "39631837", "3d30c6b6825b9bdf27e98f24f33092c7")
ZY_Vigorous = Effect_meta("ZY Vigorous", False, "7322372193738822145", "39444804", "124fa2bd07a55bce96ee0224a425d339")
ZY_Vigorous_Medium = Effect_meta("ZY Vigorous-Medium", False, "7324166831881589249", "40250732", "4d3ef21ef574d220ff7a68d14ea296af")
ZYLantastic = Effect_meta("ZYLantastic", False, "7290485139908334138", "26013698", "95ef52f88a61917fdffe9f85a59a7236")
ZYLullaby = Effect_meta("ZYLullaby", False, "7290485359744389691", "26013697", "f731f395b8bc26a30afce30d9d6fd245")
ZYSilhouette = Effect_meta("ZYSilhouette", False, "7290485464341942840", "26013700", "cbb4966830a668ba27de621df533c01e")
ZYWitty = Effect_meta("ZYWitty", False, "7290485545237484069", "26013699", "b7de21c78c00e4715a8b5a1478654131")
Zapfino = Effect_meta("Zapfino", False, "7076271146110292494", "1632681", "efa8ec4bd296ade312a2a64fe6b2d206")
中秀体 = Effect_meta("中秀体", False, "6917512631515353607", "1014410", "9561161c74ae03658e101577ec5cfae6")
今宋体 = Effect_meta("今宋体", False, "7216598549809599032", "11443544", "4bd7448e9ba53dd7fe3bd8b73a07e6f4")
仓耳周珂正大榜书 = Effect_meta("仓耳周珂正大榜书", False, "7265577040110162492", "20373112", "5c78e7cf1982aa68487d1675159b73f6")
优设标题黑 = Effect_meta("优设标题黑", False, "7068207165277737502", "1588336", "d9f1238f50005595eff5f545aa54776c")
俊雅体 = Effect_meta("俊雅体", False, "7078971008769593887", "1648731", "4f96b92a0023d2da2a4c9cb4e09e9565")
元气泡泡体 = Effect_meta("元气泡泡体", False, "7203664981080937021", "9898775", "3af8af39c55aa4109263fd49a00f3885")
元瑶体 = Effect_meta("元瑶体", False, "7290447082886795832", "25999023", "b981cfd05bb12209521b5aeac9d3740f")
先锋体 = Effect_meta("先锋体", False, "7043775345333375519", "1488720", "85da61942dcc96f5eddad1c3826b5f0c")
兰亭圆 = Effect_meta("兰亭圆", False, "7173608955527041567", "6949825", "211a5b4aed3f2ac8412d6f9f7e9d8244")
凌东齐伋体_combo = Effect_meta("凌东齐伋体-combo", False, "7265611544820453948", "20379306", "6ca3f118d0415aa1f0be2e9ee2800890")
凌东齐伋体_fallback = Effect_meta("凌东齐伋体-fallback", False, "7265611310132367931", "20379309", "5717be837d5f541193816ad6b421f7fc")
匹喏曹 = Effect_meta("匹喏曹", False, "7043773350555947551", "1488716", "4f6d74dc7cb2208981569c0842124038")
半梦体 = Effect_meta("半梦体", False, "7290439421625635385", "25999018", "ed70a8440c036e4f95d41ac34846f229")
卡酷体 = Effect_meta("卡酷体", False, "7045187669847970341", "1494864", "514acd68e036f48781d209d84cc7728e")
古典体 = Effect_meta("古典体", False, "7035911487646339598", "1459456", "37cd7f9d7364c200a37c7f9ee2192ae9")
古印宋简 = Effect_meta("古印宋简", False, "7216598368791827002", "11443545", "aafc0b7c13e1c5b790d090e57afcff76")
古雅体 = Effect_meta("古雅体", False, "7025895760583463438", "1425152", "dc99fbcf0d0a7c179313e6289d95ebaf")
古风小楷 = Effect_meta("古风小楷", False, "7216598671016596029", "11443543", "97e1ab8a11b337dc9e8369a40c936e19")
台北黑体_Light = Effect_meta("台北黑体-Light", False, "7265536169083933242", "20356619", "3367383fa78c478b88ab81a18746ee85")
台北黑体_Regular = Effect_meta("台北黑体-Regular", False, "7265536307932172861", "20356621", "640ca1b520ae3f08b77de45dab99ba33")
后现代体 = Effect_meta("后现代体", False, "6740435494053614093", "349307", "35b4b7201d26c9a26a038be8813efdd2")
喜悦体 = Effect_meta("喜悦体", False, "7045187886924173861", "1494856", "71a8ba6a406a0c02fc2a31dceb4921d0")
嘉木体 = Effect_meta("嘉木体", False, "7290443820041245241", "25999016", "a5ac5235fec9d01bbb280ab9b37b7b93")
圆体 = Effect_meta("圆体", False, "6740436583247254029", "349313", "6622f87ce830dd89234522a0d9db5104")
基础像素 = Effect_meta("基础像素", False, "7203638484752405049", "9893377", "f76ecb363595e5321389d3ed29df1c9f")
墩墩体 = Effect_meta("墩墩体", False, "7043772438898807304", "1488712", "377365df3340b4b642a0c199fcbb3882")
大字报 = Effect_meta("大字报", False, "7054126026267300382", "1530068", "bb2f51e267dce8ffd369e1721f2a6371")
大梁体 = Effect_meta("大梁体", False, "7057028912252981791", "1542202", "ceeaca2dfb033c79a261ac9e7950ec72")
妙黑体 = Effect_meta("妙黑体", False, "7203638484756599333", "9893375", "ff39549fdcdf9528ce1d0137384eb906")
字制区喜脉体 = Effect_meta("字制区喜脉体", False, "7391765808835203647", "75248650", "9e6dcd6301144426671b86797a1cfd7a")
孤月体 = Effect_meta("孤月体", False, "7290441418395357754", "25999015", "e48e0b0bf5ff728a46405176e1d5030f")
宋体 = Effect_meta("宋体", False, "6740513279296147982", "349517", "02a4eb96fa9d82bbba5906c35521f6f4")
小薇体 = Effect_meta("小薇体", False, "7265594602311127607", "20373097", "db03f70f2fc5177f552d46ab3648af3f")
尔雅新大黑 = Effect_meta("尔雅新大黑", False, "7217732136894206501", "11593555", "c3dc73e45b7b16cae8e867a0a73f35dd")
峰骨体 = Effect_meta("峰骨体", False, "7054126189211816462", "1530066", "b5a3bb8585981e629732ca53d6d3be36")
幼萱体 = Effect_meta("幼萱体", False, "7290446812442268217", "25998999", "ab1b9e358069f4187427aaecbcca1467")
得意黑 = Effect_meta("得意黑", False, "7399865900821647935", "77844112", "5219d1f012f4944aaaa2ec19556fdea6")
快乐体 = Effect_meta("快乐体", False, "6740499472523989512", "349463", "eff4f43e9bfa0adbe1cc2454ac57e98f")
快速体 = Effect_meta("快速体", False, "7197366121069023804", "9182766", "462692b2efb28f3cf411edbef8f7f6ff")
思源中宋 = Effect_meta("思源中宋", False, "6807743192671195655", "643579", "e8b002bff0884028c9f13a9d6eeb03bc")
思源粗宋 = Effect_meta("思源粗宋", False, "6807742980271641102", "643575", "e4387517f584be39bb2e1ca4ede6cbe3")
悠悠然 = Effect_meta("悠悠然", False, "7081924596999393805", "1665070", "f38c316a2e5f0e059094bbe18a252ce1")
悦妍体 = Effect_meta("悦妍体", False, "7290447167821451813", "25998984", "3c6344b0d77c47511e5b177675761c7b")
惊鸿体 = Effect_meta("惊鸿体", False, "7203638484756599356", "9893376", "d06a0ac2a94160c8e6d88bf6d1c436e6")
抖音美好体 = Effect_meta("抖音美好体", False, "7244518590332801592", "15332487", "1a9c90e65d4ac34436d90a1b19d94d5a")
招牌体 = Effect_meta("招牌体", False, "7035914068053463565", "1459526", "d591f14dd0bf7486dc318195299706a4")
挥墨体 = Effect_meta("挥墨体", False, "7037018943218782757", "1464398", "162b2fc5a67b2f7b664001030b16828a")
文研体 = Effect_meta("文研体", False, "6990293257540342302", "1203468", "bcadf482b4045f8d47bf373fc01479a0")
文艺繁体 = Effect_meta("文艺繁体", False, "6740437797456318983", "349321", "b15dc9e0411a83b2c63f983a2fb3b7a6")
文轩体 = Effect_meta("文轩体", False, "7290445778273702455", "25998976", "d5ea95d6a862335c917a93b4fc741c89")
文雅体 = Effect_meta("文雅体", False, "7068208151488631309", "1588334", "6f0ccd9662b4b0eb41318fd8547699de")
新青年体 = Effect_meta("新青年体", False, "6740435892441190919", "349309", "71a73f7e297831936018c928d61ce2b8")
方糖体 = Effect_meta("方糖体", False, "7037017159280628231", "1464396", "49573e8f5bb7ae96ce913040780803e3")
无界黑 = Effect_meta("无界黑", False, "7203638485670957629", "9893370", "1e04097242afd9dea436e390c2b8d89d")
日式标题 = Effect_meta("日式标题", False, "7081925137355772453", "1665068", "b21c3e5dcee4cbd5aa5606f1e04fe382")
星光体 = Effect_meta("星光体", False, "7216598789103030821", "11443542", "cc578f4ebfa6ec1d814f50b8ab99ce5e")
有猫在 = Effect_meta("有猫在", False, "6766524065151717901", "459290", "0880173b6edb03abadc473b64ec80316")
李李体 = Effect_meta("李李体", False, "7203638484752405053", "9893380", "87985cec317b243b34472455eb35e061")
极简拼音 = Effect_meta("极简拼音", False, "7070430470667768333", "1600484", "d9bd33e2a246c62cfae5b75504c5d7c0")
梅雨煎茶 = Effect_meta("梅雨煎茶", False, "7081925245099053604", "1665067", "7adeea403a9002c92bdb071f07506f5d")
梦桃体 = Effect_meta("梦桃体", False, "7290444545689391653", "25998998", "58f48899950d28f609bef42bcab15575")
楚辰体 = Effect_meta("楚辰体", False, "7070430593925779981", "1600482", "ced7a98a9bcc8984318a2c215192b0c5")
欣然体 = Effect_meta("欣然体", False, "7068531082265629197", "1589146", "f1d3dde1819db78d7f4bde16daf52fe3")
毡笔体 = Effect_meta("毡笔体", False, "7035924520854622757", "1459716", "171016edaee58043c22552d32579f154")
汇文明朝体 = Effect_meta("汇文明朝体", False, "7444913491762221577", "95241741", "dff19164a0e4822b2320a900db9c1c2e")
汉仪英雄体 = Effect_meta("汉仪英雄体", False, "6740499052644798984", "349471", "3f63a7b1ab4699bf11c88b284939e661")
江户招牌 = Effect_meta("江户招牌", False, "7080096840875512334", "1654205", "a98a329c2a52154b6c50b06e66d60b12")
江湖体 = Effect_meta("江湖体", False, "7080097079397192228", "1654203", "50957d5102cb4f2ea1459e140826eb0c")
油漆体 = Effect_meta("油漆体", False, "7035906361040835079", "1459392", "f3f06c4b538c534a498c5e3712a949fa")
海岛森林_全字符 = Effect_meta("海岛森林-全字符", False, "7445240658693984805", "95365506", "91a93794d0970a1acdb8822729ae5965")
清刻本悦 = Effect_meta("清刻本悦", False, "7086429206543864350", "1698068", "2e70579a0538bde91edc1eaedc68c02f")
温柔体 = Effect_meta("温柔体", False, "7050009415155454500", "1511616", "eb4b8ebef19e89895193d930e7c607c1")
港风繁体 = Effect_meta("港风繁体", False, "6740438140432945675", "349323", "9bfde9a789862114b6055ed475688908")
游园体 = Effect_meta("游园体", False, "7290446760739082789", "25998988", "b9e3537ea657978bc1963e76b66312a9")
漫语体 = Effect_meta("漫语体", False, "7081925440264213000", "1665066", "e91bd31939be0dbbcae085a64d151ad6")
点宋体 = Effect_meta("点宋体", False, "7080096967543493150", "1654204", "e5338c6ec760fc059b257d8dc31e7279")
烈金体 = Effect_meta("烈金体", False, "7043773114546655781", "1488714", "dd0bc895570589984077890ab098ef15")
烟波宋 = Effect_meta("烟波宋", False, "7068531367386026526", "1589144", "4ee19f0d46c10ccc70bac084226e6f82")
特黑体 = Effect_meta("特黑体", False, "6740439840254333443", "349329", "92988aefce8a45c8fd7fe58a60fc72cc")
琉璃宋 = Effect_meta("琉璃宋", False, "7020719089999942157", "1402720", "a3bd369495563713486e56b7f550af87")
瑞意宋 = Effect_meta("瑞意宋", False, "7130447431891685895", "3997461", "a73364889c89bd6be1d08a92cb49245a")
瑶蝶体 = Effect_meta("瑶蝶体", False, "7290446536050217532", "25998987", "04e3d3e0eae3de5c859e8c00d2b48759")
甜甜圈 = Effect_meta("甜甜圈", False, "7130634783163421215", "4009729", "bbe904649c122449f4ea360030b603a6")
目光体 = Effect_meta("目光体", False, "7035921361348334117", "1459640", "39e69d115d15e598c11d2686067dc70d")
真言体 = Effect_meta("真言体", False, "7003588300720050696", "1349505", "9ae1a1787978c3b8e2a06a9d0c55906a")
研宋体 = Effect_meta("研宋体", False, "7130644288047682085", "4010355", "06458c13377d445fe3368cd2c786c7a5")
禅影体 = Effect_meta("禅影体", False, "7278963576167993916", "22902355", "438c78fb511d6993217961e53a281c0a")
童趣体 = Effect_meta("童趣体", False, "7035888265290846756", "1459176", "07911c7bc89d724503b88c6fbafaccc5")
简中圆 = Effect_meta("简中圆", False, "7050009066717844005", "1511618", "f26eb8bd135d147bb7700a560f1a5470")
糯米团 = Effect_meta("糯米团", False, "6934225430266253837", "1053146", "aee9551fab5ef01c45dbe3335869db1d")
纯真体 = Effect_meta("纯真体", False, "7045185581772444174", "1494870", "b33e32b8733e27775849ee5d7f92d7e7")
细体 = Effect_meta("细体", False, "6740511815358222859", "349521", "3d80be25a18fb67455744136c1262c91")
经典雅黑 = Effect_meta("经典雅黑", False, "7043775037559542279", "1488718", "ba7bbfabf030860ee4a23d6596a6c6e3")
综艺字 = Effect_meta("综艺字", False, "7130642664080282149", "4010283", "74671c7987f56ba9a6ab93f95856973a")
美佳体 = Effect_meta("美佳体", False, "7203665054338650685", "9898774", "69a5666d4ab91113ea146e71bc3e42c9")
聚珍体 = Effect_meta("聚珍体", False, "7203638484752405051", "9893381", "7e024261e2d38e87bc78e6843ad2e6b3")
芋圆体 = Effect_meta("芋圆体", False, "7039989971796628005", "1478272", "c47882a0a6781f00b6b152c456844413")
若烟体 = Effect_meta("若烟体", False, "7290445344557503033", "25999000", "001f25aa8dc71e9221433f2ff6c8e540")
荔枝体 = Effect_meta("荔枝体", False, "6740498118342611464", "349483", "9beb006988541f18a560f8029d47defa")
萌趣体 = Effect_meta("萌趣体", False, "7045186231122006535", "1494868", "005466971691f729c2a0927ffe6f81b7")
蒹葭体 = Effect_meta("蒹葭体", False, "7290443923556667959", "25999014", "04660ff6d07b1fd3437128caf3adfbb8")
薯条少年 = Effect_meta("薯条少年", False, "7068530728467698213", "1589148", "8842c4ca3fde9cefeaa17fa5bb99a77b")
蝉影隶书 = Effect_meta("蝉影隶书", False, "7045186520738697742", "1494867", "afcec5248968e5b3fd7d7eb3a670eadc")
装甲明朝 = Effect_meta("装甲明朝", False, "7265536455655559739", "20356625", "3f334186c4522694108e7ab9534201fd")
谷秋体 = Effect_meta("谷秋体", False, "7290442742822343205", "25999008", "233d1f80de91946da3c59527a61b1c87")
超重要体 = Effect_meta("超重要体", False, "7203638484752405048", "9893378", "d21f913df460b6a9332a1520f7fe2d0c")
轻吟体 = Effect_meta("轻吟体", False, "7035927184275411464", "1459730", "205a76c590ab163af423468e7f416a91")
追光体 = Effect_meta("追光体", False, "7203638485666763325", "9893371", "5e0b49b0a3e33e04769cabbee228f6f4")
逸致拼音 = Effect_meta("逸致拼音", False, "7070430706689643038", "1600480", "e15bf3763fb346f8b60eebabf04bdeee")
金陵体 = Effect_meta("金陵体", False, "7086699209738424840", "1698067", "599831579b8aa5b5f0608d5e7d4ec5ce")
锦瑟体 = Effect_meta("锦瑟体", False, "7290443998345302586", "25999022", "eb465dc5d9f045c5ff3ce34d480a2529")
雁兰体 = Effect_meta("雁兰体", False, "7290446084780855867", "25998990", "6198e5f40da27fec116ee785c23b837e")
雅酷黑简 = Effect_meta("雅酷黑简", False, "7130640934366089758", "4010137", "35ddec41ffa518033484f219e324a6bd")
霸燃手书 = Effect_meta("霸燃手书", False, "7045187409960505886", "1494865", "e4f6766608951c7184a5d2a56aa370fa")
青松体 = Effect_meta("青松体", False, "7290444911940211237", "25998985", "f4e7026acbdb7edd1003d24561f2add7")
风雅宋 = Effect_meta("风雅宋", False, "7208056673317950011", "10379505", "c4624c3d535a1801e0992ccb25de6ac4")
飒爽手写 = Effect_meta("飒爽手写", False, "7054125855676568095", "1530070", "86756c9b0c71fd513bcc163893b56d7e")
飞扬行书 = Effect_meta("飞扬行书", False, "7035922620969128479", "1459678", "0532175b5a7a61e379d6b1f23c212f43")
飞驰体 = Effect_meta("飞驰体", False, "7045186745100407310", "1494866", "1e9478384005377f087abf035cdffe64")
高字标志黑 = Effect_meta("高字标志黑", False, "7268259518427959866", "20885841", "4843f24f22c8d22c984533e347be275a")
高字湘黑体 = Effect_meta("高字湘黑体", False, "7268259657167147577", "20885842", "2f0c093261b368846aae47cf8a8f74ba")
黄令东齐伋复刻体 = Effect_meta("黄令东齐伋复刻体", False, "7265535655105532476", "20356605", "e7830741b741962e5c43105ea25e3612")
黄金时代 = Effect_meta("黄金时代", False, "7050010418932093471", "1511614", "269a3b6801b4e0b8e43d2d786f729da5")
黑糖体 = Effect_meta("黑糖体", False, "7070430083919385119", "1600490", "c79b375905670f3012ae371583680109")
默陌手写 = Effect_meta("默陌手写", False, "7025886295524119053", "1424938", "64b0eee1f99387b2d7a27f9c961e6bba")
아기 = Effect_meta("아기", False, "6808056941458231815", "645451", "79273a8d31ec91b9f110243bd1096291")
セリフ太字 = Effect_meta("セリフ太字", False, "7020729846334493215", "1402800", "569bf7220b9170da8dd45c2241740140")
一笔壹画加油体 = Effect_meta("一笔壹画加油体", True, "7390218575979483659", "74697345", "f3020b0f6e2995f787a4fab6faef0e33")
一笔壹画潮黑体 = Effect_meta("一笔壹画潮黑体", True, "7390218461990883876", "74696981", "97a3a570222328a8dd97b3921d3716bd")
三极力量体简_粗 = Effect_meta("三极力量体简-粗", True, "7405555944769196595", "79942352", "4c26fb32e20e6796d98a3ee30dfb5635")
三极妙漫体 = Effect_meta("三极妙漫体", True, "7405556011081142822", "79942353", "d4ea5fbd89d90037a8d6500469023d96")
三极宋黑体超粗 = Effect_meta("三极宋黑体超粗", True, "7312720224510284326", "34549526", "8b847b757e21edd8f0189782f8dd97b4")
三极拙墨体 = Effect_meta("三极拙墨体", True, "7405556255906861605", "79942349", "8096b3c9dc67f62af7715b1d266ae1c7")
三极极宋超粗 = Effect_meta("三极极宋超粗", True, "7312719981911740954", "34549536", "433365b2542fd9472e2b74bc82c0423f")
三极榜楷简体 = Effect_meta("三极榜楷简体", True, "7410300778990015027", "81318537", "1b1aadca917f42578fb41d5d95c6539c")
三极欢乐体 = Effect_meta("三极欢乐体", True, "7405555876368486939", "79942350", "e4acf0240f647779c23d3cd70452df5b")
三极正雅黑粗 = Effect_meta("三极正雅黑粗", True, "7312720421177004571", "34549517", "705aa06a0c64ac4348cf575e3921faf9")
三极气泡体 = Effect_meta("三极气泡体", True, "7405556128832033317", "79942351", "f1120030bd9df3fc5e58adfb2be96c26")
三极泼墨体 = Effect_meta("三极泼墨体", True, "7405556071848219186", "79942347", "ecbcf36e6184d1306dc75dcc9391f4b7")
三极浓密仙粗 = Effect_meta("三极浓密仙粗", True, "7312720141865718282", "34549529", "d65312a270f2f970f94b453b0e05949f")
三极湘乡体 = Effect_meta("三极湘乡体", True, "7410300778994209289", "81318538", "c817812de4b4be06462070c0af0e9ab0")
三极萌喵简体 = Effect_meta("三极萌喵简体", True, "7410300778994225674", "81318536", "d56f4a0c1c39de0bc7d5c9fb6e9b1400")
三极行楷简体_粗 = Effect_meta("三极行楷简体-粗", True, "7405556194279952905", "79942348", "e901f6b29261b596fc8e7f85b1ea572b")
三极黑宋体中粗 = Effect_meta("三极黑宋体中粗", True, "7312719852194501158", "34549520", "4577355bc0adeb1763ad581f05e7c5ea")
云书法三行魏碑体 = Effect_meta("云书法三行魏碑体", True, "7316822178538721830", "36880893", "8d1f5570b333f80196ec40fde68fd190")
云书法手书建刚静心楷简= Effect_meta("云书法手书建刚静心楷简", True, "7316823183905002010", "36880886", "5b5b4250553e98394d9e01644ec47320")
云书法生如夏花简 = Effect_meta("云书法生如夏花简", True, "7316822784103944713", "36880894", "460bd3cafc980d468c35c960dd50a2d3")
云书法罗西硬笔楷书体= Effect_meta("云书法罗西硬笔楷书体", True, "7316819473019703859", "36880892", "a8554d938efd7655890ddb5c413b1d47")
亦然体 = Effect_meta("亦然体", True, "7290457372814742073", "26003134", "a4922f5c3dbd6998261cbbf9dcb51139")
仓耳丝柔体 = Effect_meta("仓耳丝柔体", True, "7423616269384946186", "85757836", "4cc0c3a634c7888ada2991778315963c")
仓耳体 = Effect_meta("仓耳体", True, "7423616268759994890", "85757842", "7d450c06b110c67f359ddbb2a6377ae4")
仓耳力士 = Effect_meta("仓耳力士", True, "7423616269326225946", "85757837", "e29302f3d11350964083cc128799dd8e")
凌丝体 = Effect_meta("凌丝体", True, "7290455877864133157", "26003145", "92fc337d10907e56437c0da3f6d10a78")
利飞体 = Effect_meta("利飞体", True, "7423616268764189193", "85757848", "b269aadd970b3705e5aaa54d0343117d")
剪映新年体 = Effect_meta("剪映新年体", True, "7463380715107783206", "102584862", "259e955ebb6238cf8b3a70e160fc26f9")
励字大黑简繁 = Effect_meta("励字大黑简繁", True, "7316745335257174578", "36825420", "78f653837bfd529904d56cfd77521eee")
励字姚体简繁 = Effect_meta("励字姚体简繁", True, "7316817407664722441", "36880881", "22b55c6dc66142309168297e2633ec9b")
励字志向黑简_特粗 = Effect_meta("励字志向黑简 特粗", True, "7316819223840297481", "36880880", "ba409eae71d9d99f370175f283002307")
励字憨憨简 = Effect_meta("励字憨憨简", True, "7316745679055884837", "36825429", "b316a0c93d766f2bcefb9962ebb92f46")
励字敲可爱简_中粗 = Effect_meta("励字敲可爱简 中粗", True, "7316746541820023306", "36825430", "e7226d59672ac424570ad6504c8241a0")
励字行楷简繁 = Effect_meta("励字行楷简繁", True, "7316817018030658075", "36880877", "63abf61c61a93772e2a0feff194c1785")
励字趣石简 = Effect_meta("励字趣石简", True, "7316746949489594931", "36825427", "e2dc9006d5e08c9c3714b9107568bddd")
励字造梦简_特粗 = Effect_meta("励字造梦简 特粗", True, "7316818766493389339", "36880891", "a21754e4d75eaa9ea07f12512f0a1df1")
励字隶书简繁 = Effect_meta("励字隶书简繁", True, "7316746076373914139", "36825425", "28d5ed8c5392b325a5f22823917e2aa7")
华书体 = Effect_meta("华书体", True, "7290455554504266298", "26003140", "2854f0774cf3b780304708ee46625fa9")
听露体 = Effect_meta("听露体", True, "7290456595102700089", "26003132", "adfad625c852fca682e02463bd7d0bbc")
字由爱驾公路体 = Effect_meta("字由爱驾公路体", True, "7311912714970862107", "34131532", "2c6b6b843410224e98e99e3d1ab427e1")
字语古兰体 = Effect_meta("字语古兰体", True, "7312718551096234523", "34549527", "b1130cae36f0b2bad353e96af5850c78")
字语咏宋体 = Effect_meta("字语咏宋体", True, "7312719367769166386", "34549533", "12fe695be021ad4406276e85f32de4be")
字语咏楷体 = Effect_meta("字语咏楷体", True, "7312719210373714459", "34549530", "06ab9abe9d2e6f4d10152bafe691738c")
字语嘟嘟体 = Effect_meta("字语嘟嘟体", True, "7312718329347576347", "34549523", "ce70e138b40294d5f159ddbdfd2f5e23")
字语文韵体 = Effect_meta("字语文韵体", True, "7312719046229627402", "34549537", "bc5a66d2265466330a836fc862b0c518")
字语软糖体 = Effect_meta("字语软糖体", True, "7312718629982704166", "34549535", "a126d5a78f08f65afdcea6f0b6d3928c")
宜宋 = Effect_meta("宜宋", True, "7423616269825348122", "85757843", "6b5fdc1a70b0b3a461bff3db1ccbbae7")
小可爱体 = Effect_meta("小可爱体", True, "7423616269267505691", "85757845", "0eb3ee4fdd0c5a415e73a7e82dd9dcd8")
少年南波万 = Effect_meta("少年南波万", True, "7441547528870302258", "93697433", "fc594dc0e1764159fff35321944e907d")
山雁体 = Effect_meta("山雁体", True, "7290456514370736698", "26003150", "c29a5195061ec2b2f72aa4fe97e04f43")
幽梦体 = Effect_meta("幽梦体", True, "7290457477873668666", "26003126", "1f23a06aada2e64a9dc3cd490aadaf07")
归雁体 = Effect_meta("归雁体", True, "7290455353756488247", "26003136", "5d364212ce7ad920f858d615448a3981")
景曜体 = Effect_meta("景曜体", True, "7290455645264810555", "26003133", "5320f82421f4ef64d62f27272241b8cf")
月亮供电不足 = Effect_meta("月亮供电不足", True, "7312720704959418930", "34549519", "65bb1af80161acd665444de74af896d8")
未光体 = Effect_meta("未光体", True, "7290456683027894839", "26003147", "2e77e4633f21a02e0a70b90977a7b01a")
毛体行楷 = Effect_meta("毛体行楷", True, "7452649447441306121", "98548489", "06e8ecfb9262f12693c90d29dc501111")
汉字之美棒棒糖粗简 = Effect_meta("汉字之美棒棒糖粗简", True, "7316732709747823114", "36795730", "296fc38d5559dba8cb8ed33daf6ea93f")
汉字之美郝刚牡丹体简= Effect_meta("汉字之美郝刚牡丹体简", True, "7316816467062690330", "36880888", "1b67a99e701e335a08536e499dfe91ff")
点字佳楷 = Effect_meta("点字佳楷", True, "7311912796520714779", "34131531", "c218de2cbf3e51caf8b425bfaf174bbf")
点字奇巧 = Effect_meta("点字奇巧", True, "7311913943188902427", "34131533", "b6ef0e1abe473dd27bde5fbdb12fa6f8")
点字小隶书 = Effect_meta("点字小隶书", True, "7311914134109426203", "34131539", "adecd49c062bfd7c94790bf7ba0b16be")
点字玄真宋 = Effect_meta("点字玄真宋", True, "7311914225767551498", "34131530", "eb6a86ba326391dc111882da9659f355")
点字艺圆 = Effect_meta("点字艺圆", True, "7311914298060575283", "34131536", "0cc2de74fd8ed8a72a0c0cbf3bb9b5ff")
点字青花楷 = Effect_meta("点字青花楷", True, "7311913734081876506", "34131534", "8de5c66831c1c08a3a0db17abffdc090")
点字青花隶 = Effect_meta("点字青花隶", True, "7311913858942112306", "34131535", "1c21f23c85ea5473322cfb2b856c686b")
烟客体 = Effect_meta("烟客体", True, "7290457082921226811", "26003138", "b6c9e51a0caeda7546833874c4f6d3f4")
爱你是无解命题 = Effect_meta("爱你是无解命题", True, "7311911945655816730", "34131537", "4d2d4673e42ced2e43c6e6d5d4a3d5d6")
爱民小楷 = Effect_meta("爱民小楷", True, "7423616268760011314", "85757851", "e1e9bb52f3cc75124b4e668bbbeed5ab")
玄鸟体 = Effect_meta("玄鸟体", True, "7290456889668670013", "26003129", "aa8b1188f865f250cce24a09f0105af8")
知新体 = Effect_meta("知新体", True, "7423616268952932902", "85757852", "ab6662733ccf500d7de099211e31423c")
竹言体 = Effect_meta("竹言体", True, "7423616269850513947", "85757835", "abf26da51a47d5dc399680cc09253f62")
花锦体 = Effect_meta("花锦体", True, "7290455460186952251", "26003144", "202627efd4e86fcac13b028297319013")
莫雪体 = Effect_meta("莫雪体", True, "7290456347177390629", "26003143", "e6df6d9922211e1b9cd907930569a320")
造字侠今朝醉简 = Effect_meta("造字侠今朝醉简", True, "7316824086712160806", "36880876", "2b98cf117f555d4789b65c865d9f5f9a")
造字侠寻味江湖简 = Effect_meta("造字侠寻味江湖简", True, "7316824437930594867", "36880883", "8335b615c4eb7b246b7aa564899c368d")
造字侠陈坤风行简繁 = Effect_meta("造字侠陈坤风行简繁", True, "7316823545399480841", "36880887", "c266c8a01c258c85c5f7d022300015e0")
阳华体 = Effect_meta("阳华体", True, "7290457161887388219", "26003127", "6ec8135c696317264510d2725a6fc83a")
阳煦体 = Effect_meta("阳煦体", True, "7290457267030200869", "26003130", "4622bd24edf2f817730e108e625b6e05")
雅月体 = Effect_meta("雅月体", True, "7423616268764189234", "85757855", "0f70f20df8d9be821e294a862be67304")
青鸟华光书宋2 = Effect_meta("青鸟华光书宋2", True, "7410326723780153893", "81332684", "6850473b134099c8049bd646c990fe44")
青鸟华光仿宋2 = Effect_meta("青鸟华光仿宋2", True, "7410326723327185435", "81332685", "96b32125bb5d11e8fe83565b5dc917fe")
青鸟华光细黑 = Effect_meta("青鸟华光细黑", True, "7410326723792736795", "81332678", "54e6e6a69da14b6a9a4a01e2bc3ba4fb")
青鸟华光美黑 = Effect_meta("青鸟华光美黑", True, "7410326723327169034", "81332683", "184e84f286db37d6ea31502521740644")
青鸟华光黑变 = Effect_meta("青鸟华光黑变", True, "7410326723322991154", "81332672", "6ca836ce90531a01adfd2909d6d119e3")
高字标志圆 = Effect_meta("高字标志圆", True, "7312720780599497225", "34549540", "b063783985f84f53748319de1532b926")
鱼太闲躺平体 = Effect_meta("鱼太闲躺平体", True, "7312720611694875162", "34549531", "928979b4f0c9ba5ac430fc2990d0ea9d")
-42
View File
@@ -1,42 +0,0 @@
"""视频蒙版元数据"""
from .effect_meta import Effect_enum
class Mask_meta:
"""蒙版元数据"""
name: str
"""转场名称"""
resource_type: str
"""资源类型, 与蒙版形状相关"""
resource_id: str
"""资源ID"""
effect_id: str
"""效果ID"""
md5: str
default_aspect_ratio: float
"""默认宽高比(宽高都是相对素材的比例)"""
def __init__(self, name: str, resource_type: str, resource_id: str, effect_id: str, md5: str, default_aspect_ratio: float):
self.name = name
self.resource_type = resource_type
self.resource_id = resource_id
self.effect_id = effect_id
self.md5 = md5
self.default_aspect_ratio = default_aspect_ratio
class Mask_type(Effect_enum):
"""蒙版类型"""
线性 = Mask_meta("线性", "line", "6791652175668843016", "636071", "1f467b8b9bb94cecc46d916219b7940a", 1.0)
"""默认遮挡下方部分"""
镜面 = Mask_meta("镜面", "mirror", "6791699060140020232", "636073", "b2c0516d1f737f4542fb9b2862907817", 1.0)
"""默认保留两线之间部分"""
圆形 = Mask_meta("圆形", "circle", "6791700663249146381", "636075", "9a55eae0e99ee6d1ecbc6defaf0501ec", 1.0)
矩形 = Mask_meta("矩形", "rectangle", "6791700809454195207", "636077", "ef361d96c456cd6077c76d737f98898d", 1.0)
爱心 = Mask_meta("爱心", "geometric_shape", "6794051276482023949", "636079", "0bf09fa1e3a32464fed4f71e49a8ab01", 1.115)
星形 = Mask_meta("星形", "geometric_shape", "6794051169434997255", "636081", "155612dee601d3f5422a3fbeabc7610c", 1.05)
-762
View File
@@ -1,762 +0,0 @@
"""转场效果元数据"""
from .effect_meta import Effect_enum
class Transition_meta:
"""转场元数据"""
name: str
"""转场名称"""
is_vip: bool
"""是否为VIP特权"""
resource_id: str
"""资源ID"""
effect_id: str
"""效果ID"""
md5: str
default_duration: int
"""默认持续时间, 单位为微秒"""
is_overlap: bool
"""是否允许重叠(?)"""
def __init__(self, name: str, is_vip: bool, resource_id: str, effect_id: str, md5: str, default_duration: float, is_overlap: bool):
self.name = name
self.is_vip = is_vip
self.resource_id = resource_id
self.effect_id = effect_id
self.md5 = md5
self.default_duration = int(round(default_duration * 1e6))
self.is_overlap = is_overlap
class Transition_type(Effect_enum):
"""转场类型"""
_3D空间 = Transition_meta("3D空间", False, "7049979667406656014", "1506926", "aaecc038f6543411f601608fc5539f0b", 1.500000, True)
"""默认时长: 1.50s"""
# 万花筒 = Transition_meta("万花筒", False, "6748220601061609996", "369155", "25c54ddf8de53d927375656c3fd5a7d3", 0.500000, True)
# """默认时长: 0.50s"""
上移 = Transition_meta("上移", False, "6724846395116753416", "2917279", "df9bc16697464de201a4924de49234a2", 0.500000, True)
"""默认时长: 0.50s"""
下移 = Transition_meta("下移", False, "6724849276100284942", "2917280", "9c042543d4846e7c17e8f950ce6f91c2", 0.500000, True)
"""默认时长: 0.50s"""
中心旋转 = Transition_meta("中心旋转", False, "6858191434294497805", "878914", "b43f5b2e59f966a3b110222773c2942d", 0.500000, False)
"""默认时长: 0.50s"""
云朵 = Transition_meta("云朵", False, "6955722927161479694", "2912469", "283bb4bbe729f19f933cb705024a0983", 0.500000, True)
"""默认时长: 0.50s"""
倒影 = Transition_meta("倒影", False, "6748313807031898627", "369691", "0ee10b771dc0443c41a90bb9fd6b3c25", 0.500000, True)
"""默认时长: 0.50s"""
冰雪结晶 = Transition_meta("冰雪结晶", False, "6919369228701143559", "1017910", "a0fd9d6eb0cb5596cac4f54d0ba59eaf", 0.500000, False)
"""默认时长: 0.50s"""
冲鸭 = Transition_meta("冲鸭", False, "7030714241359286821", "1441672", "784b284f040f61ae95f4e8e660f3a873", 0.500000, False)
"""默认时长: 0.50s"""
分割 = Transition_meta("分割", False, "6968372308419285540", "4211683", "ca45695f29bacf2dc29a6eb959e9e968", 0.500000, True)
"""默认时长: 0.50s"""
分割_II = Transition_meta("分割 II", False, "6969782622868214302", "4211740", "5ba1cb89bcf4a0898f86494864348e13", 0.500000, True)
"""默认时长: 0.50s"""
分割_III = Transition_meta("分割 III", False, "6969793843403166215", "4211739", "942fd71d67ca576384b2cd068157ca45", 0.500000, True)
"""默认时长: 0.50s"""
分割_IV = Transition_meta("分割 IV", False, "6969793934356648455", "4211738", "62d08c08542fe62e6a8429f9501e76fa", 0.500000, True)
"""默认时长: 0.50s"""
前后对比_II = Transition_meta("前后对比 II", False, "7299290706277831218", "28895844", "64e8f4a060901fd4349301f97fbdd172", 0.800000, True)
"""默认时长: 0.80s"""
动漫云朵 = Transition_meta("动漫云朵", False, "6777178865119793678", "2911876", "e835cbc7fa7b15af90a2a7090bbf68c3", 0.500000, False)
"""默认时长: 0.50s"""
动漫漩涡 = Transition_meta("动漫漩涡", False, "6858191448827761160", "878913", "fa7ba99b13036c0ff167ea3b7d5c31a2", 0.500000, False)
"""默认时长: 0.50s"""
动漫火焰 = Transition_meta("动漫火焰", False, "6777178765643485709", "2911875", "8e7c247c5ebd58aa5c3582273e9c840b", 0.500000, False)
"""默认时长: 0.50s"""
动漫闪电 = Transition_meta("动漫闪电", False, "6777178696609436174", "2911874", "3fd5d0c7c48668ba5305c57ac0b5d596", 0.500000, False)
"""默认时长: 0.50s"""
压缩 = Transition_meta("压缩", False, "6751618376780485133", "4212466", "337d4cd9be4e1860bd1e7e50a9a93841", 0.500000, True)
"""默认时长: 0.50s"""
叠加 = Transition_meta("叠加", False, "6914112332205396488", "1003369", "4f7e4bd421e382860b49e3e34eb4e4aa", 1.000000, True)
"""默认时长: 1.00s"""
叠化 = Transition_meta("叠化", False, "6724845717472416269", "322577", "2d641adc4bb63e37e3a0067d8c8cc3c3", 0.500000, True)
"""默认时长: 0.50s"""
右移 = Transition_meta("右移", False, "6726711296063967748", "2917287", "4cfd965c25e33c7df9b2c1b3b4cbdf31", 1.000000, True)
"""默认时长: 1.00s"""
向上 = Transition_meta("向上", False, "6724227090872275463", "359459", "349746a951e130fe896415f51c9eb36a", 1.000000, False)
"""默认时长: 1.00s"""
向上擦除 = Transition_meta("向上擦除", False, "6724849456891564557", "2917281", "9a2e4ebf7309c80be332e3c62594dcd6", 0.500000, True)
"""默认时长: 0.50s"""
向下 = Transition_meta("向下", False, "6724227330190873100", "359449", "9c263958ef3b5762db6ffd94a665f9e8", 1.000000, False)
"""默认时长: 1.00s"""
向下擦除 = Transition_meta("向下擦除", False, "6724849752921346573", "2917282", "ce1fb8739d1fbff3d86498fc18321933", 0.500000, True)
"""默认时长: 0.50s"""
向下流动 = Transition_meta("向下流动", False, "6858191469807669773", "878912", "45f28ed2995ca15cfe027784b55d34f2", 0.500000, False)
"""默认时长: 0.50s"""
向右 = Transition_meta("向右", False, "6724227599616184836", "359527", "55af58a9b04ff458c3a9ae3ddb358152", 1.000000, False)
"""默认时长: 1.00s"""
向右上 = Transition_meta("向右上", False, "6724227870559834635", "359567", "19d72649fe9bc3b272e1d874a93a0e9b", 0.500000, True)
"""默认时长: 0.50s"""
向右下 = Transition_meta("向右下", False, "6724228621742903815", "359537", "4291e21aefc6d87a232441d38cabacc5", 0.500000, True)
"""默认时长: 0.50s"""
向右拉伸 = Transition_meta("向右拉伸", False, "6987299127025472031", "4211782", "6c3d17aa182e6238ee3a48c2fdf4a627", 0.500000, True)
"""默认时长: 0.50s"""
向右擦除 = Transition_meta("向右擦除", False, "6724849898857959950", "2917284", "a10153bd2b569c49ddd7c055e8c9eba9", 0.500000, True)
"""默认时长: 0.50s"""
向右流动 = Transition_meta("向右流动", False, "6858191483573375495", "878911", "8d3508f6e570dc73d3e771d234796cb8", 0.500000, False)
"""默认时长: 0.50s"""
向左 = Transition_meta("向左", False, "6724227717195108867", "359529", "323fadc45da03741e6b393b3e3b34e75", 0.500000, False)
"""默认时长: 0.50s"""
向左上 = Transition_meta("向左上", False, "6724230442679013902", "359533", "4ed73d43829eb496f6885ac0b882a391", 0.500000, True)
"""默认时长: 0.50s"""
向左下 = Transition_meta("向左下", False, "6724230577211314695", "359535", "c76650d4ea9bc4e3b0530c9b9f05f28e", 0.500000, True)
"""默认时长: 0.50s"""
向左拉伸 = Transition_meta("向左拉伸", False, "6987201429622493732", "4211781", "b0dd96c3c203104a2df46d83dd91b7bd", 0.500000, True)
"""默认时长: 0.50s"""
向左擦除 = Transition_meta("向左擦除", False, "6724849999336706573", "2917283", "316c2a1c1783f51505c793b13381b445", 0.500000, True)
"""默认时长: 0.50s"""
吸入 = Transition_meta("吸入", False, "7246288124110705209", "15653345", "fb75bf696e19a04795ae9a06b43a09f2", 1.000000, True)
"""默认时长: 1.00s"""
回忆下滑 = Transition_meta("回忆下滑", False, "7309840407406318117", "33106283", "7e8f1b10bb9979d7ed184d29f301b93d", 1.000000, True)
"""默认时长: 1.00s"""
圆形分割_II = Transition_meta("圆形分割 II", False, "7317206886053319194", "37127313", "05017adee9a3798b4fb207bb3206187e", 0.800000, True)
"""默认时长: 0.80s"""
圆形扫描 = Transition_meta("圆形扫描", False, "6851775006418932238", "813992", "0260ab98d7a840c3344cb5b3e70b7d4b", 1.000000, True)
"""默认时长: 1.00s"""
圆形遮罩 = Transition_meta("圆形遮罩", False, "6725767129519362573", "2916676", "a7eb1d47f97049b17f49669622d07f3d", 0.500000, True)
"""默认时长: 0.50s"""
圆形遮罩_II = Transition_meta("圆形遮罩 II", False, "6724850215364334083", "2916675", "2772ad7c8c7e30c6421be7c2e5dd3f15", 1.000000, True)
"""默认时长: 1.00s"""
复古放映 = Transition_meta("复古放映", False, "7237068402945167909", "14192091", "44c3d405f4961d843c74c69e241df643", 0.600000, True)
"""默认时长: 0.60s"""
岁月的痕迹 = Transition_meta("岁月的痕迹", False, "6982750240663147044", "1185194", "0b228af1ebde4909bb6ff545ddd89023", 1.000000, True)
"""默认时长: 1.00s"""
左下角_II = Transition_meta("左下角 II", False, "7304868316252738098", "30874190", "e0296196f0ec6666a33b33fead4f63d6", 0.700000, True)
"""默认时长: 0.70s"""
左移 = Transition_meta("左移", False, "6726711499676455435", "2917286", "9562c0ea301229d43f9dca6f6590f306", 1.000000, True)
"""默认时长: 1.00s"""
开幕 = Transition_meta("开幕", False, "6750893890712113677", "391781", "d5f097e701ddaa984a590249896fc51a", 0.500000, True)
"""默认时长: 0.50s"""
弹幕转场 = Transition_meta("弹幕转场", False, "7028877116259176974", "1433950", "7b5385070a42a218f194d9daddb59f32", 4.000000, False)
"""默认时长: 4.00s"""
弹跳 = Transition_meta("弹跳", False, "6747865141120864779", "368205", "4b3b8b53bc1f947d57a30489d81387eb", 0.500000, True)
"""默认时长: 0.50s"""
打板转场_I = Transition_meta("打板转场 I", False, "7028143517570437668", "1432322", "355d5c4df581f6c4940c9b999e010f81", 4.000000, False)
"""默认时长: 4.00s"""
打板转场_II = Transition_meta("打板转场 II", False, "7029592645538157086", "1437264", "021dfc9a6541d8d08bac631749f9e87d", 4.000000, False)
"""默认时长: 4.00s"""
抖动 = Transition_meta("抖动", False, "7252544245444121148", "17223925", "a1b79bbc99afca7c9e5372cd050ad61d", 0.800000, True)
"""默认时长: 0.80s"""
抖动_II = Transition_meta("抖动 II", False, "7252544309830881851", "17223924", "37319b02a398332e7159f323ea93ba88", 0.800000, True)
"""默认时长: 0.80s"""
抠像旋转 = Transition_meta("抠像旋转", False, "7386584387128660506", "73423370", "290a8f067f8039b1060df3d1e8d07ca0", 0.800000, True)
"""默认时长: 0.80s"""
拉伸 = Transition_meta("拉伸", False, "7231391397717217851", "13402655", "4fd21b4a2e6382ee8851c51c8f65ed73", 1.200000, True)
"""默认时长: 1.20s"""
拉伸_II = Transition_meta("拉伸 II", False, "7259735372039459389", "19137130", "d28fee612c51edf28da804983d220f8d", 0.600000, True)
"""默认时长: 0.60s"""
拉远 = Transition_meta("拉远", False, "6724226338418332167", "359365", "9661d5321722495c0a98959a0d617b0f", 1.000000, False)
"""默认时长: 1.00s"""
拍摄器 = Transition_meta("拍摄器", False, "7100849808784495135", "2057168", "b64bebe75d492161875d4fd54725b31d", 0.500000, True)
"""默认时长: 0.50s"""
推近 = Transition_meta("推近", False, "6724226861666144779", "359359", "4d5a316f2eae582e7d0604b47feb8c32", 1.000000, False)
"""默认时长: 1.00s"""
撕纸拉屏 = Transition_meta("撕纸拉屏", False, "7254847807465460280", "17934952", "c500d2310388b63f3a4e66ff0b15f6dc", 0.700000, True)
"""默认时长: 0.70s"""
放射 = Transition_meta("放射", False, "6724239584663704071", "4212630", "06cc8d49c558d57e21207f68a6a7dbc0", 1.000000, True)
"""默认时长: 1.00s"""
故障 = Transition_meta("故障", False, "6725771847444468236", "2918080", "7bec08ae5dae8806e3ba0c66622d0fd3", 1.000000, False)
"""默认时长: 1.00s"""
斜向分割 = Transition_meta("斜向分割", False, "7085250093527339557", "4211687", "6ae9eb3ee4b08afa67e3d079a2ece505", 0.500000, True)
"""默认时长: 0.50s"""
星星 = Transition_meta("星星", False, "6751564373317128708", "2916678", "5ad3a484b1784e3f5391bf3fa7b188f4", 0.500000, True)
"""默认时长: 0.50s"""
星星_II = Transition_meta("星星 II", False, "6789847494898487822", "2916679", "16a4697aef243c1524e9581fb2f038c9", 0.500000, True)
"""默认时长: 0.50s"""
模糊 = Transition_meta("模糊", False, "6911569618171597320", "4212596", "fc1352435f88c6f284b6c6dce8552ffe", 0.500000, True)
"""默认时长: 0.50s"""
横向分割 = Transition_meta("横向分割", False, "7083771238564237861", "4211685", "aa0aa4a72fc236611d3fd4bf75a12ca3", 0.500000, True)
"""默认时长: 0.50s"""
横向拉幕 = Transition_meta("横向拉幕", False, "6724492948144132621", "2917278", "de63aa2d5225bb6a65b5bab8702aa1f5", 1.000000, True)
"""默认时长: 1.00s"""
横线 = Transition_meta("横线", False, "6724845810892149251", "2918076", "36c1c8edb0171ea082c98d38ffa8bd36", 0.500000, True)
"""默认时长: 0.50s"""
气泡转场 = Transition_meta("气泡转场", False, "7028880945671311903", "1433968", "66489506132d1314f3c7264bcd947cad", 4.000000, False)
"""默认时长: 4.00s"""
水波卷动 = Transition_meta("水波卷动", False, "6858191497280360973", "878910", "cf9bac91349a227a6155eca9d94a8af8", 0.500000, False)
"""默认时长: 0.50s"""
水波向右 = Transition_meta("水波向右", False, "6858191510865711629", "878909", "e9301bacebc6dc444aa4e6f835dd4a31", 0.500000, False)
"""默认时长: 0.50s"""
水波向左 = Transition_meta("水波向左", False, "6858191524312650248", "878908", "6b6499879310b6d29e9595799829cb15", 0.500000, False)
"""默认时长: 0.50s"""
泛光 = Transition_meta("泛光", False, "6914112263645303303", "4202527", "c978e2e22e9a9768813f5fd8d486b792", 1.000000, True)
"""默认时长: 1.00s"""
泛白 = Transition_meta("泛白", False, "6949828109663212045", "4202528", "1bf6b83628ff6416a4d87865107b739e", 1.000000, False)
"""默认时长: 1.00s"""
波点向右 = Transition_meta("波点向右", False, "6858191541706428941", "878907", "74c13e6250cdff7a4e860625d1098e0c", 0.500000, False)
"""默认时长: 0.50s"""
渐变擦除 = Transition_meta("渐变擦除", False, "6919369138800431629", "1017911", "2fff9b60c929559bce574ab8ef2c14a7", 1.000000, True)
"""默认时长: 1.00s"""
滑动 = Transition_meta("滑动", False, "6757982416649851399", "4212349", "b99916e2936aeb2e56892ca617888694", 1.000000, True)
"""默认时长: 1.00s"""
漩涡 = Transition_meta("漩涡", False, "6851810799510360583", "4211780", "31d2de43e6711a9eeb831d60529d0393", 1.000000, False)
"""默认时长: 1.00s"""
爱心 = Transition_meta("爱心", False, "6748289440130535947", "2916677", "2382e2096918b63a0f8e75f720d7d892", 0.500000, True)
"""默认时长: 0.50s"""
爱心_II = Transition_meta("爱心 II", False, "6789846472343949837", "2916682", "0c04684566638932cb6f6d86cdfabda6", 0.500000, True)
"""默认时长: 0.50s"""
爱心上升 = Transition_meta("爱心上升", False, "6789846246069637640", "2916681", "2a3c5439ce79e6113843a2b7135bd21a", 0.500000, True)
"""默认时长: 0.50s"""
电视故障_I = Transition_meta("电视故障 I", False, "7046293801123451405", "2918081", "feaf2e85b909a123ea71728f9b61fb03", 1.600000, True)
"""默认时长: 1.60s"""
电视故障_II = Transition_meta("电视故障 II", False, "7042278078415901192", "2918082", "a082bdaea1122bbf1aba730278d50250", 1.600000, True)
"""默认时长: 1.60s"""
画笔擦除 = Transition_meta("画笔擦除", False, "6789846828788486664", "2912467", "4fafb5343d5c9e726278e90b5e0c1c93", 0.500000, True)
"""默认时长: 0.50s"""
白光快闪 = Transition_meta("白光快闪", False, "7343136487182963211", "49272367", "c1f7073a94d22565ace1ab3023d1c154", 0.400000, True)
"""默认时长: 0.40s"""
白色墨花 = Transition_meta("白色墨花", False, "6858191556055142919", "878906", "775ccf71576e2b8fb075f0e61e980923", 0.500000, False)
"""默认时长: 0.50s"""
白色烟雾 = Transition_meta("白色烟雾", False, "6885646856672514567", "947664", "9b679b32ec03c42932fa37b10c141bda", 0.500000, False)
"""默认时长: 0.50s"""
百叶窗 = Transition_meta("百叶窗", False, "6789847331060584974", "521326", "9f37c3f6f5e84b37b3a0560803a16c30", 0.500000, True)
"""默认时长: 0.50s"""
眨眼 = Transition_meta("眨眼", False, "6864867302936941064", "2917719", "bf695506c8091f7a01ee7b1323a4d601", 0.500000, True)
"""默认时长: 0.50s"""
矩形分割 = Transition_meta("矩形分割", False, "6858191571196580359", "878905", "82d6235324f8c5f830f8ccf7b1cc036b", 0.500000, False)
"""默认时长: 0.50s"""
窗格 = Transition_meta("窗格", False, "6747989545448378888", "368721", "cd6a7ff53319efa1c57690f61c8737a0", 0.500000, True)
"""默认时长: 0.50s"""
立方体 = Transition_meta("立方体", False, "6785042367498949127", "519784", "be45578bb628a21eaae268a8d8df868f", 0.500000, True)
"""默认时长: 0.50s"""
竖向分割 = Transition_meta("竖向分割", False, "7083771107706147364", "4211686", "7cc017d4e1b6ab58ec4b6900432522ff", 0.500000, True)
"""默认时长: 0.50s"""
竖向拉幕 = Transition_meta("竖向拉幕", False, "6726711903684399619", "2917285", "84f91be5a43cc6a9d03505a465418206", 1.000000, True)
"""默认时长: 1.00s"""
竖向模糊 = Transition_meta("竖向模糊", False, "7125661387568714247", "3796327", "cda4099e3f207ef1509f27d0b1ab01c1", 0.800000, True)
"""默认时长: 0.80s"""
竖向模糊_II = Transition_meta("竖向模糊 II", False, "7280837008421818936", "23404229", "85e381982a94778e003f3acc9527d5cf", 0.660000, True)
"""默认时长: 0.66s"""
竖线 = Transition_meta("竖线", False, "6724846536041173511", "2918077", "75019c1486b2366675d95602f58430e2", 0.500000, True)
"""默认时长: 0.50s"""
箭头向右 = Transition_meta("箭头向右", False, "6858191587554365966", "878904", "fa0cfb9e822393af86c6df4a8477cd63", 0.500000, False)
"""默认时长: 0.50s"""
粒子 = Transition_meta("粒子", False, "6855565313715474952", "4212632", "389d08f0700dd3e646a1e92289d84d58", 0.500000, True)
"""默认时长: 0.50s"""
翻篇 = Transition_meta("翻篇", False, "7034446419641504264", "4212350", "e3a2c5e0bd63416b5f64e489beb8a702", 1.300000, True)
"""默认时长: 1.30s"""
翻页 = Transition_meta("翻页", False, "6747979085894390279", "368701", "413b2cafe7a0c6309286845c559b3066", 0.500000, True)
"""默认时长: 0.50s"""
色差逆时针 = Transition_meta("色差逆时针", False, "6940500629013926413", "1069274", "b235f0bc4c9eb6e090358c09c7b0ffb0", 1.000000, False)
"""默认时长: 1.00s"""
色差顺时针 = Transition_meta("色差顺时针", False, "6940520116035523080", "1069374", "8661a7a8b19762d35506cd6513d8ed3e", 1.000000, False)
"""默认时长: 1.00s"""
色彩溶解 = Transition_meta("色彩溶解", False, "6724846004274729480", "322583", "b5f962a334dcc141bbc3dae0f5777564", 0.500000, True)
"""默认时长: 0.50s"""
色彩溶解_II = Transition_meta("色彩溶解 II", False, "6724866927933526542", "322625", "8179e342f9b24dd1817c56f7ef1f8f9b", 1.000000, True)
"""默认时长: 1.00s"""
色彩溶解_III= Transition_meta("色彩溶解 III", False, "6724867032312975875", "322627", "293a03bd140d09b0c616f879bda235e1", 1.000000, True)
"""默认时长: 1.00s"""
蓝色线条 = Transition_meta("蓝色线条", False, "6858191605384352263", "878903", "d4d2996c3f6cf97fb8602f825d98a4da", 0.500000, False)
"""默认时长: 0.50s"""
逆时针旋转 = Transition_meta("逆时针旋转", False, "6724226603372515853", "359437", "048170ae8df06f9d6964691b1e472c6a", 0.500000, True)
"""默认时长: 0.50s"""
逆时针旋转_II= Transition_meta("逆时针旋转 II", False, "7252544659245765179", "17224251", "1b2c634ea54e81de34cb6d31848908af", 0.800000, True)
"""默认时长: 0.80s"""
镜像翻转 = Transition_meta("镜像翻转", False, "6848792278710882824", "2917288", "1109c08965141f90b9174c38e85c8cab", 1.000000, False)
"""默认时长: 1.00s"""
闪白 = Transition_meta("闪白", False, "6724845376098013708", "322575", "b033ea56618d5b0f098071fb326bb02a", 0.500000, False)
"""默认时长: 0.50s"""
闪白_II = Transition_meta("闪白 II", False, "7306818286413419017", "31619869", "9a1089fc9fefe2a79a71c37c1bc5831a", 0.300000, True)
"""默认时长: 0.30s"""
闪黑 = Transition_meta("闪黑", False, "6724239388189921806", "321493", "3bca53e9f3dfa2c184fbee96438ea097", 0.500000, False)
"""默认时长: 0.50s"""
雪花故障 = Transition_meta("雪花故障", False, "6724866446842663431", "2918079", "71cabe836d9c88afd44f43654ba67fa7", 1.000000, False)
"""默认时长: 1.00s"""
雾化 = Transition_meta("雾化", False, "7216171159589491259", "11387229", "945e1560e2c65277b4bd4127cd479746", 1.200000, True)
"""默认时长: 1.20s"""
震动 = Transition_meta("震动", False, "7198100561235808825", "9261771", "e46204ca1e4fcf76d1b1c86e852e862d", 1.000000, True)
"""默认时长: 1.00s"""
顺时针旋转 = Transition_meta("顺时针旋转", False, "6724226684721041932", "359421", "d6d0c76fb82ca2a355de138d94a94780", 0.500000, True)
"""默认时长: 0.50s"""
顺时针旋转_II= Transition_meta("顺时针旋转 II", False, "7252544556799889975", "17224317", "5e81c58bf217a2bdaf479275e412ea93", 0.800000, True)
"""默认时长: 0.80s"""
频闪 = Transition_meta("频闪", False, "7083767957662208549", "1674710", "35a76b77dd0812f7012911109db35799", 0.500000, True)
"""默认时长: 0.50s"""
风车 = Transition_meta("风车", False, "6748286529921094157", "369485", "367b8b51b2eeb63eb2009bf5b356bc2f", 0.500000, True)
"""默认时长: 0.50s"""
马赛克 = Transition_meta("马赛克", False, "6724866519022440967", "4212631", "eed93b26d9cd6296b10d2f5065ee396e", 1.000000, True)
"""默认时长: 1.00s"""
黑色块 = Transition_meta("黑色块", False, "6724866346569437710", "2918078", "357e865f3bb0c6529ee882ebf279d7c6", 0.500000, True)
"""默认时长: 0.50s"""
黑色烟雾 = Transition_meta("黑色烟雾", False, "6885647017452769805", "947663", "fa02f80c28a9671a206c2ccf17b41c58", 0.500000, False)
"""默认时长: 0.50s"""
万花筒 = Transition_meta("万花筒", True, "7257806429086552632", "18722268", "0aa1d28fdb90725586089436e6ccd243", 0.800000, True)
"""默认时长: 0.80s"""
三屏放大 = Transition_meta("三屏放大", True, "7320254175466492467", "38586528", "b59a3df958aeeba78f1ceb075be189f0", 1.000000, True)
"""默认时长: 1.00s"""
三屏滑入 = Transition_meta("三屏滑入", True, "7312438185261273650", "34443818", "09dc4fee56acca3e6f1c104277b8695d", 1.000000, True)
"""默认时长: 1.00s"""
三屏闪切 = Transition_meta("三屏闪切", True, "7252599996254523959", "17242682", "2bc234d945f15d93f3d292e64042d69d", 0.800000, True)
"""默认时长: 0.80s"""
下滑 = Transition_meta("下滑", True, "7309694074015977993", "32998125", "9c54ccb7b27ab98f7c3bb03a5d4acc4b", 0.550000, True)
"""默认时长: 0.55s"""
云朵_II = Transition_meta("云朵 II", True, "6955760408737092132", "2912470", "5a8914a3658f88265bbeda060a7c79aa", 0.500000, True)
"""默认时长: 0.50s"""
亮点模糊 = Transition_meta("亮点模糊", True, "7123135366504124936", "3705757", "b48f47c097e83842d1c0f919d9c67af6", 1.000000, True)
"""默认时长: 1.00s"""
便利贴 = Transition_meta("便利贴", True, "7302023728441856549", "29871972", "a5a04de1e339c4d4907e26ff6b229563", 1.100000, True)
"""默认时长: 1.10s"""
信号故障 = Transition_meta("信号故障", True, "7288149307197231676", "25265947", "f23f60f3bee4fac6368268a1406ccaf7", 0.500000, True)
"""默认时长: 0.50s"""
信号故障_II = Transition_meta("信号故障 II", True, "7342791345162949183", "49094731", "b5537d48d5d72d9707bb4641d51ecc73", 0.670000, False)
"""默认时长: 0.67s"""
倾斜拉伸 = Transition_meta("倾斜拉伸", True, "7383960886131560960", "72481265", "c87e594192131b1b82e1c34cd383f807", 0.800000, True)
"""默认时长: 0.80s"""
倾斜模糊 = Transition_meta("倾斜模糊", True, "7355762441533264394", "56268173", "0b88f86366c21c3ebd2bcc8df140810d", 0.800000, True)
"""默认时长: 0.80s"""
像素冲屏 = Transition_meta("像素冲屏", True, "6981689835534684702", "1182216", "b7f8e6cd03560d1f52e1270dcf7c9ba4", 0.800000, True)
"""默认时长: 0.80s"""
光束 = Transition_meta("光束", True, "6982127832042312206", "4202531", "84525ee78728b5cce44c8404d9f50b0d", 0.500000, True)
"""默认时长: 0.50s"""
全息投影 = Transition_meta("全息投影", True, "7298230450768581129", "28518430", "95a2a049736e0843b5984e0090276f7b", 0.400000, True)
"""默认时长: 0.40s"""
六边形变焦 = Transition_meta("六边形变焦", True, "7182413216276812346", "7824963", "faf521d87b90c79031bfd08d687df52a", 1.000000, True)
"""默认时长: 1.00s"""
冲屏扭曲 = Transition_meta("冲屏扭曲", True, "7359133728313971227", "58099421", "2fb5734ab118c745bfa0596264533e54", 0.900000, True)
"""默认时长: 0.90s"""
几何分割 = Transition_meta("几何分割", True, "7130139199394550303", "3985085", "4f6209fcc7e8746a7c1e43d8a1704827", 0.500000, True)
"""默认时长: 0.50s"""
分屏下滑 = Transition_meta("分屏下滑", True, "7337974537683735080", "46873416", "eb4e4368773f40a8c807e77497acab4f", 0.900000, True)
"""默认时长: 0.90s"""
前后对比 = Transition_meta("前后对比", True, "7205856572994490935", "10139297", "f38bc39938f58a4ee3f9c7bfcf4f524f", 1.200000, True)
"""默认时长: 1.20s"""
剧烈摇晃 = Transition_meta("剧烈摇晃", True, "7367356130307084838", "63047898", "4ffdc4b55688e65262a229d5e7b987ca", 0.900000, True)
"""默认时长: 0.90s"""
卡片弹出 = Transition_meta("卡片弹出", True, "7384334283659285032", "72605929", "67660fa9cdb387454a59d3a747cff6ef", 1.000000, True)
"""默认时长: 1.00s"""
可爱爆炸 = Transition_meta("可爱爆炸", True, "7187674415268631101", "8375167", "75942cf09b7e84526a357898a47c18bb", 0.800000, True)
"""默认时长: 0.80s"""
吃掉 = Transition_meta("吃掉", True, "7372506069328728585", "66629623", "64b8f472cc109cccd9c50e210331af43", 0.900000, True)
"""默认时长: 0.90s"""
后台切换 = Transition_meta("后台切换", True, "7320129407799005734", "38530921", "c5092413343f5e808ffc27ab8b02e7c4", 0.800000, True)
"""默认时长: 0.80s"""
向上波动 = Transition_meta("向上波动", True, "7148734739807998495", "4861515", "69a520845b900b142b203cf2e677abd5", 5.000000, True)
"""默认时长: 5.00s"""
向下抖动 = Transition_meta("向下抖动", True, "7338709911791997480", "47241669", "1a44879e265bc89746e30f59d2ff0245", 1.300000, True)
"""默认时长: 1.30s"""
向下拖拽 = Transition_meta("向下拖拽", True, "7199528468244075067", "9382531", "f1d490e1e2a87013bee63a8aa4191f9f", 0.800000, True)
"""默认时长: 0.80s"""
向左拉屏 = Transition_meta("向左拉屏", True, "7089311972235153950", "1722934", "21538bc8fa278603f8e944fc405a65c9", 0.500000, True)
"""默认时长: 0.50s"""
向左波动 = Transition_meta("向左波动", True, "7126772940451877406", "3971081", "cbffe80a580575becb3beb3bcbd5cc09", 5.000000, True)
"""默认时长: 5.00s"""
喜欢 = Transition_meta("喜欢", True, "7070430644563612191", "1600478", "945ee55ddc4b7c9762b55c0ee302bdce", 0.500000, True)
"""默认时长: 0.50s"""
四屏转换 = Transition_meta("四屏转换", True, "7337612480610308649", "46644610", "e7bd3aacd0daeafdf20d93d4a171a846", 1.000000, True)
"""默认时长: 1.00s"""
回忆 = Transition_meta("回忆", True, "6748220149284737550", "4211778", "48a73d2ca44a59d8faf88ab0c4bb39f6", 0.500000, True)
"""默认时长: 0.50s"""
回忆_II = Transition_meta("回忆 II", True, "6748220462746046989", "4211779", "bfb17d87ed3db6332a6e0855299809d9", 0.500000, True)
"""默认时长: 0.50s"""
回忆拉屏 = Transition_meta("回忆拉屏", True, "7184682990901924410", "8027945", "3bc26bcea93ea43b349c60c28bea394f", 1.000000, True)
"""默认时长: 1.00s"""
回忆拉屏_II = Transition_meta("回忆拉屏 II", True, "7306440470119322139", "31456359", "2464d4afc9c5f43072935915c6a86c29", 0.700000, True)
"""默认时长: 0.70s"""
圆形分割 = Transition_meta("圆形分割", True, "7083435788322476581", "4211684", "2bb3ad90a4eb3a2563b87c300e0ae8a1", 1.500000, False)
"""默认时长: 1.50s"""
圣诞树 = Transition_meta("圣诞树", True, "7302357935902954035", "29976594", "8c40262df8758d19446264aa5749008a", 0.700000, True)
"""默认时长: 0.70s"""
复古叠影 = Transition_meta("复古叠影", True, "7200638304591548985", "9529419", "078be6db2b8d8abded47cbd72f5635df", 1.000000, True)
"""默认时长: 1.00s"""
复古放映_II = Transition_meta("复古放映 II", True, "7240050497804046908", "14607947", "9891a08898646c3795cab650979bf0dc", 1.000000, True)
"""默认时长: 1.00s"""
复古漏光 = Transition_meta("复古漏光", True, "7181752495150993957", "8104139", "0af78adb0da721bbe253b096b8152851", 0.800000, True)
"""默认时长: 0.80s"""
复古漏光_II = Transition_meta("复古漏光 II", True, "7287881053534949943", "25193261", "1789e06f18340fbcbd30e6757f10ba75", 0.600000, True)
"""默认时长: 0.60s"""
复古胶片 = Transition_meta("复古胶片", True, "7261814111816651322", "19552395", "c5686c7e832a5e8c178c5cadb42d9ab4", 1.000000, True)
"""默认时长: 1.00s"""
多层环形 = Transition_meta("多层环形", True, "7373523970538082866", "67116644", "cf6da6be1066054f86c4524fa6494d8e", 1.500000, True)
"""默认时长: 1.50s"""
多屏定格 = Transition_meta("多屏定格", True, "7287860606395224613", "25184085", "c12aeac3828eb06fd5d0f865ee7041d1", 0.800000, True)
"""默认时长: 0.80s"""
大圆盘 = Transition_meta("大圆盘", True, "7362104359682839055", "59713023", "9d6a02b47846369cec6d19a35826570d", 0.800000, True)
"""默认时长: 0.80s"""
射灯 = Transition_meta("射灯", True, "7368775489445433883", "63886272", "23706ad60c2258a524da320eca564d12", 1.600000, True)
"""默认时长: 1.60s"""
小喇叭 = Transition_meta("小喇叭", True, "7070430823597478407", "1600476", "3707101142d3069789f3d821cdb7bc35", 0.500000, True)
"""默认时长: 0.50s"""
小恶魔 = Transition_meta("小恶魔", True, "7075598043252265509", "1628344", "c9a87dfafa58fbc0d401fc182fbaf6fc", 1.000000, True)
"""默认时长: 1.00s"""
幻影 = Transition_meta("幻影", True, "7218040359715082809", "11634125", "4a1a61e615eb94e37e2c198dd4602107", 0.800000, True)
"""默认时长: 0.80s"""
幻觉 = Transition_meta("幻觉", True, "7395044376621093391", "76465118", "cb9796c59a719185df8c9c5d1922b061", 1.000000, True)
"""默认时长: 1.00s"""
开心 = Transition_meta("开心", True, "7073053544839909919", "1610838", "0d80e7d2b7171236732668e91b849120", 0.500000, False)
"""默认时长: 0.50s"""
弹出 = Transition_meta("弹出", True, "7394709307842892303", "76381219", "5c7ab5f82d4253e2225b57ba734edd3a", 0.900000, True)
"""默认时长: 0.90s"""
弹动发光 = Transition_meta("弹动发光", True, "7347897562436735503", "51950360", "31bdfcfe5852df71426d22fc02293698", 0.800000, True)
"""默认时长: 0.80s"""
彩色像素 = Transition_meta("彩色像素", True, "7096015235953201701", "4212518", "d91c7ef4be8808bddec8a1a119f78da7", 0.500000, False)
"""默认时长: 0.50s"""
微抖动 = Transition_meta("微抖动", True, "7368739347845091877", "63860874", "9870ae40f2c8a325debc06d25ef46895", 1.500000, True)
"""默认时长: 1.50s"""
心形叠化 = Transition_meta("心形叠化", True, "7264829174601224764", "20224653", "24559e84f2cfae6bbfd86d47bb8f60f9", 1.000000, True)
"""默认时长: 1.00s"""
快速缩放 = Transition_meta("快速缩放", True, "7382154814144123392", "71890617", "bbedbf5ac1b865d1e1395d4d402ce5fa", 1.000000, True)
"""默认时长: 1.00s"""
快门 = Transition_meta("快门", True, "6882983860615778823", "2917720", "2df569fefb5004c041af5509c10d6c53", 0.500000, True)
"""默认时长: 0.50s"""
扫光 = Transition_meta("扫光", True, "7106765945305043463", "4202535", "333aa7e9d8b24e358ea60784ce47b6fe", 0.500000, True)
"""默认时长: 0.50s"""
扭曲溶解 = Transition_meta("扭曲溶解", True, "7374259106502152741", "67617874", "756df14869da51538ed41e2bfac3b779", 1.000000, True)
"""默认时长: 1.00s"""
扭转弹动 = Transition_meta("扭转弹动", True, "7344986966145896994", "50231600", "e5d36f065e3f0e8801c43a625a7d9947", 1.500000, True)
"""默认时长: 1.50s"""
抖动放大 = Transition_meta("抖动放大", True, "7260415521852494397", "19272888", "e4cafc076ecab223a39a26fe6f05b6db", 0.800000, True)
"""默认时长: 0.80s"""
抖动缩小 = Transition_meta("抖动缩小", True, "7291972229087105563", "26488746", "6e78a0c97c60562573a30342882a240f", 0.700000, True)
"""默认时长: 0.70s"""
抖动缩小__II= Transition_meta("抖动缩小 II", True, "7316783851206873651", "36841926", "137d3f03fbd4dddbc6a2a0dd1f371e17", 1.000000, True)
"""默认时长: 1.00s"""
抽象前景 = Transition_meta("抽象前景", True, "7104215831919202853", "2459634", "88b3ead3e00313684cd868d51c1173c9", 0.500000, True)
"""默认时长: 0.50s"""
抽象前景_II = Transition_meta("抽象前景 II", True, "7108564115529929229", "2870170", "b8628f4b1d6fc27447dfad6a5f25beb4", 0.500000, True)
"""默认时长: 0.50s"""
拉开 = Transition_meta("拉开", True, "7384323685026370098", "72601002", "828b81127e669508f999900bff18cf2a", 0.600000, True)
"""默认时长: 0.60s"""
拉框入屏 = Transition_meta("拉框入屏", True, "7297077423487586826", "28115429", "bfc8a51d2b304be3dd36a68331f8d0f8", 1.000000, True)
"""默认时长: 1.00s"""
拍摄器_II = Transition_meta("拍摄器 II", True, "7109727014780670495", "2958464", "5483f878a302c6d7879bd566cebab543", 0.900000, True)
"""默认时长: 0.90s"""
拍摄器_III = Transition_meta("拍摄器 III", True, "7107542030976291336", "2792048", "36c9b870a00e16365421398ac4e51652", 0.800000, True)
"""默认时长: 0.80s"""
推近_II = Transition_meta("推近 II", True, "7290852476259930685", "26135688", "94815943a86e741a5fec1737fbb46d60", 0.900000, True)
"""默认时长: 0.90s"""
推远_II = Transition_meta("推远 II", True, "7360987817066893862", "59043083", "0a10553e75180add06fd336bf16fa8aa", 1.000000, True)
"""默认时长: 1.00s"""
摄像机 = Transition_meta("摄像机", True, "7070047850960261668", "1598384", "bb0b9fa428e5a3fde828c03022b5082d", 0.500000, True)
"""默认时长: 0.50s"""
摇晃描边 = Transition_meta("摇晃描边", True, "7372137986877559335", "66403340", "0a5449cf1ca4c9fb473ff664ea23185b", 1.000000, True)
"""默认时长: 1.00s"""
摇晃震动 = Transition_meta("摇晃震动", True, "7343618757530489379", "49545855", "c911cc41c158afbd43636d1aa465e1d2", 1.300000, True)
"""默认时长: 1.30s"""
摇镜 = Transition_meta("摇镜", True, "7305969268259033609", "31254345", "f215c106100f76dcf6c550d0f8217ecb", 0.700000, True)
"""默认时长: 0.70s"""
撕纸 = Transition_meta("撕纸", True, "6875627914444935694", "2912468", "131ae40c737ab9f5c79e35e3639a4bad", 0.500000, True)
"""默认时长: 0.50s"""
撕纸掉落 = Transition_meta("撕纸掉落", True, "7218114518314914365", "11661051", "42fa2f7a99a392e2801ad5ec5f62d73a", 1.200000, True)
"""默认时长: 1.20s"""
收缩抖动 = Transition_meta("收缩抖动", True, "7347676775633130024", "51859926", "88939867fef0a71b39f549558d724d31", 1.000000, True)
"""默认时长: 1.00s"""
放大左移 = Transition_meta("放大左移", True, "7347582471111709236", "51784590", "a2c4ddc0f96c5694e941d738ed52cdf4", 1.300000, True)
"""默认时长: 1.30s"""
放大镜 = Transition_meta("放大镜", True, "7313974602156216858", "35244988", "91aee5fc06c85dda958101a677f19c0b", 0.700000, True)
"""默认时长: 0.70s"""
故障模糊 = Transition_meta("故障模糊", True, "7302270954602762789", "29927992", "fc3fae70595c7bb6f943aca08dc7b9f1", 0.700000, True)
"""默认时长: 0.70s"""
数字矩阵 = Transition_meta("数字矩阵", True, "7268870949548593725", "20983534", "f39bf079c6066cbfee7c5eca1491b276", 1.000000, True)
"""默认时长: 1.00s"""
斜向模糊 = Transition_meta("斜向模糊", True, "7125661284762128910", "3796323", "b14d9650ca6eef79d6b19c16c65166d3", 0.800000, True)
"""默认时长: 0.80s"""
斜向闪光 = Transition_meta("斜向闪光", True, "7384331194978013711", "72603864", "eba796256a96c4ff0d1b331a8819c6f2", 0.700000, True)
"""默认时长: 0.70s"""
斜线翻页 = Transition_meta("斜线翻页", True, "7339900424956154403", "47905855", "46d525166125a781ce8cf9c6e6370454", 0.700000, True)
"""默认时长: 0.70s"""
新篇章 = Transition_meta("新篇章", True, "7174756125902901797", "7089439", "74716b2d52b85799f78903818eb3c98f", 0.800000, True)
"""默认时长: 0.80s"""
新篇章_II = Transition_meta("新篇章 II", True, "7174754977544409657", "7089435", "6c1c52a50f842600c69417cf38adc113", 1.600000, True)
"""默认时长: 1.60s"""
方形分割 = Transition_meta("方形分割", True, "7127901205820346917", "3895735", "9f29e50ac72b66f4b0320ee1ea9d112f", 0.500000, True)
"""默认时长: 0.50s"""
方形模糊 = Transition_meta("方形模糊", True, "7122721406210544164", "3686479", "8e3579bda4787d20d8c8ab1b0c68112d", 1.000000, True)
"""默认时长: 1.00s"""
方形模糊_II = Transition_meta("方形模糊 II", True, "7384005295770440201", "72501238", "301fe868bf7b1549d6d07af9405beb4a", 1.000000, True)
"""默认时长: 1.00s"""
旋焦 = Transition_meta("旋焦", True, "7215424325036282428", "11286537", "917c209246e975d4f10d9b8c8c78035f", 0.500000, True)
"""默认时长: 0.50s"""
旋转圆球 = Transition_meta("旋转圆球", True, "7377722094806635048", "69481298", "34211e59f420adb42bc00b9a8d36bb6a", 0.800000, True)
"""默认时长: 0.80s"""
旋转圆盘 = Transition_meta("旋转圆盘", True, "7261828356386067005", "19556167", "86ce95075986170812258b247969c972", 1.000000, True)
"""默认时长: 1.00s"""
旋转圆盘_II = Transition_meta("旋转圆盘 II", True, "7262674749258469949", "19727008", "17d1ac181dd7b623059b8aed82d2ef13", 1.000000, True)
"""默认时长: 1.00s"""
旋转快门 = Transition_meta("旋转快门", True, "7350577049968316979", "53358879", "f2b536b7d3f17bc58e0e4957f517ece0", 1.000000, True)
"""默认时长: 1.00s"""
旋转拨盘 = Transition_meta("旋转拨盘", True, "7368844683256009242", "63924504", "88ac2494e5cdec7f874c4157555d2d2b", 1.000000, True)
"""默认时长: 1.00s"""
旋转模糊 = Transition_meta("旋转模糊", True, "7332480491058106943", "44259414", "1a28e7fbb2a177240786bd945fb9ca7e", 1.200000, True)
"""默认时长: 1.20s"""
旋转穿越 = Transition_meta("旋转穿越", True, "7343092798993732148", "49228871", "e05493559e59bf7f4c4a9ea5a5d212de", 1.800000, True)
"""默认时长: 1.80s"""
旋转纵深 = Transition_meta("旋转纵深", True, "7368687055225754153", "63822177", "e717dfe6ccb3c6a6c6a6f70987b1a894", 0.900000, True)
"""默认时长: 0.90s"""
旋转翻页 = Transition_meta("旋转翻页", True, "7320577375752688165", "38717232", "31a897fbdd402adaf84724fb28ef606b", 0.800000, True)
"""默认时长: 0.80s"""
旋转震动 = Transition_meta("旋转震动", True, "7326861725213397514", "41492871", "70bea2644a8dc8bc2b24102d8fa90ca4", 0.600000, True)
"""默认时长: 0.60s"""
无限穿越_I = Transition_meta("无限穿越 I", True, "7036984568536109581", "1465694", "3ee3fc9318dc2315d250f0baa1763e5b", 1.600000, True)
"""默认时长: 1.60s"""
无限穿越_II = Transition_meta("无限穿越 II", True, "7034717113130422791", "1458828", "b87498756c478952cf7c804234f97bbb", 1.600000, True)
"""默认时长: 1.60s"""
旧胶片 = Transition_meta("旧胶片", True, "7099310030138118687", "1933296", "782110cae96a4f9ed73f6a85d0610a7a", 0.500000, False)
"""默认时长: 0.50s"""
旧胶片_II = Transition_meta("旧胶片 II", True, "7111634884153578014", "3114014", "79901fab61f0b8c2960c73a78e84e5a3", 0.500000, True)
"""默认时长: 0.50s"""
时光穿梭 = Transition_meta("时光穿梭", True, "7306853312400200229", "31645629", "74eab27c1dc1a568b851a2e543682058", 1.100000, True)
"""默认时长: 1.10s"""
星光 = Transition_meta("星光", True, "7177201869612126777", "7339355", "2215320b9ba4138c53f1f7b9d0c58b54", 1.500000, True)
"""默认时长: 1.50s"""
星光叠化 = Transition_meta("星光叠化", True, "7321658733497422363", "39173243", "f6d691dd1f991655b2826964c3883772", 0.800000, True)
"""默认时长: 0.80s"""
星星_III = Transition_meta("星星 III", True, "7293358903176204851", "26885516", "1ece838a7bfd2c8b1b0daf25d5776d22", 0.500000, True)
"""默认时长: 0.50s"""
星星吸入 = Transition_meta("星星吸入", True, "7312716430875562506", "34540914", "6ce2a58bc6a3df532a3c1ca890c97394", 1.000000, True)
"""默认时长: 1.00s"""
星星模糊 = Transition_meta("星星模糊", True, "7206157339253019197", "10169537", "28556f2cabd470e0da1a9ddf16d76198", 0.800000, True)
"""默认时长: 0.80s"""
春日光斑 = Transition_meta("春日光斑", True, "7330599151685603875", "43351778", "5d872c46167c2f25f897ae1fc7625c8d", 1.000000, True)
"""默认时长: 1.00s"""
暧昧光晕 = Transition_meta("暧昧光晕", True, "7268613185337299513", "20954940", "ab82749d799477631ae63c081ad569d1", 0.800000, True)
"""默认时长: 0.80s"""
曝光拉丝 = Transition_meta("曝光拉丝", True, "7308617539452408358", "32432969", "56eaaf319007193c199f17554890abb4", 2.000000, True)
"""默认时长: 2.00s"""
曝光摇镜 = Transition_meta("曝光摇镜", True, "7283720497513108025", "24147753", "e0ee1d0a29d1138f7a3b673ffbad91d5", 0.700000, True)
"""默认时长: 0.70s"""
未来光谱 = Transition_meta("未来光谱", True, "7176890183940313658", "7307905", "7974c984bf60d60079cc03be5928f74d", 0.800000, True)
"""默认时长: 0.80s"""
未来光谱II = Transition_meta("未来光谱II", True, "7176914791267570232", "7312585", "524895c4bce265b44ffa8ac92bf0dd6a", 0.800000, True)
"""默认时长: 0.80s"""
条形模糊 = Transition_meta("条形模糊", True, "7122387202725646862", "3675841", "0a5742430e336b3a1e1b6ff9983c5d25", 1.000000, True)
"""默认时长: 1.00s"""
模糊放大 = Transition_meta("模糊放大", True, "7301280654015074842", "29614872", "7c0ef1a54495f7cd9343efe2acc57b26", 1.000000, True)
"""默认时长: 1.00s"""
模糊缩小 = Transition_meta("模糊缩小", True, "7297133348567126566", "28141206", "742e708ac73c3a335a41133684c488ed", 1.200000, True)
"""默认时长: 1.20s"""
横条挤压 = Transition_meta("横条挤压", True, "7369507828668568116", "64687184", "6bbc30d59ef4fd16e4ba6656129cfd95", 1.200000, True)
"""默认时长: 1.20s"""
横移模糊 = Transition_meta("横移模糊", True, "7316901787762430491", "36950128", "aa2ce5c9b13a62881d04f9c23aa30678", 0.800000, True)
"""默认时长: 0.80s"""
水墨 = Transition_meta("水墨", True, "6789847231873683976", "2912466", "d1dd3dd8905f0b96be756bd34be1a84d", 0.500000, True)
"""默认时长: 0.50s"""
水滴 = Transition_meta("水滴", True, "7218875183413596730", "11765299", "d5fa6a1daecd2c45b0414626a69e7674", 0.500000, True)
"""默认时长: 0.50s"""
水滴_II = Transition_meta("水滴 II", True, "7231860840452854332", "13482623", "eebf40246476d57ccbf8bbdf15864864", 0.900000, True)
"""默认时长: 0.90s"""
水滴_III = Transition_meta("水滴 III", True, "7337571999885038130", "46608908", "32eea5171000b838f2eb74941fb751d7", 1.100000, True)
"""默认时长: 1.10s"""
汇聚 = Transition_meta("汇聚", True, "7308666709932511753", "32470148", "3bb1668888e7e87764d03b15733370fb", 1.000000, True)
"""默认时长: 1.00s"""
泡泡模糊 = Transition_meta("泡泡模糊", True, "7159097688955294222", "5663559", "10478b300821fa6eccadf67b07b63208", 1.000000, True)
"""默认时长: 1.00s"""
波光粼粼 = Transition_meta("波光粼粼", True, "7361758664182469157", "59511491", "da913924bc6975821de103b371d540ff", 1.166600, True)
"""默认时长: 1.17s"""
波动 = Transition_meta("波动", True, "7169480114860724773", "6500749", "af314da6343d025cc0f5d668d2fa0a7b", 0.500000, True)
"""默认时长: 0.50s"""
波动_II = Transition_meta("波动 II", True, "7308652550574576138", "32459394", "dd709d2dd83add664f3cbd45893438f7", 0.400000, True)
"""默认时长: 0.40s"""
波动故障 = Transition_meta("波动故障", True, "7223312837320380983", "12349835", "bd7d819531a9d2b044f823080aa0fc1c", 0.600000, True)
"""默认时长: 0.60s"""
流光 = Transition_meta("流光", True, "7316789832833831461", "36847370", "686a5ae873f34ac400ee8ad6a8658d68", 1.000000, True)
"""默认时长: 1.00s"""
涂鸦放大 = Transition_meta("涂鸦放大", True, "7239925851335168569", "14573363", "2a29109cf3c013e6f7770a28cba4154a", 1.500000, True)
"""默认时长: 1.50s"""
溶解推进 = Transition_meta("溶解推进", True, "7348406367394206271", "52246665", "e6c9fda251c612d8cdf69ddef055e410", 0.806000, True)
"""默认时长: 0.81s"""
滑动弹出 = Transition_meta("滑动弹出", True, "7343237606043292200", "49343171", "bb190e71a692bc20d9060b22b4311896", 1.000000, True)
"""默认时长: 1.00s"""
滑动放大 = Transition_meta("滑动放大", True, "7327132595190239759", "41576555", "a746b6b7c2e83275d90864d0b28173aa", 1.000000, True)
"""默认时长: 1.00s"""
滑块拼贴 = Transition_meta("滑块拼贴", True, "7239990715307004477", "14594823", "c8552ba32a7e8804013a8a1b977e23c1", 1.500000, True)
"""默认时长: 1.50s"""
漩涡扭曲 = Transition_meta("漩涡扭曲", True, "7308653984888132123", "32460372", "fedeb478c6e4d39282dfe1ad13ee653a", 0.700000, True)
"""默认时长: 0.70s"""
炫光 = Transition_meta("炫光", True, "6726707814028284423", "4202524", "a3fd6266c293496fd9480884a93fb90e", 0.500000, True)
"""默认时长: 0.50s"""
炫光_II = Transition_meta("炫光 II", True, "6950255790762496548", "4202530", "aafb556352016d087cddd1939ada20f8", 0.500000, False)
"""默认时长: 0.50s"""
炫光_III = Transition_meta("炫光 III", True, "6950255930160189988", "4202529", "5ed29701053e9f7640ecf8dcfc34c7cc", 0.500000, False)
"""默认时长: 0.50s"""
炫光弹动 = Transition_meta("炫光弹动", True, "7348337133838406194", "52201950", "113a7490b314d57a7dea4826e056ff99", 1.000000, True)
"""默认时长: 1.00s"""
炫光扫描 = Transition_meta("炫光扫描", True, "7371717412736995903", "66131585", "4bd676f9001765af20ac02b252da5575", 1.466660, True)
"""默认时长: 1.47s"""
炸弹 = Transition_meta("炸弹", True, "7076321483282190878", "1632990", "e0a1a6b556395c054ce97d73b6d1ef25", 0.500000, True)
"""默认时长: 0.50s"""
烟雾弹 = Transition_meta("烟雾弹", True, "7366189026677625359", "62284094", "58dced44162cefabdc709058b7583d65", 1.400000, True)
"""默认时长: 1.40s"""
热成像 = Transition_meta("热成像", True, "7112344011737666061", "3141662", "9ddbaf68f325c10f04ba84f22272cf40", 1.000000, True)
"""默认时长: 1.00s"""
燃烧 = Transition_meta("燃烧", True, "7089309494550729253", "1722848", "0f42e514001c30186e1c9c68e1ebfee9", 0.500000, True)
"""默认时长: 0.50s"""
燃烧_II = Transition_meta("燃烧 II", True, "7089307363806548510", "1722824", "164c1073bde892dcd9f21d8026fb3cbd", 0.500000, True)
"""默认时长: 0.50s"""
燃烧_III = Transition_meta("燃烧 III", True, "7088523814102897188", "1714536", "da10f2f4ae0aa70ad4d61b2c750aef6b", 0.500000, True)
"""默认时长: 0.50s"""
爆米花 = Transition_meta("爆米花", True, "7075173004560306724", "1623902", "3b70ab38b467c15d463b018b05a420e2", 0.500000, True)
"""默认时长: 0.50s"""
爆闪 = Transition_meta("爆闪", True, "7255132261584998969", "18010162", "68768628ef11bee5b3887f0dbd7f7c6c", 1.000000, True)
"""默认时长: 1.00s"""
爆闪_II = Transition_meta("爆闪 II", True, "7259635767096382011", "19102212", "96e672a98b09ef157224e8b1399ae316", 0.600000, True)
"""默认时长: 0.60s"""
爱心冲击 = Transition_meta("爱心冲击", True, "6789846355742298632", "2916680", "6ca91f7bba738e2e4a67cbf8104eb7b0", 0.500000, True)
"""默认时长: 0.50s"""
爱心模糊 = Transition_meta("爱心模糊", True, "7226945634312393274", "12851969", "3dfdf5cbfe44b5271b9e41acb15ddc37", 0.600000, True)
"""默认时长: 0.60s"""
爱心气球 = Transition_meta("爱心气球", True, "7267895649599754808", "20810100", "6b969705ffc616c0ad03c1e0fc039bd7", 1.000000, True)
"""默认时长: 1.00s"""
环形色散 = Transition_meta("环形色散", True, "7384745397022888488", "72761824", "608a4f0f4729821ff115f72bfb57a909", 0.900000, True)
"""默认时长: 0.90s"""
玻璃破碎 = Transition_meta("玻璃破碎", True, "7242225450628420133", "14930013", "55aa86f7d52f2e3471574b51aedfffe8", 1.000000, True)
"""默认时长: 1.00s"""
玻璃破碎_II = Transition_meta("玻璃破碎 II", True, "7249622034878042661", "16373363", "f77fe839adb1ca6cddc086834a514b79", 1.000000, True)
"""默认时长: 1.00s"""
珠光模糊 = Transition_meta("珠光模糊", True, "7181370814594290234", "7738323", "75984d0cab40abfd59ec5d7ede711496", 1.000000, True)
"""默认时长: 1.00s"""
生气 = Transition_meta("生气", True, "7070430937900651016", "1600475", "be7a4f8a24aafb10db343e51e72fead2", 0.500000, False)
"""默认时长: 0.50s"""
电光 = Transition_meta("电光", True, "7186953120490983997", "8298317", "6142261f8bd0361a56d15a3d408c20ab", 1.000000, True)
"""默认时长: 1.00s"""
电光_II = Transition_meta("电光 II", True, "7292990637350064690", "26773684", "e8a9edb89dae57afad5dfd6b707a6b57", 1.300000, True)
"""默认时长: 1.30s"""
百叶窗_II = Transition_meta("百叶窗 II", True, "7389190159989740072", "74345085", "0786c1d4057bf47fbdb5f6bfeab8a0f3", 0.800000, True)
"""默认时长: 0.80s"""
相片切换 = Transition_meta("相片切换", True, "7324946677305971226", "40583461", "0bcab7309cd00dc17a95071b62282d0a", 0.700000, True)
"""默认时长: 0.70s"""
相片拼贴 = Transition_meta("相片拼贴", True, "7212523710685647420", "10917367", "bdff0041ed99b812568c15e5a7c5d798", 0.600000, True)
"""默认时长: 0.60s"""
空间弹动 = Transition_meta("空间弹动", True, "7265321906830578235", "20330329", "e86c774726c177ee17fd90f63750cf78", 1.000000, False)
"""默认时长: 1.00s"""
空间弹动_II = Transition_meta("空间弹动 II", True, "7269664953584325179", "21121644", "adf0c9abb5c1399909318bb603f28ad1", 1.000000, False)
"""默认时长: 1.00s"""
空间弹动_III= Transition_meta("空间弹动 III", True, "7265322078276948535", "20330339", "d8c4ad960be7cfbe8093fa26076ce000", 1.000000, False)
"""默认时长: 1.00s"""
空间弹动_IV = Transition_meta("空间弹动 IV", True, "7270393974517404215", "21261060", "fb42b8f0a30fe4a0c81c292460aabdbd", 1.000000, False)
"""默认时长: 1.00s"""
空间旋转 = Transition_meta("空间旋转", True, "7127563142359421471", "3878325", "07c37c8bcf40b83415aa6f223de2cd8a", 1.000000, True)
"""默认时长: 1.00s"""
空间旋转_II = Transition_meta("空间旋转 II", True, "7137983390896099871", "4360464", "43927ed137278ab2c3cf8a4933cb4169", 1.000000, True)
"""默认时长: 1.00s"""
空间旋转_III= Transition_meta("空间旋转 III", True, "7138602593751667207", "4382158", "7baa76e42959ee273c278389d359fc59", 1.000000, True)
"""默认时长: 1.00s"""
空间翻转 = Transition_meta("空间翻转", True, "7218870491400901157", "11764147", "0ea4c7c316341196f21440967330f063", 1.200000, True)
"""默认时长: 1.20s"""
空间翻转_II = Transition_meta("空间翻转 II", True, "7223591053973000761", "12371701", "ee9309f01cc53522243198c4ba69ab96", 1.200000, True)
"""默认时长: 1.20s"""
空间跳跃 = Transition_meta("空间跳跃", True, "7309399317662405146", "32858947", "82c5ef6e77c7178c7ca45d8549b87578", 0.633000, True)
"""默认时长: 0.63s"""
穿越 = Transition_meta("穿越", True, "7152422191944962567", "5083535", "80fb974789637e8175557c7c3e649c0e", 1.000000, True)
"""默认时长: 1.00s"""
穿越_II = Transition_meta("穿越 II", True, "7152354215132664357", "5076093", "aa3181f829fe16f72540cc0ec7dfb171", 1.000000, True)
"""默认时长: 1.00s"""
穿越_III = Transition_meta("穿越 III", True, "7341295618863665690", "48498880", "6d6fa95fe1414d4b4a45db9ddec0ee9b", 0.800000, True)
"""默认时长: 0.80s"""
立体翻转 = Transition_meta("立体翻转", True, "7353088031705797159", "54820217", "3746e458c37ab10f2aaa1ac83dee99f6", 0.800000, True)
"""默认时长: 0.80s"""
立体翻页 = Transition_meta("立体翻页", True, "7156512800867619335", "5379189", "ac010354774404d6b8e092120ab76772", 0.800000, True)
"""默认时长: 0.80s"""
立体翻页_II = Transition_meta("立体翻页 II", True, "7156527319274754568", "5381749", "a033fe7038252ba812a4377ff3326acf", 0.800000, True)
"""默认时长: 0.80s"""
竖向拉伸 = Transition_meta("竖向拉伸", True, "7384005384349946418", "72501228", "ac2563343aceb1b399c6b97b2b21f567", 1.000000, True)
"""默认时长: 1.00s"""
竖移模糊 = Transition_meta("竖移模糊", True, "7270505237935297085", "21300860", "4f77c735f448ec5f6df27f21d88e4ee6", 0.600000, True)
"""默认时长: 0.60s"""
粉色反转片 = Transition_meta("粉色反转片", True, "7200360240393491000", "9504701", "80529c6e270d25d9fa6e4babb45346c7", 0.800000, True)
"""默认时长: 0.80s"""
纸团 = Transition_meta("纸团", True, "7238905266912105019", "14451527", "283ecb29f26d13d371658f0b8b476776", 0.700000, True)
"""默认时长: 0.70s"""
翻转冲屏 = Transition_meta("翻转冲屏", True, "7275914638267519525", "22253379", "c1ebaab317335c387d342a3d0b42a65b", 1.200000, True)
"""默认时长: 1.20s"""
翻页_II = Transition_meta("翻页 II", True, "7221478593803588152", "12108759", "7720214c69eaa3203c3edda2027b28d4", 0.900000, True)
"""默认时长: 0.90s"""
聚光灯 = Transition_meta("聚光灯", True, "7325700559556579878", "40923539", "43853a772e195442e07760b04fb236dd", 1.100000, True)
"""默认时长: 1.10s"""
胶片定格 = Transition_meta("胶片定格", True, "7211146962513433147", "10764691", "1a96476b4a04acd24a1b5a7f293fc2eb", 1.000000, True)
"""默认时长: 1.00s"""
胶片擦除 = Transition_meta("胶片擦除", True, "7308265370480022026", "32274061", "4bbb3dcb507832529d7a18020c8fc88d", 0.800000, True)
"""默认时长: 0.80s"""
胶片融化 = Transition_meta("胶片融化", True, "7346474643827462667", "51067351", "563d0dfa49528bb59646384d8a18552a", 0.700000, True)
"""默认时长: 0.70s"""
胶片闪光 = Transition_meta("胶片闪光", True, "7356486482271408666", "56656394", "d3eb0fe7d4088694cc0f9ca02cad07b2", 1.000000, True)
"""默认时长: 1.00s"""
色块故障 = Transition_meta("色块故障", True, "7104539089629614606", "2483334", "1f60c6b995a4cf2212dfd9038f738706", 3.000000, False)
"""默认时长: 3.00s"""
色差故障 = Transition_meta("色差故障", True, "6724239785205961228", "2918075", "9de90519d59e432b81c38423aa0393d7", 1.000000, False)
"""默认时长: 1.00s"""
色彩溶解_IV = Transition_meta("色彩溶解 IV", True, "7171714374912971271", "6736571", "a113cd4e04b969f3d988d76899885d42", 0.800000, True)
"""默认时长: 0.80s"""
色彩溶解_V = Transition_meta("色彩溶解 V", True, "7171714652248740365", "6736575", "da37129b95501377039f01acfded91fc", 0.800000, True)
"""默认时长: 0.80s"""
色散晃镜 = Transition_meta("色散晃镜", True, "7340477409478578738", "48127374", "554ea6d10cd7fbb24ccd24bd91d8c7e1", 0.600000, True)
"""默认时长: 0.60s"""
色散闪烁 = Transition_meta("色散闪烁", True, "7234416277974946365", "13830295", "2d9f72076aeefe8f52dfd1a012cd5127", 0.800000, True)
"""默认时长: 0.80s"""
色散闪烁_II = Transition_meta("色散闪烁 II", True, "7281584246882308665", "23586159", "5f501bb3da1bcbd2ffadca8b916eba81", 0.700000, True)
"""默认时长: 0.70s"""
荧光爆闪 = Transition_meta("荧光爆闪", True, "7342499359503684150", "48938221", "a2d70591b5f8dcc52298426ca626c931", 0.800000, True)
"""默认时长: 0.80s"""
菱格翻转 = Transition_meta("菱格翻转", True, "6983867136510792206", "1187052", "99c0d1524575c7f7020cd77d36a6b008", 1.450000, True)
"""默认时长: 1.45s"""
蓝光扫描 = Transition_meta("蓝光扫描", True, "7275176500381356599", "22119723", "95462badbbb87bd7dc4e1d7b04e58306", 1.000000, True)
"""默认时长: 1.00s"""
蓝色反转片 = Transition_meta("蓝色反转片", True, "7200358812316865085", "9504705", "41e718fd6dbac560c6c7a23afc66e50b", 0.800000, True)
"""默认时长: 0.80s"""
融化 = Transition_meta("融化", True, "7198096122970116663", "9261283", "a0db335169668ca09f5244aa487730c0", 1.000000, True)
"""默认时长: 1.00s"""
融化_II = Transition_meta("融化 II", True, "7200339965442527803", "9503051", "74a83d45bdccf5d27bd4b55ddd2733f3", 1.000000, True)
"""默认时长: 1.00s"""
负片下滑 = Transition_meta("负片下滑", True, "7302412902181376539", "29999964", "e2db0036d057c27aea3460f3442aedf9", 0.600000, True)
"""默认时长: 0.60s"""
超赞 = Transition_meta("超赞", True, "7070430749547041293", "1600477", "e0bd13b237d73eb121473c442c752a23", 0.500000, True)
"""默认时长: 0.50s"""
透镜故障 = Transition_meta("透镜故障", True, "7097849004062413343", "1889546", "bc652327bcde0e6bf9db8a89d371dd05", 0.500000, True)
"""默认时长: 0.50s"""
重叠上滑 = Transition_meta("重叠上滑", True, "7232587870672785980", "13582109", "aea42365eeb8cd0df3e4e422cde45e8a", 1.200000, True)
"""默认时长: 1.20s"""
金色光斑 = Transition_meta("金色光斑", True, "7317211103652483621", "37131315", "f9224f91ef353fefa3bae96af26a447e", 0.800000, True)
"""默认时长: 0.80s"""
钱兔无量 = Transition_meta("钱兔无量", True, "7189608212193088060", "8605167", "a6c068f7790c563231b8df2b5796d60c", 1.500000, True)
"""默认时长: 1.50s"""
长曝光 = Transition_meta("长曝光", True, "7306435255286633010", "31452163", "c239e26c5f99cf83cabd28f63d04b93f", 1.000000, True)
"""默认时长: 1.00s"""
闪光灯 = Transition_meta("闪光灯", True, "6986584807543149063", "4202532", "9abfb7452d046a1dafd4d9525b58ec3a", 1.000000, True)
"""默认时长: 1.00s"""
闪光灯_II = Transition_meta("闪光灯 II", True, "7244074212158083641", "15250161", "1fcc7fccf7829d94f2747938fcb84706", 1.900000, True)
"""默认时长: 1.90s"""
闪光灯_III = Transition_meta("闪光灯 III", True, "7246234663755190839", "15638113", "5af30d0f877301d5235b925ccbda0703", 0.800000, True)
"""默认时长: 0.80s"""
闪动光斑 = Transition_meta("闪动光斑", True, "6777178510050988551", "4202525", "06560e9ea51f532b18b7e5ae23bd2b9c", 0.500000, False)
"""默认时长: 0.50s"""
闪动光斑_II = Transition_meta("闪动光斑 II", True, "7148374073716773407", "4840333", "ffeb2bd8b46b0a212c1fbf004aeac626", 1.000000, True)
"""默认时长: 1.00s"""
闪回 = Transition_meta("闪回", True, "7250427149318885945", "16638473", "0a22de17ce5c2fd97f2bd77aa115de77", 0.200000, True)
"""默认时长: 0.20s"""
闪屏故障 = Transition_meta("闪屏故障", True, "7348352782744687130", "52211013", "a76337e1d1e2301f5d13fd7c90c41282", 1.000000, True)
"""默认时长: 1.00s"""
闪黑_II = Transition_meta("闪黑 II", True, "7264932863613604412", "20257185", "1ecd9bf4057919c5aa78002f97e715de", 0.600000, True)
"""默认时长: 0.60s"""
闹钟 = Transition_meta("闹钟", True, "7074854214479909390", "1621980", "eabbd46c7d68fe93406dd55d4178a574", 0.500000, False)
"""默认时长: 0.50s"""
雪雾 = Transition_meta("雪雾", True, "7309372378096603699", "32838061", "776c40711e9f0f6f32570bc12ea50f91", 1.700000, True)
"""默认时长: 1.70s"""
震动_II = Transition_meta("震动 II", True, "7195815265337086520", "9041507", "f5685f90de96d6541417f0331f84de8a", 1.000000, True)
"""默认时长: 1.00s"""
震动缩小 = Transition_meta("震动缩小", True, "7339865466506056207", "47887388", "3cb961ebfd78ef43742e78bca2d04d06", 1.100000, True)
"""默认时长: 1.10s"""
霓虹闪光 = Transition_meta("霓虹闪光", True, "7337938801882305074", "46839548", "60cee393e1ddf8c117ca6856e474d47d", 0.600000, True)
"""默认时长: 0.60s"""
霓虹闪光_II = Transition_meta("霓虹闪光 II", True, "7337946710041170470", "46846588", "b87a9bf7d6c8e93cc9873ccb47ffc4d0", 0.500000, True)
"""默认时长: 0.50s"""
飘雪 = Transition_meta("飘雪", True, "7169510140138230285", "6506905", "b373d6de281f9cc9cec4b52b0f498517", 2.000000, True)
"""默认时长: 2.00s"""
飘雪_II = Transition_meta("飘雪 II", True, "7170983464416580133", "6658449", "f6e6d83024f30ae2ecf739e15e98813a", 2.000000, True)
"""默认时长: 2.00s"""
马赛克_II = Transition_meta("马赛克 II", True, "7322278354579624486", "39369063", "c2c4fdb0da65e27a073eaba6fcf8dd2a", 0.800000, True)
"""默认时长: 0.80s"""
鱼眼 = Transition_meta("鱼眼", True, "7158359902950265352", "5508285", "0319d3f53fd0e79e7e7165f27d7eb9bb", 0.800000, True)
"""默认时长: 0.80s"""
鱼眼_II = Transition_meta("鱼眼 II", True, "7152723523721499167", "5096381", "6705e7c01ad8518db1428a34b1357d8f", 0.800000, True)
"""默认时长: 0.80s"""
鱼眼_III = Transition_meta("鱼眼 III", True, "7270399429297836605", "21261750", "cdaf9cd4712f5f8061110dfed13738fd", 1.333300, True)
"""默认时长: 1.33s"""
黑白摇镜 = Transition_meta("黑白摇镜", True, "7306819191724577331", "31620427", "cc6bea0aa49c6824aa42d0448d6d0080", 0.700000, True)
"""默认时长: 0.70s"""
黑色反转片 = Transition_meta("黑色反转片", True, "7202075814085530149", "9683173", "8e31bcdedda0fe123ad1a71a967ecaa1", 0.800000, True)
"""默认时长: 0.80s"""
File diff suppressed because it is too large Load Diff
-777
View File
@@ -1,777 +0,0 @@
"""定义文本片段及其相关类"""
import json
import uuid
from copy import deepcopy
from typing import Dict, Tuple, Any, List
from typing import Union, Optional, Literal
from pyJianYingDraft.metadata.capcut_text_animation_meta import CapCut_Text_intro, CapCut_Text_outro, CapCut_Text_loop_anim
from .time_util import Timerange, tim
from .segment import Clip_settings, Visual_segment
from .animation import Segment_animations, Text_animation
from .metadata import Font_type, Effect_meta
from .metadata import Text_intro, Text_outro, Text_loop_anim
class Text_style:
"""字体样式类"""
size: float
"""字体大小"""
bold: bool
"""是否加粗"""
italic: bool
"""是否斜体"""
underline: bool
"""是否加下划线"""
color: Tuple[float, float, float]
"""字体颜色, RGB三元组, 取值范围为[0, 1]"""
alpha: float
"""字体不透明度"""
align: Literal[0, 1, 2]
"""对齐方式"""
vertical: bool
"""是否为竖排文本"""
letter_spacing: int
"""字符间距"""
line_spacing: int
"""行间距"""
def __init__(self, *, size: float = 8.0, bold: bool = False, italic: bool = False, underline: bool = False,
color: Tuple[float, float, float] = (1.0, 1.0, 1.0), alpha: float = 1.0,
align: Literal[0, 1, 2] = 0, vertical: bool = False,
letter_spacing: int = 0, line_spacing: int = 0):
"""
Args:
size (`float`, optional): 字体大小, 默认为8.0
bold (`bool`, optional): 是否加粗, 默认为否
italic (`bool`, optional): 是否斜体, 默认为否
underline (`bool`, optional): 是否加下划线, 默认为否
color (`Tuple[float, float, float]`, optional): 字体颜色, RGB三元组, 取值范围为[0, 1], 默认为白色
alpha (`float`, optional): 字体不透明度, 取值范围[0, 1], 默认不透明
align (`int`, optional): 对齐方式, 0: 左对齐, 1: 居中, 2: 右对齐, 默认为左对齐
vertical (`bool`, optional): 是否为竖排文本, 默认为否
letter_spacing (`int`, optional): 字符间距, 定义与剪映中一致, 默认为0
line_spacing (`int`, optional): 行间距, 定义与剪映中一致, 默认为0
"""
self.size = size
self.bold = bold
self.italic = italic
self.underline = underline
self.color = color
self.alpha = alpha
self.align = align
self.vertical = vertical
self.letter_spacing = letter_spacing
self.line_spacing = line_spacing
class Text_border:
"""文本描边的参数"""
alpha: float
"""描边不透明度"""
color: Tuple[float, float, float]
"""描边颜色, RGB三元组, 取值范围为[0, 1]"""
width: float
"""描边宽度"""
def __init__(self, *, alpha: float = 1.0, color: Tuple[float, float, float] = (0.0, 0.0, 0.0), width: float = 40.0):
"""
Args:
alpha (`float`, optional): 描边不透明度, 取值范围[0, 1], 默认为1.0
color (`Tuple[float, float, float]`, optional): 描边颜色, RGB三元组, 取值范围为[0, 1], 默认为黑色
width (`float`, optional): 描边宽度, 与剪映中一致, 取值范围为[0, 100], 默认为40.0
"""
self.alpha = alpha
self.color = color
self.width = width / 100.0 * 0.2 # 此映射可能不完全正确
def export_json(self) -> Dict[str, Any]:
"""导出JSON数据, 放置在素材content的styles中"""
return {
"content": {
"solid": {
"alpha": self.alpha,
"color": list(self.color),
}
},
"width": self.width
}
class Text_background:
"""文本背景参数"""
style: Literal[0, 2]
"""背景样式"""
alpha: float
"""背景不透明度"""
color: str
"""背景颜色, 格式为'#RRGGBB'"""
round_radius: float
"""背景圆角半径"""
height: float
"""背景高度"""
width: float
"""背景宽度"""
horizontal_offset: float
"""背景水平偏移"""
vertical_offset: float
"""背景竖直偏移"""
def __init__(self, *, color: str, style: Literal[1, 2] = 1, alpha: float = 1.0, round_radius: float = 0.0,
height: float = 0.14, width: float = 0.14,
horizontal_offset: float = 0.5, vertical_offset: float = 0.5):
"""
Args:
color (`str`): 背景颜色, 格式为'#RRGGBB'
style (`int`, optional): 背景样式, 1和2分别对应剪映中的两种样式, 默认为1
alpha (`float`, optional): 背景不透明度, 与剪映中一致, 取值范围[0, 1], 默认为1.0
round_radius (`float`, optional): 背景圆角半径, 与剪映中一致, 取值范围[0, 1], 默认为0.0
height (`float`, optional): 背景高度, 与剪映中一致, 取值范围为[0, 1], 默认为0.14
width (`float`, optional): 背景宽度, 与剪映中一致, 取值范围为[0, 1], 默认为0.14
horizontal_offset (`float`, optional): 背景水平偏移, 与剪映中一致, 取值范围为[0, 1], 默认为0.5
vertical_offset (`float`, optional): 背景竖直偏移, 与剪映中一致, 取值范围为[0, 1], 默认为0.5
"""
self.style = (0, 2)[style - 1]
self.alpha = alpha
self.color = color
self.round_radius = round_radius
self.height = height
self.width = width
self.horizontal_offset = horizontal_offset * 2 - 1
self.vertical_offset = vertical_offset * 2 - 1
def export_json(self) -> Dict[str, Any]:
"""生成子JSON数据, 在Text_segment导出时合并到其中"""
return {
"background_style": self.style,
"background_color": self.color,
"background_alpha": self.alpha,
"background_round_radius": self.round_radius,
"background_height": self.height,
"background_width": self.width,
"background_horizontal_offset": self.horizontal_offset,
"background_vertical_offset": self.vertical_offset,
}
class Text_shadow:
"""文本阴影参数"""
has_shadow: bool
"""是否启用阴影"""
alpha: float
"""阴影不透明度"""
angle: float
"""阴影角度"""
color: str
"""阴影颜色,格式为'#RRGGBB'"""
distance: float
"""阴影距离"""
smoothing: float
"""阴影平滑度"""
def __init__(self, *, has_shadow: bool = False, alpha: float = 0.9, angle: float = -45.0,
color: str = "#000000", distance: float = 5.0, smoothing: float = 0.45):
"""
Args:
has_shadow (`bool`, optional): 是否启用阴影默认为False
alpha (`float`, optional): 阴影不透明度取值范围[0, 1]默认为0.9
angle (`float`, optional): 阴影角度取值范围[-180, 180], 默认为-45.0
color (`str`, optional): 阴影颜色格式为'#RRGGBB'默认为黑色
distance (`float`, optional): 阴影距离默认为5.0
smoothing (`float`, optional): 阴影平滑度取值范围[0, 1], 默认0.15
"""
self.has_shadow = has_shadow
self.alpha = alpha
self.angle = angle
self.color = color
self.distance = distance
self.smoothing = smoothing
def export_json(self) -> Dict[str, Any]:
"""生成子JSON数据,在Text_segment导出时合并到其中"""
return {
"has_shadow": self.has_shadow,
"shadow_alpha": self.alpha,
"shadow_angle": self.angle,
"shadow_color": self.color,
"shadow_distance": self.distance,
"shadow_smoothing": self.smoothing * 3
}
class TextBubble:
"""文本气泡素材, 与滤镜素材本质上一致"""
global_id: str
"""气泡全局id, 由程序自动生成"""
effect_id: str
resource_id: str
def __init__(self, effect_id: str, resource_id: str):
self.global_id = uuid.uuid4().hex
self.effect_id = effect_id
self.resource_id = resource_id
def export_json(self) -> Dict[str, Any]:
return {
"apply_target_type": 0,
"effect_id": self.effect_id,
"id": self.global_id,
"resource_id": self.resource_id,
"type": "text_shape",
"value": 1.0,
# 不导出path和request_id
}
class TextEffect(TextBubble):
"""文本花字素材, 与滤镜素材本质上也一致"""
def export_json(self) -> Dict[str, Any]:
ret = super().export_json()
ret["type"] = "text_effect"
ret["source_platform"] = 1
return ret
class TextStyleRange:
"""文本样式范围类,用于定义文本特定范围的样式"""
start: int
"""起始位置(包含)"""
end: int
"""结束位置(不包含)"""
style: Text_style
"""字体样式"""
border: Optional[Text_border]
"""文本描边参数,None表示无描边"""
font: Optional[Effect_meta]
"""字体设置,None表示使用全局字体"""
def __init__(self, start: int, end: int, style: Text_style, border: Optional[Text_border] = None, font_str:str = None):
"""创建文本样式范围
Args:
start (`int`): 起始位置包含
end (`int`): 结束位置不包含
style (`Text_style`): 字体样式
border (`Text_border`, optional): 文本描边参数默认为None无描边
font (optional): 字体设置默认为None使用全局字体
"""
self.start = start
self.end = end
self.style = style
self.border = border
if font_str:
try:
font_type = getattr(Font_type, font_str).value
except:
available_fonts = [attr for attr in dir(Font_type) if not attr.startswith('_')]
raise ValueError(f"不支持的字体:{font_str},请使用Font_type中的字体之一:{available_fonts}")
self.font = font_type
def get_range(self) -> List[int]:
"""获取范围列表
Returns:
`List[int]`: [start, end] 形式的范围列表
"""
return [self.start, self.end]
class Text_segment(Visual_segment):
"""文本片段类, 目前仅支持设置基本的字体样式"""
text: str
"""文本内容"""
font: Optional[Effect_meta]
"""字体类型"""
style: Text_style
"""字体样式"""
border: Optional[Text_border]
"""文本描边参数, None表示无描边"""
background: Optional[Text_background]
"""文本背景参数, None表示无背景"""
shadow: Optional[Text_shadow]
"""文本阴影参数, None表示无阴影"""
bubble: Optional[TextBubble]
"""文本气泡效果, 在放入轨道时加入素材列表中"""
effect: Optional[TextEffect]
"""文本花字效果, 在放入轨道时加入素材列表中, 目前仅支持一部分花字效果"""
fixed_width: float
"""固定宽度, -1表示不固定"""
fixed_height: float
"""固定高度, -1表示不固定"""
text_styles: List[TextStyleRange]
"""文本的多种样式列表"""
def __init__(self, text: str, timerange: Timerange, *,
font: Optional[Font_type] = None,
style: Optional[Text_style] = None, clip_settings: Optional[Clip_settings] = None,
border: Optional[Text_border] = None, background: Optional[Text_background] = None,
shadow: Optional[Text_shadow] = None,
fixed_width: int = -1, fixed_height: int = -1):
"""创建文本片段, 并指定其时间信息、字体样式及图像调节设置
片段创建完成后, 可通过`Script_file.add_segment`方法将其添加到轨道中
Args:
text (`str`): 文本内容
timerange (`Timerange`): 片段在轨道上的时间范围
font (`Font_type`, optional): 字体类型, 默认为系统字体
style (`Text_style`, optional): 字体样式, 包含大小/颜色/对齐/透明度等.
clip_settings (`Clip_settings`, optional): 图像调节设置, 默认不做任何变换
border (`Text_border`, optional): 文本描边参数, 默认无描边
background (`Text_background`, optional): 文本背景参数, 默认无背景
fixed_width (`int`, optional): 文本固定宽度像素值, 默认为-1不固定宽度
fixed_height (`int`, optional): 文本固定高度像素值, 默认为-1不固定高度
"""
super().__init__(uuid.uuid4().hex, None, timerange, 1.0, 1.0, clip_settings=clip_settings)
self.text = text
self.font = font.value if font else None
self.style = style or Text_style()
self.border = border
self.background = background
self.shadow = shadow
self.bubble = None
self.effect = None
self.fixed_width = fixed_width
self.fixed_height = fixed_height
self.text_styles = []
# 修改设置特定范围的文本样式的方法
def add_text_style(self, textStyleRange: TextStyleRange) -> "Text_segment":
# 添加新的样式范围
self.text_styles.append(textStyleRange)
return self
@classmethod
def create_from_template(cls, text: str, timerange: Timerange, template: "Text_segment") -> "Text_segment":
"""根据模板创建新的文本片段, 并指定其文本内容"""
new_segment = cls(text, timerange, style=deepcopy(template.style), clip_settings=deepcopy(template.clip_settings),
border=deepcopy(template.border), background=deepcopy(template.background))
new_segment.font = deepcopy(template.font)
# 处理动画等
if template.animations_instance:
new_segment.animations_instance = deepcopy(template.animations_instance)
new_segment.animations_instance.animation_id = uuid.uuid4().hex
new_segment.extra_material_refs.append(new_segment.animations_instance.animation_id)
if template.bubble:
new_segment.add_bubble(template.bubble.effect_id, template.bubble.resource_id)
if template.effect:
new_segment.add_effect(template.effect.effect_id)
return new_segment
def add_animation(self, animation_type: Union[Text_intro, Text_outro, Text_loop_anim,
CapCut_Text_intro, CapCut_Text_outro, CapCut_Text_loop_anim],
duration: Union[str, float] = 500000) -> "Text_segment":
"""将给定的入场/出场/循环动画添加到此片段的动画列表中, 出入场动画的持续时间可以自行设置, 循环动画则会自动填满其余无动画部分
注意: 若希望同时使用循环动画和入出场动画, **先添加出入场动画再添加循环动画**
Args:
animation_type (`Text_intro`, `Text_outro` or `Text_loop_anim`): 文本动画类型.
duration (`str` or `float`, optional): 动画持续时间, 单位为微秒, 仅对入场/出场动画有效.
若传入字符串则会调用`tim()`函数进行解析. 默认为0.5
"""
duration = min(tim(duration), self.target_timerange.duration)
if (isinstance(animation_type, Text_intro) or isinstance(animation_type, CapCut_Text_intro)):
start = 0
elif (isinstance(animation_type, Text_outro) or isinstance(animation_type, CapCut_Text_outro)):
start = self.target_timerange.duration - duration
elif (isinstance(animation_type, Text_loop_anim) or isinstance(animation_type, CapCut_Text_loop_anim)):
intro_trange = self.animations_instance and self.animations_instance.get_animation_trange("in")
outro_trange = self.animations_instance and self.animations_instance.get_animation_trange("out")
start = intro_trange.start if intro_trange else 0
duration = self.target_timerange.duration - start - (outro_trange.duration if outro_trange else 0)
else:
raise TypeError("Invalid animation type %s" % type(animation_type))
if self.animations_instance is None:
self.animations_instance = Segment_animations()
self.extra_material_refs.append(self.animations_instance.animation_id)
self.animations_instance.add_animation(Text_animation(animation_type, start, duration))
return self
def add_bubble(self, effect_id: str, resource_id: str) -> "Text_segment":
"""根据素材信息添加气泡效果, 相应素材信息可通过`Script_file.inspect_material`从模板中获取
Args:
effect_id (`str`): 气泡效果的effect_id
resource_id (`str`): 气泡效果的resource_id
"""
self.bubble = TextBubble(effect_id, resource_id)
self.extra_material_refs.append(self.bubble.global_id)
return self
def add_effect(self, effect_id: str) -> "Text_segment":
"""根据素材信息添加花字效果, 相应素材信息可通过`Script_file.inspect_material`从模板中获取
Args:
effect_id (`str`): 花字效果的effect_id, 也同时是其resource_id
"""
self.effect = TextEffect(effect_id, effect_id)
self.extra_material_refs.append(self.effect.global_id)
return self
def export_material(self) -> Dict[str, Any]:
"""与此文本片段联系的素材, 以此不再单独定义Text_material类"""
# 叠加各类效果的flag
check_flag: int = 7
if self.border:
check_flag |= 8
if self.background:
check_flag |= 16
if self.shadow and self.shadow.has_shadow: # 如果有阴影且启用了阴影
check_flag |= 32 # 添加阴影标志
# 构建styles数组
styles = []
if self.text_styles:
# 创建一个排序后的样式范围列表
sorted_styles = sorted(self.text_styles, key=lambda x: x.start)
# 检查是否需要在开头添加默认样式
if sorted_styles[0].start > 0:
# 添加从0到第一个样式开始的默认样式
default_style = {
"fill": {
"alpha": 1.0,
"content": {
"render_type": "solid",
"solid": {
"alpha": self.style.alpha,
"color": list(self.style.color)
}
}
},
"range": [0, sorted_styles[0].start],
"size": self.style.size,
"bold": self.style.bold,
"italic": self.style.italic,
"underline": self.style.underline,
"strokes": [self.border.export_json()] if self.border else []
}
# 如果有阴影设置,添加到样式中
if self.shadow and self.shadow.has_shadow:
style_item["shadows"] = [
{
"diffuse": self.shadow.smoothing / 6, # diffuse = smoothing/6
"angle": self.shadow.angle,
"content": {
"solid": {
"color": [int(self.shadow.color[1:3], 16)/255,
int(self.shadow.color[3:5], 16)/255,
int(self.shadow.color[5:7], 16)/255]
}
},
"distance": self.shadow.distance,
"alpha": self.shadow.alpha
}
]
# 如果有全局字体设置,添加到样式中
if self.font:
default_style["font"] = {
"id": self.font.resource_id,
"path": "C:/%s.ttf" % self.font.name
}
# 如果有特效设置,添加到样式中
if self.effect:
default_style["effectStyle"] = {
"id": self.effect.effect_id,
"path": "C:" # 并不会真正在此处放置素材文件
}
styles.append(default_style)
# 处理每个样式范围
for i, style_range in enumerate(sorted_styles):
# 添加当前样式范围的样式
style_item = {
"fill": {
"alpha": 1.0,
"content": {
"render_type": "solid",
"solid": {
"alpha": style_range.style.alpha,
"color": list(style_range.style.color)
}
}
},
"range": style_range.get_range(),
"size": style_range.style.size,
"bold": style_range.style.bold,
"italic": style_range.style.italic,
"underline": style_range.style.underline,
"strokes": [style_range.border.export_json()] if style_range.border else []
}
# 如果TextStyleRange有字体设置,优先使用它
if hasattr(style_range, 'font') and style_range.font:
style_item["font"] = {
"id": style_range.font.resource_id,
"path": "C:/%s.ttf" % style_range.font.name
}
# 否则,如果有全局字体设置,使用全局字体
elif self.font:
style_item["font"] = {
"id": self.font.resource_id,
"path": "C:/%s.ttf" % self.font.name
}
# 如果有特效设置,添加到样式中
if self.effect:
style_item["effectStyle"] = {
"id": self.effect.effect_id,
"path": "C:" # 并不会真正在此处放置素材文件
}
styles.append(style_item)
# 检查是否需要在当前样式和下一个样式之间添加默认样式
if i < len(sorted_styles) - 1 and style_range.end < sorted_styles[i+1].start:
# 添加从当前样式结束到下一个样式开始的默认样式
gap_style = {
"fill": {
"alpha": 1.0,
"content": {
"render_type": "solid",
"solid": {
"alpha": self.style.alpha,
"color": list(self.style.color)
}
}
},
"range": [style_range.end, sorted_styles[i+1].start],
"size": self.style.size,
"bold": self.style.bold,
"italic": self.style.italic,
"underline": self.style.underline,
"strokes": [self.border.export_json()] if self.border else []
}
# 如果有全局字体设置,添加到样式中
if self.font:
gap_style["font"] = {
"id": self.font.resource_id,
"path": "C:/%s.ttf" % self.font.name
}
# 如果有特效设置,添加到样式中
if self.effect:
gap_style["effectStyle"] = {
"id": self.effect.effect_id,
"path": "C:" # 并不会真正在此处放置素材文件
}
styles.append(gap_style)
# 检查是否需要在最后一个样式之后添加默认样式
if sorted_styles[-1].end < len(self.text):
# 添加从最后一个样式结束到文本结尾的默认样式
end_style = {
"fill": {
"alpha": 1.0,
"content": {
"render_type": "solid",
"solid": {
"alpha": self.style.alpha,
"color": list(self.style.color)
}
}
},
"range": [sorted_styles[-1].end, len(self.text)],
"size": self.style.size,
"bold": self.style.bold,
"italic": self.style.italic,
"underline": self.style.underline,
"strokes": [self.border.export_json()] if self.border else []
}
# 如果有全局字体设置,添加到样式中
if self.font:
end_style["font"] = {
"id": self.font.resource_id,
"path": "C:/%s.ttf" % self.font.name
}
# 如果有特效设置,添加到样式中
if self.effect:
end_style["effectStyle"] = {
"id": self.effect.effect_id,
"path": "C:" # 并不会真正在此处放置素材文件
}
styles.append(end_style)
else:
# 如果text_styles为空,使用全局样式创建一个默认的style
style_item = {
"fill": {
"alpha": 1.0,
"content": {
"render_type": "solid",
"solid": {
"alpha": self.style.alpha,
"color": list(self.style.color)
}
}
},
"range": [0, len(self.text)],
"size": self.style.size,
"bold": self.style.bold,
"italic": self.style.italic,
"underline": self.style.underline,
"strokes": [self.border.export_json()] if self.border else []
}
# 如果有阴影设置,添加到样式中
if self.shadow and self.shadow.has_shadow:
style_item["shadows"] = [
{
"diffuse": self.shadow.smoothing / 6, # diffuse = smoothing/6
"angle": self.shadow.angle,
"content": {
"solid": {
"color": [int(self.shadow.color[1:3], 16)/255,
int(self.shadow.color[3:5], 16)/255,
int(self.shadow.color[5:7], 16)/255]
}
},
"distance": self.shadow.distance,
"alpha": self.shadow.alpha
}
]
# 如果有全局字体设置,添加到样式中
if self.font:
style_item["font"] = {
"id": self.font.resource_id,
"path": "C:/%s.ttf" % self.font.name # 并不会真正在此处放置字体文件
}
# 如果有特效设置,添加到样式中
if self.effect:
style_item["effectStyle"] = {
"id": self.effect.effect_id,
"path": "C:" # 并不会真正在此处放置素材文件
}
styles.append(style_item)
content_json = {
"styles": styles,
"text": self.text
}
ret = {
"id": self.material_id,
"content": json.dumps(content_json, ensure_ascii=False),
"typesetting": int(self.style.vertical),
"alignment": self.style.align,
"letter_spacing": self.style.letter_spacing * 0.05,
"line_spacing": 0.02 + self.style.line_spacing * 0.05,
"line_feed": 1,
"line_max_width": 0.82,
"force_apply_line_max_width": False,
"check_flag": check_flag,
"type": "text",
"fixed_width": self.fixed_width,
"fixed_height": self.fixed_height,
# 混合 (+4)
# "global_alpha": 1.0,
# 发光 (+64),属性由extra_material_refs记录
# 阴影 (+32)
# "has_shadow": False,
# "shadow_alpha": 0.9,
# "shadow_angle": -45.0,
# "shadow_color": "",
# "shadow_distance": 5.0,
# "shadow_point": {
# "x": 0.6363961030678928,
# "y": -0.6363961030678928
# },
# "shadow_smoothing": 0.45,
# 整体字体设置
"font_category_id": "",
"font_category_name": "",
"font_id": "",
"font_name": "",
"font_path": "",
"font_resource_id": "",
"font_size": 15.0,
"font_source_platform": 0,
"font_team_id": "",
"font_title": "none",
"font_url": "",
"fonts": [] if not self.text_styles else [
# 根据text_styles生成fonts数组
*[{
"category_id": "preset",
"category_name": "剪映预设",
"effect_id": style_range.font.resource_id if hasattr(style_range, 'font') and style_range.font else (self.font.resource_id if self.font else ""),
"file_uri": "",
"id": "BFBA9655-1FE5-41A0-A85D-577EFFF17BDD",
"path": "C:/%s.ttf" % (style_range.font.name if hasattr(style_range, 'font') and style_range.font else (self.font.name if self.font else "")),
"request_id": "20250713102314DA3D8F267527925ADC9A",
"resource_id": style_range.font.resource_id if hasattr(style_range, 'font') and style_range.font else (self.font.resource_id if self.font else ""),
"source_platform": 0,
"team_id": "",
"title": style_range.font.name if hasattr(style_range, 'font') and style_range.font else (self.font.name if self.font else "")
} for style_range in self.text_styles if (hasattr(style_range, 'font') and style_range.font) or self.font]
],
# 似乎会被content覆盖
# "text_alpha": 1.0,
# "text_color": "#FFFFFF",
# "text_curve": None,
# "text_preset_resource_id": "",
# "text_size": 30,
# "underline": False,
}
if self.background:
ret.update(self.background.export_json())
# 添加阴影参数
if self.shadow and self.shadow.has_shadow:
shadow_json = self.shadow.export_json()
ret.update(shadow_json) # 将阴影参数合并到返回的字典中
return ret
-212
View File
@@ -1,212 +0,0 @@
"""轨道类及其元数据"""
import uuid
from enum import Enum
from typing import TypeVar, Generic, Type
from typing import Dict, List, Any, Union
from dataclasses import dataclass
from abc import ABC, abstractmethod
import pyJianYingDraft as draft
from .exceptions import SegmentOverlap
from .segment import Base_segment
from .video_segment import Video_segment, Sticker_segment
from .audio_segment import Audio_segment
from .text_segment import Text_segment
from .effect_segment import Effect_segment, Filter_segment
@dataclass
class Track_meta:
"""与轨道类型关联的轨道元数据"""
segment_type: Union[Type[Video_segment], Type[Audio_segment],
Type[Effect_segment], Type[Filter_segment],
Type[Text_segment], Type[Sticker_segment], None]
"""与轨道关联的片段类型"""
render_index: int
"""默认渲染顺序, 值越大越接近前景"""
allow_modify: bool
"""当被导入时, 是否允许修改"""
class Track_type(Enum):
"""轨道类型枚举
变量名对应type属性, 值表示相应的轨道元数据
"""
video = Track_meta(Video_segment, 0, True)
audio = Track_meta(Audio_segment, 0, True)
effect = Track_meta(Effect_segment, 10000, False)
filter = Track_meta(Filter_segment, 11000, False)
sticker = Track_meta(Sticker_segment, 14000, False)
text = Track_meta(Text_segment, 15000, True) # 原本是14000, 避免与sticker冲突改为15000
adjust = Track_meta(None, 0, False)
"""仅供导入时使用, 不要尝试新建此类型的轨道"""
@staticmethod
def from_name(name: str) -> "Track_type":
"""根据名称获取轨道类型枚举"""
for t in Track_type:
if t.name == name:
return t
raise ValueError("Invalid track type: %s" % name)
class Base_track(ABC):
"""轨道基类"""
track_type: Track_type
"""轨道类型"""
name: str
"""轨道名称"""
track_id: str
"""轨道全局ID"""
render_index: int
"""渲染顺序, 值越大越接近前景"""
@abstractmethod
def export_json(self) -> Dict[str, Any]: ...
Seg_type = TypeVar("Seg_type", bound=Base_segment)
class Track(Base_track, Generic[Seg_type]):
"""非模板模式下的轨道"""
mute: bool
"""是否静音"""
segments: List[Seg_type]
"""该轨道包含的片段列表"""
pending_keyframes: List[Dict[str, Any]]
"""待处理的关键帧列表"""
def __init__(self, track_type: Track_type, name: str, render_index: int, mute: bool):
self.track_type = track_type
self.name = name
self.track_id = uuid.uuid4().hex
self.render_index = render_index
self.mute = mute
self.segments = []
self.pending_keyframes = []
def add_pending_keyframe(self, property_type: str, time: float, value: str) -> None:
"""添加待处理的关键帧
Args:
property_type: 关键帧属性类型
time: 关键帧时间点
value: 关键帧值
"""
self.pending_keyframes.append({
"property_type": property_type,
"time": time,
"value": value
})
def process_pending_keyframes(self) -> None:
"""处理所有待处理的关键帧"""
if not self.pending_keyframes:
return
for kf_info in self.pending_keyframes:
property_type = kf_info["property_type"]
time = kf_info["time"]
value = kf_info["value"]
try:
# 找到时间点对应的片段(时间单位:微秒)
target_time = int(time * 1000000) # 将秒转换为微秒
target_segment = next(
(segment for segment in self.segments
if segment.target_timerange.start <= target_time <= segment.target_timerange.end),
None
)
if target_segment is None:
print(f"警告:在轨道 {self.name} 的时间点 {time}s 找不到对应的片段,跳过此关键帧")
continue
# 将属性类型字符串转换为枚举值
property_enum = getattr(draft.Keyframe_property, property_type)
# 解析value值
if property_type == 'alpha' and value.endswith('%'):
float_value = float(value[:-1]) / 100
elif property_type == 'volume' and value.endswith('%'):
float_value = float(value[:-1]) / 100
elif property_type == 'rotation' and value.endswith('deg'):
float_value = float(value[:-3])
elif property_type in ['saturation', 'contrast', 'brightness']:
if value.startswith('+'):
float_value = float(value[1:])
elif value.startswith('-'):
float_value = -float(value[1:])
else:
float_value = float(value)
else:
float_value = float(value)
# 计算时间偏移量
offset_time = target_time - target_segment.target_timerange.start
# 添加关键帧
target_segment.add_keyframe(property_enum, offset_time, float_value)
print(f"成功添加关键帧: {property_type}{time}s")
except Exception as e:
print(f"添加关键帧失败: {str(e)}")
# 清空待处理的关键帧
self.pending_keyframes = []
@property
def end_time(self) -> int:
"""轨道结束时间, 微秒"""
if len(self.segments) == 0:
return 0
return self.segments[-1].target_timerange.end
@property
def accept_segment_type(self) -> Type[Seg_type]:
"""返回该轨道允许的片段类型"""
return self.track_type.value.segment_type # type: ignore
def add_segment(self, segment: Seg_type) -> "Track[Seg_type]":
"""向轨道中添加一个片段, 添加的片段必须匹配轨道类型且不与现有片段重叠
Args:
segment (Seg_type): 要添加的片段
Raises:
`TypeError`: 新片段类型与轨道类型不匹配
`SegmentOverlap`: 新片段与现有片段重叠
"""
if not isinstance(segment, self.accept_segment_type):
raise TypeError("New segment (%s) is not of the same type as the track (%s)" % (type(segment), self.accept_segment_type))
# 检查片段是否重叠
for seg in self.segments:
if seg.overlaps(segment):
raise SegmentOverlap("New segment overlaps with existing segment [start: {}, end: {}]"
.format(segment.target_timerange.start, segment.target_timerange.end))
self.segments.append(segment)
return self
def export_json(self) -> Dict[str, Any]:
# 为每个片段写入render_index
segment_exports = [seg.export_json() for seg in self.segments]
for seg in segment_exports:
seg["render_index"] = self.render_index
return {
"attribute": int(self.mute),
"flag": 0,
"id": self.track_id,
"is_default_name": len(self.name) == 0,
"name": self.name,
"segments": segment_exports,
"type": self.track_type.name
}
+9 -51
View File
@@ -1,59 +1,17 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "capcut-mate"
version = "1.0.0"
description = "Open source CapCut API tool with MCP support"
readme = "README.md"
requires-python = ">=3.11"
description = "CapCut Mate API Service"
authors = [
{ name = "CapCut Mate Contributors" }
]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
{ name = "Hommy", email = "taohongmin51@gmail.com" }
]
requires-python = ">=3.11"
dependencies = [
"requests>=2.28.0",
"Pillow>=9.0.0",
"numpy>=1.21.0",
"opencv-python>=4.6.0",
"ffmpeg-python>=0.2.0",
"pydantic>=2.0.0",
"email-validator>=2.2.0",
"fastapi>=0.100.0",
"uvicorn[standard]>=0.23.0",
"imageio>=2.31.0",
"psutil>=5.9.0",
"flask>=2.3.0",
"oss2>=2.17.0",
"json5>=0.9.0",
"flasgger>=0.9.0",
"pymediainfo>=7.0.1",
"requests>=2.32.5",
"uiautomation>=2.0.29",
"uvicorn[standard]>=0.35.0",
]
[project.optional-dependencies]
mcp = [
"mcp>=1.0.0",
"aiohttp>=3.8.0",
"websockets>=11.0",
"jsonrpc-base>=2.2.0",
"jsonrpc-websocket>=3.1.0",
"jsonrpc-async>=2.1.0",
]
[project.urls]
Homepage = "https://github.com/sun-guannan/CapCutAPI"
Repository = "https://github.com/sun-guannan/CapCutAPI.git"
Issues = "https://github.com/sun-guannan/CapCutAPI/issues"
[tool.uv]
dev-dependencies = []
[tool.hatch.build.targets.wheel]
packages = ["pyJianYingDraft", "settings"]
-715
View File
@@ -1,715 +0,0 @@
import os
import re
import pyJianYingDraft as draft
import shutil
from util import zip_draft, is_windows_path
from oss import upload_to_oss
from typing import Dict, Literal
from draft_cache import DRAFT_CACHE
from save_task_cache import DRAFT_TASKS, get_task_status, update_tasks_cache, update_task_field, increment_task_field, update_task_fields, create_task
from downloader import download_audio, download_file, download_image, download_video
from concurrent.futures import ThreadPoolExecutor, as_completed
import imageio.v2 as imageio
import subprocess
import json
from get_duration_impl import get_video_duration
import uuid
import threading
from collections import OrderedDict
import time
import requests # Import requests for making HTTP calls
import logging
# Import configuration
from settings import IS_CAPCUT_ENV, IS_UPLOAD_DRAFT
# --- Get your Logger instance ---
# The name here must match the logger name you configured in app.py
logger = logging.getLogger('flask_video_generator')
# Define task status enumeration type
TaskStatus = Literal["initialized", "processing", "completed", "failed", "not_found"]
def build_asset_path(draft_folder: str, draft_id: str, asset_type: str, material_name: str) -> str:
"""
Build asset file path
:param draft_folder: Draft folder path
:param draft_id: Draft ID
:param asset_type: Asset type (audio, image, video)
:param material_name: Material name
:return: Built path
"""
if is_windows_path(draft_folder):
if os.name == 'nt': # 'nt' for Windows
draft_real_path = os.path.join(draft_folder, draft_id, "assets", asset_type, material_name)
else:
windows_drive, windows_path = re.match(r'([a-zA-Z]:)(.*)', draft_folder).groups()
parts = [p for p in windows_path.split('\\') if p]
draft_real_path = os.path.join(windows_drive, *parts, draft_id, "assets", asset_type, material_name)
draft_real_path = draft_real_path.replace('/', '\\')
else:
draft_real_path = os.path.join(draft_folder, draft_id, "assets", asset_type, material_name)
return draft_real_path
def save_draft_background(draft_id, draft_folder, task_id):
"""Background save draft to OSS"""
try:
# Get draft information from global cache
if draft_id not in DRAFT_CACHE:
task_status = {
"status": "failed",
"message": f"Draft {draft_id} does not exist in cache",
"progress": 0,
"completed_files": 0,
"total_files": 0,
"draft_url": ""
}
update_tasks_cache(task_id, task_status) # Use new cache management function
logger.error(f"Draft {draft_id} does not exist in cache, task {task_id} failed.")
return
script = DRAFT_CACHE[draft_id]
logger.info(f"Successfully retrieved draft {draft_id} from cache.")
# Update task status to processing
task_status = {
"status": "processing",
"message": "Preparing draft files",
"progress": 0,
"completed_files": 0,
"total_files": 0,
"draft_url": ""
}
update_tasks_cache(task_id, task_status) # Use new cache management function
logger.info(f"Task {task_id} status updated to 'processing': Preparing draft files.")
# Delete possibly existing draft_id folder
if os.path.exists(draft_id):
logger.warning(f"Deleting existing draft folder (current working directory): {draft_id}")
shutil.rmtree(draft_id)
logger.info(f"Starting to save draft: {draft_id}")
# Save draft
current_dir = os.path.dirname(os.path.abspath(__file__))
draft_folder_for_duplicate = draft.Draft_folder(current_dir)
# Choose different template directory based on configuration
template_dir = "template" if IS_CAPCUT_ENV else "template_jianying"
draft_folder_for_duplicate.duplicate_as_template(template_dir, draft_id)
# Update task status
update_task_field(task_id, "message", "Updating media file metadata")
update_task_field(task_id, "progress", 5)
logger.info(f"Task {task_id} progress 5%: Updating media file metadata.")
update_media_metadata(script, task_id)
download_tasks = []
audios = script.materials.audios
if audios:
for audio in audios:
remote_url = audio.remote_url
material_name = audio.material_name
# Use helper function to build path
if draft_folder:
audio.replace_path = build_asset_path(draft_folder, draft_id, "audio", material_name)
if not remote_url:
logger.warning(f"Audio file {material_name} has no remote_url, skipping download.")
continue
# Add audio download task
download_tasks.append({
'type': 'audio',
'func': download_file,
'args': (remote_url, os.path.join(current_dir, f"{draft_id}/assets/audio/{material_name}")),
'material': audio
})
# Collect video and image download tasks
videos = script.materials.videos
if videos:
for video in videos:
remote_url = video.remote_url
material_name = video.material_name
if video.material_type == 'photo':
# Use helper function to build path
if draft_folder:
video.replace_path = build_asset_path(draft_folder, draft_id, "image", material_name)
if not remote_url:
logger.warning(f"Image file {material_name} has no remote_url, skipping download.")
continue
# Add image download task
download_tasks.append({
'type': 'image',
'func': download_file,
'args': (remote_url, os.path.join(current_dir, f"{draft_id}/assets/image/{material_name}")),
'material': video
})
elif video.material_type == 'video':
# Use helper function to build path
if draft_folder:
video.replace_path = build_asset_path(draft_folder, draft_id, "video", material_name)
if not remote_url:
logger.warning(f"Video file {material_name} has no remote_url, skipping download.")
continue
# Add video download task
download_tasks.append({
'type': 'video',
'func': download_file,
'args': (remote_url, os.path.join(current_dir, f"{draft_id}/assets/video/{material_name}")),
'material': video
})
update_task_field(task_id, "message", f"Collected {len(download_tasks)} download tasks in total")
update_task_field(task_id, "progress", 10)
logger.info(f"Task {task_id} progress 10%: Collected {len(download_tasks)} download tasks in total.")
# Execute all download tasks concurrently
downloaded_paths = []
completed_files = 0
if download_tasks:
logger.info(f"Starting concurrent download of {len(download_tasks)} files...")
# Use thread pool for concurrent downloads, maximum concurrency of 16
with ThreadPoolExecutor(max_workers=16) as executor:
# Submit all download tasks
future_to_task = {
executor.submit(task['func'], *task['args']): task
for task in download_tasks
}
# Wait for all tasks to complete
for future in as_completed(future_to_task):
task = future_to_task[future]
try:
local_path = future.result()
downloaded_paths.append(local_path)
# Update task status - only update completed files count
completed_files += 1
update_task_field(task_id, "completed_files", completed_files)
task_status = get_task_status(task_id)
completed = task_status["completed_files"]
total = len(download_tasks)
update_task_field(task_id, "total_files", total)
# Download part accounts for 60% of the total progress
download_progress = 10 + int((completed / total) * 60)
update_task_field(task_id, "progress", download_progress)
update_task_field(task_id, "message", f"Downloaded {completed}/{total} files")
logger.info(f"Task {task_id}: Successfully downloaded {task['type']} file, progress {download_progress}.")
except Exception as e:
logger.error(f"Task {task_id}: Download {task['type']} file failed: {str(e)}", exc_info=True)
# Continue processing other files, don't interrupt the entire process
logger.info(f"Task {task_id}: Concurrent download completed, downloaded {len(downloaded_paths)} files in total.")
# Update task status - Start saving draft information
update_task_field(task_id, "progress", 70)
update_task_field(task_id, "message", "Saving draft information")
logger.info(f"Task {task_id} progress 70%: Saving draft information.")
script.dump(os.path.join(current_dir, f"{draft_id}/draft_info.json"))
logger.info(f"Draft information has been saved to {os.path.join(current_dir, draft_id)}/draft_info.json.")
draft_url = ""
# Only upload draft information when IS_UPLOAD_DRAFT is True
if IS_UPLOAD_DRAFT:
# Update task status - Start compressing draft
update_task_field(task_id, "progress", 80)
update_task_field(task_id, "message", "Compressing draft files")
logger.info(f"Task {task_id} progress 80%: Compressing draft files.")
# Compress the entire draft directory
zip_path = zip_draft(draft_id)
logger.info(f"Draft directory {os.path.join(current_dir, draft_id)} has been compressed to {zip_path}.")
# Update task status - Start uploading to OSS
update_task_field(task_id, "progress", 90)
update_task_field(task_id, "message", "Uploading to cloud storage")
logger.info(f"Task {task_id} progress 90%: Uploading to cloud storage.")
# Upload to OSS
draft_url = upload_to_oss(zip_path)
logger.info(f"Draft archive has been uploaded to OSS, URL: {draft_url}")
update_task_field(task_id, "draft_url", draft_url)
# Clean up temporary files
if os.path.exists(os.path.join(current_dir, draft_id)):
shutil.rmtree(os.path.join(current_dir, draft_id))
logger.info(f"Cleaned up temporary draft folder: {os.path.join(current_dir, draft_id)}")
# Update task status - Completed
update_task_field(task_id, "status", "completed")
update_task_field(task_id, "progress", 100)
update_task_field(task_id, "message", "Draft creation completed")
logger.info(f"Task {task_id} completed, draft URL: {draft_url}")
return draft_url
except Exception as e:
# Update task status - Failed
update_task_fields(task_id,
status="failed",
message=f"Failed to save draft: {str(e)}")
logger.error(f"Saving draft {draft_id} task {task_id} failed: {str(e)}", exc_info=True)
return ""
def query_task_status(task_id: str):
return get_task_status(task_id)
def save_draft_impl(draft_id: str, draft_folder: str = None) -> Dict[str, str]:
"""Start a background task to save the draft"""
logger.info(f"Received save draft request: draft_id={draft_id}, draft_folder={draft_folder}")
try:
# Generate a unique task ID
task_id = draft_id
create_task(task_id)
logger.info(f"Task {task_id} has been created.")
# Changed to synchronous execution
return {
"success": True,
"draft_url": save_draft_background(draft_id, draft_folder, task_id)
}
# # Start a background thread to execute the task
# thread = threading.Thread(
# target=save_draft_background,
# args=(draft_id, draft_folder, task_id)
# )
# thread.start()
except Exception as e:
logger.error(f"Failed to start save draft task {draft_id}: {str(e)}", exc_info=True)
return {
"success": False,
"error": str(e)
}
def update_media_metadata(script, task_id=None):
"""
Update metadata for all media files in the script (duration, width/height, etc.)
:param script: Draft script object
:param task_id: Optional task ID for updating task status
:return: None
"""
# Process audio file metadata
audios = script.materials.audios
if not audios:
logger.info("No audio files found in the draft.")
else:
for audio in audios:
remote_url = audio.remote_url
material_name = audio.material_name
if not remote_url:
logger.warning(f"Warning: Audio file {material_name} has no remote_url, skipped.")
continue
try:
video_command = [
'ffprobe',
'-v', 'error',
'-select_streams', 'v:0',
'-show_entries', 'stream=codec_type',
'-of', 'json',
remote_url
]
video_result = subprocess.check_output(video_command, stderr=subprocess.STDOUT)
video_result_str = video_result.decode('utf-8')
# Find JSON start position (first '{')
video_json_start = video_result_str.find('{')
if video_json_start != -1:
video_json_str = video_result_str[video_json_start:]
video_info = json.loads(video_json_str)
if 'streams' in video_info and len(video_info['streams']) > 0:
logger.warning(f"Warning: Audio file {material_name} contains video tracks, skipped its metadata update.")
continue
except Exception as e:
logger.error(f"Error occurred while checking if audio {material_name} contains video streams: {str(e)}", exc_info=True)
# Get audio duration and set it
try:
duration_result = get_video_duration(remote_url)
if duration_result["success"]:
if task_id:
update_task_field(task_id, "message", f"Processing audio metadata: {material_name}")
# Convert seconds to microseconds
audio.duration = int(duration_result["output"] * 1000000)
logger.info(f"Successfully obtained audio {material_name} duration: {duration_result['output']:.2f} seconds ({audio.duration} microseconds).")
# Update timerange for all segments using this audio material
for track_name, track in script.tracks.items():
if track.track_type == draft.Track_type.audio:
for segment in track.segments:
if isinstance(segment, draft.Audio_segment) and segment.material_id == audio.material_id:
# Get current settings
current_target = segment.target_timerange
current_source = segment.source_timerange
speed = segment.speed.speed
# If the end time of source_timerange exceeds the new audio duration, adjust it
if current_source.end > audio.duration or current_source.end <= 0:
# Adjust source_timerange to fit the new audio duration
new_source_duration = audio.duration - current_source.start
if new_source_duration <= 0:
logger.warning(f"Warning: Audio segment {segment.segment_id} start time {current_source.start} exceeds audio duration {audio.duration}, will skip this segment.")
continue
# Update source_timerange
segment.source_timerange = draft.Timerange(current_source.start, new_source_duration)
# Update target_timerange based on new source_timerange and speed
new_target_duration = int(new_source_duration / speed)
segment.target_timerange = draft.Timerange(current_target.start, new_target_duration)
logger.info(f"Adjusted audio segment {segment.segment_id} timerange to fit the new audio duration.")
else:
logger.warning(f"Warning: Unable to get audio {material_name} duration: {duration_result['error']}.")
except Exception as e:
logger.error(f"Error occurred while getting audio {material_name} duration: {str(e)}", exc_info=True)
# Process video and image file metadata
videos = script.materials.videos
if not videos:
logger.info("No video or image files found in the draft.")
else:
for video in videos:
remote_url = video.remote_url
material_name = video.material_name
if not remote_url:
logger.warning(f"Warning: Media file {material_name} has no remote_url, skipped.")
continue
if video.material_type == 'photo':
# Use imageio to get image width/height and set it
try:
if task_id:
update_task_field(task_id, "message", f"Processing image metadata: {material_name}")
img = imageio.imread(remote_url)
video.height, video.width = img.shape[:2]
logger.info(f"Successfully set image {material_name} dimensions: {video.width}x{video.height}.")
except Exception as e:
logger.error(f"Failed to set image {material_name} dimensions: {str(e)}, using default values 1920x1080.", exc_info=True)
video.width = 1920
video.height = 1080
elif video.material_type == 'video':
# Get video duration and width/height information
try:
if task_id:
update_task_field(task_id, "message", f"Processing video metadata: {material_name}")
# Use ffprobe to get video information
command = [
'ffprobe',
'-v', 'error',
'-select_streams', 'v:0', # Select the first video stream
'-show_entries', 'stream=width,height,duration',
'-show_entries', 'format=duration',
'-of', 'json',
remote_url
]
result = subprocess.check_output(command, stderr=subprocess.STDOUT)
result_str = result.decode('utf-8')
# Find JSON start position (first '{')
json_start = result_str.find('{')
if json_start != -1:
json_str = result_str[json_start:]
info = json.loads(json_str)
if 'streams' in info and len(info['streams']) > 0:
stream = info['streams'][0]
# Set width and height
video.width = int(stream.get('width', 0))
video.height = int(stream.get('height', 0))
logger.info(f"Successfully set video {material_name} dimensions: {video.width}x{video.height}.")
# Set duration
# Prefer stream duration, if not available use format duration
duration = stream.get('duration') or info['format'].get('duration', '0')
video.duration = int(float(duration) * 1000000) # Convert to microseconds
logger.info(f"Successfully obtained video {material_name} duration: {float(duration):.2f} seconds ({video.duration} microseconds).")
# Update timerange for all segments using this video material
for track_name, track in script.tracks.items():
if track.track_type == draft.Track_type.video:
for segment in track.segments:
if isinstance(segment, draft.Video_segment) and segment.material_id == video.material_id:
# Get current settings
current_target = segment.target_timerange
current_source = segment.source_timerange
speed = segment.speed.speed
# If the end time of source_timerange exceeds the new video duration, adjust it
if current_source.end > video.duration or current_source.end <= 0:
# Adjust source_timerange to fit the new video duration
new_source_duration = video.duration - current_source.start
if new_source_duration <= 0:
logger.warning(f"Warning: Video segment {segment.segment_id} start time {current_source.start} exceeds video duration {video.duration}, will skip this segment.")
continue
# Update source_timerange
segment.source_timerange = draft.Timerange(current_source.start, new_source_duration)
# Update target_timerange based on new source_timerange and speed
new_target_duration = int(new_source_duration / speed)
segment.target_timerange = draft.Timerange(current_target.start, new_target_duration)
logger.info(f"Adjusted video segment {segment.segment_id} timerange to fit the new video duration.")
else:
logger.warning(f"Warning: Unable to get video {material_name} stream information.")
# Set default values
video.width = 1920
video.height = 1080
else:
logger.warning(f"Warning: Could not find JSON data in ffprobe output.")
# Set default values
video.width = 1920
video.height = 1080
except Exception as e:
logger.error(f"Error occurred while getting video {material_name} information: {str(e)}, using default values 1920x1080.", exc_info=True)
# Set default values
video.width = 1920
video.height = 1080
# Try to get duration separately
try:
duration_result = get_video_duration(remote_url)
if duration_result["success"]:
# Convert seconds to microseconds
video.duration = int(duration_result["output"] * 1000000)
logger.info(f"Successfully obtained video {material_name} duration: {duration_result['output']:.2f} seconds ({video.duration} microseconds).")
else:
logger.warning(f"Warning: Unable to get video {material_name} duration: {duration_result['error']}.")
except Exception as e2:
logger.error(f"Error occurred while getting video {material_name} duration: {str(e2)}.", exc_info=True)
# After updating all segments' timerange, check if there are time range conflicts in each track, and delete the later segment in case of conflict
logger.info("Checking track segment time range conflicts...")
for track_name, track in script.tracks.items():
# Use a set to record segment indices that need to be deleted
to_remove = set()
# Check for conflicts between all segments
for i in range(len(track.segments)):
# Skip if current segment is already marked for deletion
if i in to_remove:
continue
for j in range(len(track.segments)):
# Skip self-comparison and segments already marked for deletion
if i == j or j in to_remove:
continue
# Check if there is a conflict
if track.segments[i].overlaps(track.segments[j]):
# Always keep the segment with the smaller index (added first)
later_index = max(i, j)
logger.warning(f"Time range conflict between segments {track.segments[min(i, j)].segment_id} and {track.segments[later_index].segment_id} in track {track_name}, deleting the later segment")
to_remove.add(later_index)
# Delete marked segments from back to front to avoid index change issues
for index in sorted(to_remove, reverse=True):
track.segments.pop(index)
# After updating all segments' timerange, recalculate the total duration of the script
max_duration = 0
for track_name, track in script.tracks.items():
for segment in track.segments:
max_duration = max(max_duration, segment.end)
script.duration = max_duration
logger.info(f"Updated script total duration to: {script.duration} microseconds.")
# Process all pending keyframes in tracks
logger.info("Processing pending keyframes...")
for track_name, track in script.tracks.items():
if hasattr(track, 'pending_keyframes') and track.pending_keyframes:
logger.info(f"Processing {len(track.pending_keyframes)} pending keyframes in track {track_name}...")
track.process_pending_keyframes()
logger.info(f"Pending keyframes in track {track_name} have been processed.")
def query_script_impl(draft_id: str, force_update: bool = True):
"""
Query draft script object, with option to force refresh media metadata
:param draft_id: Draft ID
:param force_update: Whether to force refresh media metadata, default is True
:return: Script object
"""
# Get draft information from global cache
if draft_id not in DRAFT_CACHE:
logger.warning(f"Draft {draft_id} does not exist in cache.")
return None
script = DRAFT_CACHE[draft_id]
logger.info(f"Retrieved draft {draft_id} from cache.")
# If force_update is True, force refresh media metadata
if force_update:
logger.info(f"Force refreshing media metadata for draft {draft_id}.")
update_media_metadata(script)
# Return script object
return script
def download_script(draft_id: str, draft_folder: str = None, script_data: Dict = None) -> Dict[str, str]:
"""Downloads the draft script and its associated media assets.
This function fetches the script object from a remote API,
then iterates through its materials (audios, videos, images)
to download them to the specified draft folder. It also updates
task status and progress throughout the process.
:param draft_id: The ID of the draft to download.
:param draft_folder: The base folder where the draft's assets will be stored.
If None, assets will be stored directly under a folder named
after the draft_id in the current working directory.
:return: A dictionary indicating success and, if successful, the URL where the draft
would eventually be saved (though this function primarily focuses on download).
If failed, it returns an error message.
"""
logger.info(f"Starting to download draft: {draft_id} to folder: {draft_folder}")
# Copy template to target directory
template_path = os.path.join("./", 'template') if IS_CAPCUT_ENV else os.path.join("./", 'template_jianying')
new_draft_path = os.path.join(draft_folder, draft_id)
if os.path.exists(new_draft_path):
logger.warning(f"Deleting existing draft target folder: {new_draft_path}")
shutil.rmtree(new_draft_path)
# Copy draft folder
shutil.copytree(template_path, new_draft_path)
try:
# 1. Fetch the script from the remote endpoint
if script_data is None:
query_url = "https://cut-jianying-vdvswivepm.cn-hongkong.fcapp.run/query_script"
headers = {"Content-Type": "application/json"}
payload = {"draft_id": draft_id}
logger.info(f"Attempting to get script for draft ID: {draft_id} from {query_url}.")
response = requests.post(query_url, headers=headers, json=payload)
response.raise_for_status() # Raise an exception for HTTP errors (4xx or 5xx)
script_data = json.loads(response.json().get('output'))
logger.info(f"Successfully retrieved script data for draft {draft_id}.")
else:
logger.info(f"Using provided script_data, skipping remote retrieval.")
# Collect download tasks
download_tasks = []
# Collect audio download tasks
audios = script_data.get('materials',{}).get('audios',[])
if audios:
for audio in audios:
remote_url = audio['remote_url']
material_name = audio['name']
# Use helper function to build path
if draft_folder:
audio['path']=build_asset_path(draft_folder, draft_id, "audio", material_name)
logger.debug(f"Local path for audio {material_name}: {audio['path']}")
if not remote_url:
logger.warning(f"Audio file {material_name} has no remote_url, skipping download.")
continue
# Add audio download task
download_tasks.append({
'type': 'audio',
'func': download_file,
'args': (remote_url, audio['path']),
'material': audio
})
# Collect video and image download tasks
videos = script_data['materials']['videos']
if videos:
for video in videos:
remote_url = video['remote_url']
material_name = video['material_name']
if video['type'] == 'photo':
# Use helper function to build path
if draft_folder:
video['path'] = build_asset_path(draft_folder, draft_id, "image", material_name)
if not remote_url:
logger.warning(f"Image file {material_name} has no remote_url, skipping download.")
continue
# Add image download task
download_tasks.append({
'type': 'image',
'func': download_file,
'args': (remote_url, video['path']),
'material': video
})
elif video['type'] == 'video':
# Use helper function to build path
if draft_folder:
video['path'] = build_asset_path(draft_folder, draft_id, "video", material_name)
if not remote_url:
logger.warning(f"Video file {material_name} has no remote_url, skipping download.")
continue
# Add video download task
download_tasks.append({
'type': 'video',
'func': download_file,
'args': (remote_url, video['path']),
'material': video
})
# Execute all download tasks concurrently
downloaded_paths = []
completed_files = 0
if download_tasks:
logger.info(f"Starting concurrent download of {len(download_tasks)} files...")
# Use thread pool for concurrent downloads, maximum concurrency of 16
with ThreadPoolExecutor(max_workers=16) as executor:
# Submit all download tasks
future_to_task = {
executor.submit(task['func'], *task['args']): task
for task in download_tasks
}
# Wait for all tasks to complete
for future in as_completed(future_to_task):
task = future_to_task[future]
try:
local_path = future.result()
downloaded_paths.append(local_path)
# Update task status - only update completed files count
completed_files += 1
logger.info(f"Downloaded {completed_files}/{len(download_tasks)} files.")
except Exception as e:
logger.error(f"Failed to download {task['type']} file {task['args'][0]}: {str(e)}", exc_info=True)
logger.error("Download failed.")
# Continue processing other files, don't interrupt the entire process
logger.info(f"Concurrent download completed, downloaded {len(downloaded_paths)} files in total.")
"""Write draft file content to file"""
with open(f"{draft_folder}/{draft_id}/draft_info.json", "w", encoding="utf-8") as f:
f.write(json.dumps(script_data))
logger.info(f"Draft has been saved.")
# No draft_url for download, but return success
return {"success": True, "message": f"Draft {draft_id} and its assets downloaded successfully"}
except requests.exceptions.RequestException as e:
logger.error(f"API request failed: {e}", exc_info=True)
return {"success": False, "error": f"Failed to fetch script from API: {str(e)}"}
except Exception as e:
logger.error(f"Unexpected error during download: {e}", exc_info=True)
return {"success": False, "error": f"An unexpected error occurred: {str(e)}"}
if __name__ == "__main__":
print('hello')
download_script("dfd_cat_1751012163_a7e8c315",'/Users/sunguannan/Movies/JianyingPro/User Data/Projects/com.lveditor.draft')
-142
View File
@@ -1,142 +0,0 @@
from collections import OrderedDict
import threading
from typing import Dict, Any
# Using OrderedDict to implement LRU cache, limiting the maximum number to 1000
DRAFT_TASKS: Dict[str, dict] = OrderedDict() # Using Dict for type hinting
MAX_TASKS_CACHE_SIZE = 1000
def update_tasks_cache(task_id: str, task_status: dict) -> None:
"""Update task status LRU cache
:param task_id: Task ID
:param task_status: Task status information dictionary
"""
if task_id in DRAFT_TASKS:
# If the key exists, delete the old item
DRAFT_TASKS.pop(task_id)
elif len(DRAFT_TASKS) >= MAX_TASKS_CACHE_SIZE:
# If the cache is full, delete the least recently used item (the first item)
DRAFT_TASKS.popitem(last=False)
# Add new item to the end (most recently used)
DRAFT_TASKS[task_id] = task_status
def update_task_field(task_id: str, field: str, value: Any) -> None:
"""Update a single field in the task status
:param task_id: Task ID
:param field: Field name to update
:param value: New value for the field
"""
if task_id in DRAFT_TASKS:
# Copy the current status, modify the specified field, then update the cache
task_status = DRAFT_TASKS[task_id].copy()
task_status[field] = value
# Delete the old item and add the updated item
DRAFT_TASKS.pop(task_id)
DRAFT_TASKS[task_id] = task_status
else:
# If the task doesn't exist, create a default status and set the specified field
task_status = {
"status": "initialized",
"message": "Task initialized",
"progress": 0,
"completed_files": 0,
"total_files": 0,
"draft_url": ""
}
task_status[field] = value
# If the cache is full, delete the least recently used item
if len(DRAFT_TASKS) >= MAX_TASKS_CACHE_SIZE:
DRAFT_TASKS.popitem(last=False)
# Add new item
DRAFT_TASKS[task_id] = task_status
def update_task_fields(task_id: str, **fields) -> None:
"""Update multiple fields in the task status
:param task_id: Task ID
:param fields: Fields to update and their values, provided as keyword arguments
"""
if task_id in DRAFT_TASKS:
# Copy the current status, modify the specified fields, then update the cache
task_status = DRAFT_TASKS[task_id].copy()
for field, value in fields.items():
task_status[field] = value
# Delete the old item and add the updated item
DRAFT_TASKS.pop(task_id)
DRAFT_TASKS[task_id] = task_status
else:
# If the task doesn't exist, create a default status and set the specified fields
task_status = {
"status": "initialized",
"message": "Task initialized",
"progress": 0,
"completed_files": 0,
"total_files": 0,
"draft_url": ""
}
for field, value in fields.items():
task_status[field] = value
# If the cache is full, delete the least recently used item
if len(DRAFT_TASKS) >= MAX_TASKS_CACHE_SIZE:
DRAFT_TASKS.popitem(last=False)
# Add new item
DRAFT_TASKS[task_id] = task_status
def increment_task_field(task_id: str, field: str, increment: int = 1) -> None:
"""Increment a numeric field in the task status
:param task_id: Task ID
:param field: Field name to increment
:param increment: Value to increment by, default is 1
"""
if task_id in DRAFT_TASKS:
# Copy the current status, increment the specified field, then update the cache
task_status = DRAFT_TASKS[task_id].copy()
if field in task_status and isinstance(task_status[field], (int, float)):
task_status[field] += increment
else:
task_status[field] = increment
# Delete the old item and add the updated item
DRAFT_TASKS.pop(task_id)
DRAFT_TASKS[task_id] = task_status
def get_task_status(task_id: str) -> dict:
"""Get task status
:param task_id: Task ID
:return: Task status information dictionary
"""
task_status = DRAFT_TASKS.get(task_id, {
"status": "not_found",
"message": "Task does not exist",
"progress": 0,
"completed_files": 0,
"total_files": 0,
"draft_url": ""
})
# If the task is found, update its position in the LRU cache
if task_id in DRAFT_TASKS:
# First delete, then add to the end, implementing LRU update
update_tasks_cache(task_id, task_status)
return task_status
def create_task(task_id: str) -> None:
"""Create a new task and initialize its status
:param task_id: Task ID
"""
task_status = {
"status": "initialized",
"message": "Task initialized",
"progress": 0,
"completed_files": 0,
"total_files": 0,
"draft_url": ""
}
update_tasks_cache(task_id, task_status)
-30
View File
@@ -1,30 +0,0 @@
from schemas.add_video import AddVideoRequest
from schemas.add_audio import AddAudioRequest
from schemas.create_draft import CreateDraftRequest
from schemas.add_subtitle import AddSubtitleRequest
from schemas.add_text import AddTextRequest, TextStyleData
from schemas.add_image import AddImageRequest
from schemas.add_keyframe import AddVideoKeyframeRequest
from schemas.add_effect import AddEffectRequest
from schemas.query_script import QueryScriptRequest
from schemas.save_draft import SaveDraftRequest
from schemas.query_draft_status import QueryDraftStatusRequest
from schemas.generate_draft_url import GenerateDraftURLRequest
from schemas.add_sticker import AddStickerRequest
__all__ = [
"AddVideoRequest",
"AddAudioRequest",
"CreateDraftRequest",
"AddSubtitleRequest",
"AddTextRequest",
"TextStyleData",
"AddImageRequest",
"AddVideoKeyframeRequest",
"AddEffectRequest",
"QueryScriptRequest",
"SaveDraftRequest",
"QueryDraftStatusRequest",
"GenerateDraftURLRequest",
"AddStickerRequest",
]
-18
View File
@@ -1,18 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class AddAudioRequest(BaseModel):
audio_url: str = Field(..., description="音频 URL(必需)")
draft_folder: Optional[str] = None
draft_id: Optional[str] = None
start: float = 0
end: Optional[float] = None
volume: float = 1.0
target_start: float = 0
speed: float = 1.0
track_name: str = "audio_main"
duration: Optional[float] = None
effect_type: Optional[str] = None
effect_params: Optional[List[Any]] = None
width: int = 1080
height: int = 1920
-14
View File
@@ -1,14 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class AddEffectRequest(BaseModel):
effect_type: str = Field(..., description="特效类型(必需)")
start: float = 0
end: float = 3.0
effect_category: str = "scene"
draft_id: Optional[str] = None
track_name: str = "effect_01"
params: Optional[List[Any]] = None
width: int = 1080
height: int = 1920
-39
View File
@@ -1,39 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class AddImageRequest(BaseModel):
image_url: str = Field(..., description="图片 URL(必需)")
draft_folder: Optional[str] = None
draft_id: Optional[str] = None
width: int = 1080
height: int = 1920
start: float = 0
end: float = 3.0
transform_y: float = 0
scale_x: float = 1
scale_y: float = 1
transform_x: float = 0
track_name: str = "image_main"
relative_index: int = 0
animation: Optional[str] = None
animation_duration: float = 0.5
intro_animation: Optional[str] = None
intro_animation_duration: float = 0.5
outro_animation: Optional[str] = None
outro_animation_duration: float = 0.5
combo_animation: Optional[str] = None
combo_animation_duration: float = 0.5
transition: Optional[str] = None
transition_duration: float = 0.5
mask_type: Optional[str] = None
mask_center_x: float = 0.0
mask_center_y: float = 0.0
mask_size: float = 0.5
mask_rotation: float = 0.0
mask_feather: float = 0.0
mask_invert: bool = False
mask_rect_width: Optional[float] = None
mask_round_corner: Optional[float] = None
background_blur: Optional[int] = None
-13
View File
@@ -1,13 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class AddVideoKeyframeRequest(BaseModel):
draft_id: Optional[str] = None
track_name: str = "video_main"
property_type: str = "alpha"
time: float = 0.0
value: str = "1.0"
property_types: Optional[List[str]] = None
times: Optional[List[float]] = None
values: Optional[List[str]] = None
-21
View File
@@ -1,21 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class AddStickerRequest(BaseModel):
sticker_id: str = Field(..., description="贴纸 ID(必需)")
start: float = 0
end: float = 5.0
draft_id: Optional[str] = None
transform_y: float = 0
transform_x: float = 0
alpha: float = 1.0
flip_horizontal: bool = False
flip_vertical: bool = False
rotation: float = 0.0
scale_x: float = 1.0
scale_y: float = 1.0
track_name: str = "sticker_main"
relative_index: int = 0
width: int = 1080
height: int = 1920
-30
View File
@@ -1,30 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class AddSubtitleRequest(BaseModel):
srt: str = Field(..., description="字幕内容或 URL(必需)")
draft_id: Optional[str] = None
time_offset: float = 0.0
font: str = "思源粗宋"
font_size: float = 5.0
bold: bool = False
italic: bool = False
underline: bool = False
font_color: str = "#FFFFFF"
vertical: bool = False
alpha: float = 1.0
border_alpha: float = 1.0
border_color: str = "#000000"
border_width: float = 0.0
background_color: str = "#000000"
background_style: int = 0
background_alpha: float = 0.0
transform_x: float = 0.0
transform_y: float = -0.8
scale_x: float = 1.0
scale_y: float = 1.0
rotation: float = 0.0
track_name: str = "subtitle"
width: int = 1080
height: int = 1920
-56
View File
@@ -1,56 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class TextStyleData(BaseModel):
start: int = 0
end: int = 0
font: Optional[str] = None
style: Optional[Dict[str, Any]] = None
border: Optional[Dict[str, Any]] = None
class AddTextRequest(BaseModel):
text: str = Field(..., description="文字内容(必需)")
start: float = Field(..., description="开始时间(必需)")
end: float = Field(..., description="结束时间(必需)")
draft_id: Optional[str] = None
transform_y: float = 0
transform_x: float = 0
font: str = "文轩体"
color: Optional[str] = None
font_color: str = "#FF0000"
size: Optional[float] = None
font_size: float = 8.0
track_name: str = "text_main"
vertical: bool = False
alpha: Optional[float] = None
font_alpha: float = 1.0
width: int = 1080
height: int = 1920
fixed_width: float = -1
fixed_height: float = -1
border_alpha: float = 1.0
border_color: str = "#000000"
border_width: float = 0.0
background_color: str = "#000000"
background_style: int = 0
background_alpha: float = 0.0
background_round_radius: float = 0.0
background_height: float = 0.14
background_width: float = 0.14
background_horizontal_offset: float = 0.5
background_vertical_offset: float = 0.5
shadow_enabled: bool = False
shadow_alpha: float = 0.9
shadow_angle: float = -45.0
shadow_color: str = "#000000"
shadow_distance: float = 5.0
shadow_smoothing: float = 0.15
bubble_effect_id: Optional[str] = None
bubble_resource_id: Optional[str] = None
effect_effect_id: Optional[str] = None
intro_animation: Optional[str] = None
intro_duration: float = 0.5
outro_animation: Optional[str] = None
outro_duration: float = 0.5
text_styles: List[TextStyleData] = []
-34
View File
@@ -1,34 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class AddVideoRequest(BaseModel):
video_url: str = Field(..., description="视频 URL(必需)")
draft_folder: Optional[str] = None
draft_id: Optional[str] = None
start: float = 0
end: float = 0
width: int = 1080
height: int = 1920
transform_y: float = 0
scale_x: float = 1
scale_y: float = 1
transform_x: float = 0
speed: float = 1.0
target_start: float = 0
track_name: str = "video_main"
relative_index: int = 0
duration: Optional[float] = None
transition: Optional[str] = None
transition_duration: float = 0.5
volume: float = 1.0
mask_type: Optional[str] = None
mask_center_x: float = 0.5
mask_center_y: float = 0.5
mask_size: float = 1.0
mask_rotation: float = 0.0
mask_feather: float = 0.0
mask_invert: bool = False
mask_rect_width: Optional[float] = None
mask_round_corner: Optional[float] = None
background_blur: Optional[int] = None
-7
View File
@@ -1,7 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class CreateDraftRequest(BaseModel):
width: int = 1080
height: int = 1920
-7
View File
@@ -1,7 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class GenerateDraftURLRequest(BaseModel):
draft_id: str = Field(..., description="草稿 ID(必需)")
draft_folder: Optional[str] = None
-5
View File
@@ -1,5 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class QueryDraftStatusRequest(BaseModel):
task_id: str = Field(..., description="任务 ID(必需)")
-6
View File
@@ -1,6 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class QueryScriptRequest(BaseModel):
draft_id: str = Field(..., description="草稿 ID(必需)")
force_update: bool = True
-6
View File
@@ -1,6 +0,0 @@
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
class SaveDraftRequest(BaseModel):
draft_id: str = Field(..., description="草稿 ID(必需)")
draft_folder: Optional[str] = None
-36
View File
@@ -1,36 +0,0 @@
"""
配置包入口导出所有配置
"""
# 从local模块导入所有配置,local模块已经导入了env和base模块的配置
from .local import *
__all__ = [
"IS_CAPCUT_ENV",
"API_KEYS",
"MODEL_CONFIG",
"PURCHASE_LINKS",
"LICENSE_CONFIG"
]
# 提供一个获取平台信息的辅助函数
def get_platform_info():
"""
获取平台信息用于script_file.py中的dumps方法cap_cut需要返回platform信息
Returns:
dict: 平台信息字典
"""
if not IS_CAPCUT_ENV:
return None
return {
"app_id": 359289,
"app_source": "cc",
"app_version": "6.5.0",
"device_id": "c4ca4238a0b923820dcc509a6f75849b",
"hard_disk_id": "307563e0192a94465c0e927fbc482942",
"mac_address": "c3371f2d4fb02791c067ce44d8fb4ed5",
"os": "mac",
"os_version": "15.5"
}
-66
View File
@@ -1,66 +0,0 @@
"""
本地配置模块用于从本地配置文件中加载配置
"""
import os
import json5 # 替换原来的json模块
# 配置文件路径
CONFIG_FILE_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "config.json")
# 默认配置
IS_CAPCUT_ENV = True
# 默认域名配置
DRAFT_DOMAIN = "https://www.install-ai-guider.top"
# 默认预览路由
PREVIEW_ROUTER = "/draft/downloader"
# 是否上传草稿文件
IS_UPLOAD_DRAFT = False
# 端口号
PORT = 9000
OSS_CONFIG = []
MP4_OSS_CONFIG=[]
# 尝试加载本地配置文件
if os.path.exists(CONFIG_FILE_PATH):
try:
with open(CONFIG_FILE_PATH, "r", encoding="utf-8") as f:
# 使用json5.load替代json.load
local_config = json5.load(f)
# 更新是否是国际版
if "is_capcut_env" in local_config:
IS_CAPCUT_ENV = local_config["is_capcut_env"]
# 更新域名配置
if "draft_domain" in local_config:
DRAFT_DOMAIN = local_config["draft_domain"]
# 更新端口号配置
if "port" in local_config:
PORT = local_config["port"]
# 更新预览路由
if "preview_router" in local_config:
PREVIEW_ROUTER = local_config["preview_router"]
# 更新是否上传草稿文件
if "is_upload_draft" in local_config:
IS_UPLOAD_DRAFT = local_config["is_upload_draft"]
# 更新OSS配置
if "oss_config" in local_config:
OSS_CONFIG = local_config["oss_config"]
# 更新MP4 OSS配置
if "mp4_oss_config" in local_config:
MP4_OSS_CONFIG = local_config["mp4_oss_config"]
except Exception as e:
# 配置文件加载失败,使用默认配置
pass
+2
View File
@@ -0,0 +1,2 @@
# 空文件,标识src为Python包
+5
View File
@@ -0,0 +1,5 @@
# 中间件实现
from .prepare import PrepareMiddleware
from .response import ResponseMiddleware
__all__ = ["PrepareMiddleware", "ResponseMiddleware"]
+22
View File
@@ -0,0 +1,22 @@
# 环境初始化中间件
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware
import config
import os
class PrepareMiddleware(BaseHTTPMiddleware):
"""请求前的准备工作中间件
功能
1. 创建临时目录
2. 创建输出目录
"""
async def dispatch(self, request: Request, call_next):
# 递归创建目录,如果目录存在,就直接跳过创建
os.makedirs(config.DRAFT_DIR, exist_ok=True)
os.makedirs(config.TEMP_DIR, exist_ok=True)
# 继续处理请求
response = await call_next(request)
return response
+163
View File
@@ -0,0 +1,163 @@
from fastapi import Request
from fastapi.responses import JSONResponse
from exceptions import CustomError, CustomException
from starlette.middleware.base import BaseHTTPMiddleware
from src.utils.logger import logger
import json
class ResponseMiddleware(BaseHTTPMiddleware):
"""统一响应处理中间件
功能
1. 统一处理业务正常响应添加code和message字段
2. 统一处理异常返回标准错误格式
"""
async def dispatch(self, request: Request, call_next):
# 提前初始化 lang 变量,确保在异常处理中可用
lang = 'zh' # 默认语言
try:
lang = self._get_language_from_request(request)
response = await call_next(request)
# 处理非200状态码的响应
if response.status_code != 200:
return await self._handle_non_200_response(response, lang)
# 处理JSON响应
if self._is_json_response(response):
return await self._process_json_response(response, lang)
return response
except CustomException as e:
return self._handle_custom_exception(e, lang)
except Exception as e:
return self._handle_generic_exception(e, lang)
def _get_language_from_request(self, request: Request) -> str:
"""从请求头获取语言偏好"""
try:
# 安全地解析 Accept-Language 头
accept_lang = request.headers.get('Accept-Language', 'zh')
if not accept_lang or not accept_lang.strip():
return 'zh'
# 先按逗号分割,取第一部分
lang_parts = accept_lang.split(',')[0].strip()
if not lang_parts:
return 'zh'
# 再按连字符分割,取语言代码部分
lang_code_parts = lang_parts.split('-')
if not lang_code_parts or not lang_code_parts[0]:
return 'zh'
lang = lang_code_parts[0].lower()
return lang if lang in ['zh', 'en'] else 'zh'
except Exception:
# 如果解析过程中出现任何异常,返回默认语言
return 'zh'
def _handle_422_error(self, body_str: str, lang: str) -> JSONResponse:
"""特殊处理422参数验证错误"""
try:
# 尝试解析422错误的响应体
error_data = json.loads(body_str)
# 提取验证错误的详细信息
validation_messages = []
if "detail" in error_data:
for error in error_data["detail"]:
if "loc" in error and "msg" in error:
# 格式化错误信息
field = ".".join(str(part) for part in error["loc"] if part != "body")
message = f"{field}: {error['msg']}"
validation_messages.append(message)
# 构建统一的422错误响应(不包含data字段)
error_message = "; ".join(validation_messages) if validation_messages else ""
error_response = CustomError.PARAM_VALIDATION_FAILED.as_dict(detail=error_message, lang=lang)
return JSONResponse(status_code=200, content=error_response)
except json.JSONDecodeError:
logger.warning(f"Failed to parse 422 response body: {body_str}")
error_response = CustomError.PARAM_VALIDATION_FAILED.as_dict(detail=body_str, lang=lang)
return JSONResponse(status_code=200, content=error_response)
async def _handle_non_200_response(self, response, lang: str) -> JSONResponse:
"""处理非200状态码的响应"""
body = b""
async for chunk in response.body_iterator:
body += chunk
body_str = body.decode()
# 特殊处理422错误(参数验证错误)
if response.status_code == 422:
return self._handle_422_error(body_str, lang)
# 其它情况不应该发生,每一个错误都应该在前面被处理
logger.error(f"Non-200 response: {response.status_code} - {body_str}")
# 其他非200错误处理
error_response = {
"code": response.status_code,
"message": f"HTTP Error {response.status_code}, detail: {body_str}"
}
return JSONResponse(status_code=200, content=error_response)
def _is_json_response(self, response) -> bool:
"""检查是否为JSON响应"""
return response.headers.get('content-type') == 'application/json'
async def _process_json_response(self, response, lang: str):
"""处理JSON响应并统一格式"""
body = [section async for section in response.body_iterator]
if not body:
return response
body_str = b''.join(body).decode()
try:
data = json.loads(body_str)
# 如果响应已经有统一格式,直接返回
if 'code' in data and 'message' in data:
return response
# 创建统一格式的响应(成功响应保留data字段)
unified_response = {
'code': CustomError.SUCCESS.code,
'message': CustomError.SUCCESS.as_dict(lang=lang)['message'],
**data
}
return JSONResponse(
status_code=response.status_code,
content=unified_response
)
except json.JSONDecodeError:
logger.warning(f"JSON decode error: {body_str}")
return response
def _handle_custom_exception(self, e: CustomException, lang: str) -> JSONResponse:
"""处理自定义异常(不包含data字段)"""
logger.warning(f"Custom exception: {e.err.code} - {e.err.cn_message}" +
(f" ({e.detail})" if e.detail else ""))
# 获取错误信息
error_response = e.err.as_dict(detail=e.detail, lang=lang)
return JSONResponse(status_code=200, content=error_response)
def _handle_generic_exception(self, e: Exception, lang: str) -> JSONResponse:
"""处理通用异常(不包含data字段)"""
logger.warning(f"Internal server error: {str(e)}")
# 获取错误信息
error_response = CustomError.INTERNAL_SERVER_ERROR.as_dict(detail=str(e), lang=lang)
return JSONResponse(status_code=200, content=error_response)
+277
View File
@@ -0,0 +1,277 @@
import warnings
import sys
from .local_materials import CropSettings, VideoMaterial, AudioMaterial
from .keyframe import KeyframeProperty
from .time_util import Timerange
from .audio_segment import AudioSegment
from .video_segment import VideoSegment, StickerSegment, ClipSettings
from .effect_segment import EffectSegment, FilterSegment
from .text_segment import TextSegment, TextStyle, TextBorder, TextBackground, TextShadow
from .metadata import FontType
from .metadata import MaskType
from .metadata import TransitionType, FilterType
from .metadata import IntroType, OutroType, GroupAnimationType
from .metadata import TextIntro, TextOutro, TextLoopAnim
from .metadata import AudioSceneEffectType
from .metadata import VideoSceneEffectType, VideoCharacterEffectType
from .track import TrackType
from .template_mode import ShrinkMode, ExtendMode
from .script_file import ScriptFile
from .draft_folder import DraftFolder
# 仅在Windows系统下导入jianying_controller
ISWIN = (sys.platform == 'win32')
if ISWIN:
from .jianying_controller import JianyingController, ExportResolution, ExportFramerate
from .time_util import SEC, tim, trange
def _deprecated_class_warning(old_name: str, new_name: str):
warnings.warn(
f"{old_name} is deprecated and will be removed in a future version. "
f"Use {new_name} instead.",
DeprecationWarning,
stacklevel=3
)
# 保持向后兼容
class Script_file:
"""Deprecated: Use ScriptFile instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Script_file", "ScriptFile")
return ScriptFile(*args, **kwargs)
class Draft_folder:
"""Deprecated: Use DraftFolder instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Draft_folder", "DraftFolder")
return DraftFolder(*args, **kwargs)
class Shrink_mode:
"""Deprecated: Use ShrinkMode instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Shrink_mode", "ShrinkMode")
return ShrinkMode(*args, **kwargs)
class Extend_mode:
"""Deprecated: Use ExtendMode instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Extend_mode", "ExtendMode")
return ExtendMode(*args, **kwargs)
class Clip_settings:
"""Deprecated: Use ClipSettings instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Clip_settings", "ClipSettings")
return ClipSettings(*args, **kwargs)
class Text_style:
"""Deprecated: Use TextStyle instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Text_style", "TextStyle")
return TextStyle(*args, **kwargs)
class Text_border:
"""Deprecated: Use TextBorder instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Text_border", "TextBorder")
return TextBorder(*args, **kwargs)
class Text_background:
"""Deprecated: Use TextBackground instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Text_background", "TextBackground")
return TextBackground(*args, **kwargs)
class Text_segment:
"""Deprecated: Use TextSegment instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Text_segment", "TextSegment")
return TextSegment(*args, **kwargs)
class Audio_segment:
"""Deprecated: Use AudioSegment instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Audio_segment", "AudioSegment")
return AudioSegment(*args, **kwargs)
class Video_segment:
"""Deprecated: Use VideoSegment instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Video_segment", "VideoSegment")
return VideoSegment(*args, **kwargs)
class Sticker_segment:
"""Deprecated: Use StickerSegment instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Sticker_segment", "StickerSegment")
return StickerSegment(*args, **kwargs)
class Effect_segment:
"""Deprecated: Use EffectSegment instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Effect_segment", "EffectSegment")
return EffectSegment(*args, **kwargs)
class Filter_segment:
"""Deprecated: Use FilterSegment instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Filter_segment", "FilterSegment")
return FilterSegment(*args, **kwargs)
class Video_material:
"""Deprecated: Use VideoMaterial instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Video_material", "VideoMaterial")
return VideoMaterial(*args, **kwargs)
class Audio_material:
"""Deprecated: Use AudioMaterial instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Audio_material", "AudioMaterial")
return AudioMaterial(*args, **kwargs)
class Crop_settings:
"""Deprecated: Use CropSettings instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Crop_settings", "CropSettings")
return CropSettings(*args, **kwargs)
# 枚举类的向后兼容 - 使用代理类
class _DeprecatedEnum:
"""带deprecation警告的枚举代理类"""
def __init__(self, original_enum, old_name, new_name):
self._enum = original_enum
self._old_name = old_name
self._new_name = new_name
def __getattr__(self, name):
# 当访问枚举成员时显示警告
_deprecated_class_warning(self._old_name, self._new_name)
return getattr(self._enum, name)
def __getitem__(self, name):
# 当通过索引访问时显示警告
_deprecated_class_warning(self._old_name, self._new_name)
return self._enum[name]
def __repr__(self):
return f"<Deprecated {self._old_name} (use {self._new_name} instead)>"
Track_type = _DeprecatedEnum(TrackType, "Track_type", "TrackType")
Font_type = _DeprecatedEnum(FontType, "Font_type", "FontType")
Mask_type = _DeprecatedEnum(MaskType, "Mask_type", "MaskType")
Filter_type = _DeprecatedEnum(FilterType, "Filter_type", "FilterType")
Transition_type = _DeprecatedEnum(TransitionType, "Transition_type", "TransitionType")
Intro_type = _DeprecatedEnum(IntroType, "Intro_type", "IntroType")
Outro_type = _DeprecatedEnum(OutroType, "Outro_type", "OutroType")
Group_animation_type = _DeprecatedEnum(GroupAnimationType, "Group_animation_type", "GroupAnimationType")
Text_intro = _DeprecatedEnum(TextIntro, "Text_intro", "TextIntro")
Text_outro = _DeprecatedEnum(TextOutro, "Text_outro", "TextOutro")
Text_loop_anim = _DeprecatedEnum(TextLoopAnim, "Text_loop_anim", "TextLoopAnim")
Audio_scene_effect_type = _DeprecatedEnum(AudioSceneEffectType, "Audio_scene_effect_type", "AudioSceneEffectType")
Video_scene_effect_type = _DeprecatedEnum(VideoSceneEffectType, "Video_scene_effect_type", "VideoSceneEffectType")
Video_character_effect_type = _DeprecatedEnum(VideoCharacterEffectType, "Video_character_effect_type", "VideoCharacterEffectType")
Keyframe_property = _DeprecatedEnum(KeyframeProperty, "Keyframe_property", "KeyframeProperty")
# 仅在Windows系统下定义jianying_controller相关的向后兼容类
if ISWIN:
class Jianying_controller:
"""Deprecated: Use JianyingController instead."""
def __new__(cls, *args, **kwargs):
_deprecated_class_warning("Jianying_controller", "JianyingController")
return JianyingController(*args, **kwargs)
Export_resolution = _DeprecatedEnum(ExportResolution, "Export_resolution", "ExportResolution")
Export_framerate = _DeprecatedEnum(ExportFramerate, "Export_framerate", "ExportFramerate")
# 基础__all__列表(所有平台通用)
__all__ = [
"FontType",
"MaskType",
"FilterType",
"TransitionType",
"IntroType",
"OutroType",
"GroupAnimationType",
"TextIntro",
"TextOutro",
"TextLoopAnim",
"AudioSceneEffectType",
"VideoSceneEffectType",
"VideoCharacterEffectType",
"CropSettings",
"VideoMaterial",
"AudioMaterial",
"KeyframeProperty",
"Timerange",
"AudioSegment",
"VideoSegment",
"StickerSegment",
"ClipSettings",
"EffectSegment",
"FilterSegment",
"TextSegment",
"TextStyle",
"TextBorder",
"TextBackground",
"TextShadow",
"TrackType",
"ShrinkMode",
"ExtendMode",
"ScriptFile",
"DraftFolder",
"SEC",
"tim",
"trange",
# 向后兼容的snake_case类
"Script_file",
"Draft_folder",
"Shrink_mode",
"Extend_mode",
"Track_type",
"Font_type",
"Mask_type",
"Filter_type",
"Transition_type",
"Intro_type",
"Outro_type",
"Group_animation_type",
"Text_intro",
"Text_outro",
"Text_loop_anim",
"Audio_scene_effect_type",
"Video_scene_effect_type",
"Video_character_effect_type",
"Clip_settings",
"Text_style",
"Text_border",
"Text_background",
"Text_segment",
"Audio_segment",
"Video_segment",
"Sticker_segment",
"Effect_segment",
"Filter_segment",
"Video_material",
"Audio_material",
"Crop_settings",
"Keyframe_property",
]
# 仅在Windows系统下添加jianying_controller相关的导出
if ISWIN:
__all__.extend([
"JianyingController",
"ExportResolution",
"ExportFramerate",
"Jianying_controller",
"Export_resolution",
"Export_framerate",
])

Some files were not shown because too many files have changed in this diff Show More