Showing preview only (3,907K chars total). Download the full file or copy to clipboard to get everything.
Repository: Hommy-master/capcut-mate
Branch: main
Commit: e48b50529638
Files: 342
Total size: 136.6 MB
Directory structure:
gitextract_66uhurkx/
├── .github/
│ └── workflows/
│ ├── desktop-client-dev.yml
│ └── dev.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── README.zh.md
├── config/
│ ├── huazi.json
│ └── sticker.json
├── config.py
├── desktop-client/
│ ├── .gitignore
│ ├── .npmrc
│ ├── LICENSE
│ ├── assets/
│ │ ├── entitlements.mac.plist
│ │ └── icons/
│ │ └── logo.icns
│ ├── main.js
│ ├── nodeapi/
│ │ ├── download.js
│ │ ├── draftPathDetect.js
│ │ ├── ipcHandlers.js
│ │ └── logger.js
│ ├── package.json
│ ├── preload.js
│ ├── scripts/
│ │ ├── electron-builder-green.config.js
│ │ ├── electron-builder.config.js
│ │ └── update-version.js
│ └── web/
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── public/
│ │ └── index.html
│ ├── src/
│ │ ├── App.jsx
│ │ ├── components/
│ │ │ ├── DownloadButton.jsx
│ │ │ ├── DownloadControls.jsx
│ │ │ ├── ExternalWebpage.jsx
│ │ │ ├── Header/
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ │ ├── LogModule.jsx
│ │ │ ├── Tabs.jsx
│ │ │ └── Textarea.jsx
│ │ ├── index.jsx
│ │ ├── pages/
│ │ │ ├── ConfigCenter/
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ │ ├── Download/
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ │ └── History/
│ │ │ ├── index.jsx
│ │ │ └── index.less
│ │ ├── services/
│ │ │ └── electronService.js
│ │ ├── styles/
│ │ │ ├── index.less
│ │ │ └── root.less
│ │ └── utils/
│ │ ├── const.tsx
│ │ └── date.ts
│ └── vite.config.js
├── docker-compose.example.yaml
├── docker-compose.yaml
├── docs/
│ ├── add_audios.md
│ ├── add_audios.zh.md
│ ├── add_captions.md
│ ├── add_captions.zh.md
│ ├── add_effects.md
│ ├── add_effects.zh.md
│ ├── add_filters.md
│ ├── add_filters.zh.md
│ ├── add_images.md
│ ├── add_images.zh.md
│ ├── add_keyframes.md
│ ├── add_keyframes.zh.md
│ ├── add_masks.md
│ ├── add_masks.zh.md
│ ├── add_sticker.md
│ ├── add_sticker.zh.md
│ ├── add_text_style.md
│ ├── add_text_style.zh.md
│ ├── add_videos.md
│ ├── add_videos.zh.md
│ ├── audio_infos.md
│ ├── audio_infos.zh.md
│ ├── audio_timelines.md
│ ├── audio_timelines.zh.md
│ ├── caption_infos.md
│ ├── caption_infos.zh.md
│ ├── create_draft.md
│ ├── create_draft.zh.md
│ ├── easy_create_material.md
│ ├── easy_create_material.zh.md
│ ├── effect_infos.md
│ ├── effect_infos.zh.md
│ ├── filter_infos.md
│ ├── filter_infos.zh.md
│ ├── gen_video.md
│ ├── gen_video.zh.md
│ ├── gen_video_status.md
│ ├── gen_video_status.zh.md
│ ├── get_audio_duration.md
│ ├── get_audio_duration.zh.md
│ ├── get_draft.md
│ ├── get_draft.zh.md
│ ├── get_image_animations.md
│ ├── get_image_animations.zh.md
│ ├── get_text_animations.md
│ ├── get_text_animations.zh.md
│ ├── get_text_effects.md
│ ├── get_url.md
│ ├── get_url.zh.md
│ ├── imgs_infos.md
│ ├── imgs_infos.zh.md
│ ├── keyframes_infos.md
│ ├── keyframes_infos.zh.md
│ ├── objs_to_str_list.md
│ ├── objs_to_str_list.zh.md
│ ├── save_draft.md
│ ├── save_draft.zh.md
│ ├── search_sticker.md
│ ├── search_sticker.zh.md
│ ├── str_list_to_objs.md
│ ├── str_list_to_objs.zh.md
│ ├── str_to_list.md
│ ├── str_to_list.zh.md
│ ├── timelines.md
│ ├── timelines.zh.md
│ ├── video_infos.md
│ └── video_infos.zh.md
├── exceptions.py
├── main.py
├── openapi.yaml
├── pyproject.toml
├── src/
│ ├── __init__.py
│ ├── middlewares/
│ │ ├── __init__.py
│ │ ├── prepare.py
│ │ ├── response.py
│ │ └── trace_context.py
│ ├── pyJianYingDraft/
│ │ ├── __init__.py
│ │ ├── animation.py
│ │ ├── assets/
│ │ │ ├── __init__.py
│ │ │ ├── draft_content_template.json
│ │ │ └── draft_meta_info.json
│ │ ├── audio_segment.py
│ │ ├── draft_folder.py
│ │ ├── effect_segment.py
│ │ ├── exceptions.py
│ │ ├── jianying_controller.py
│ │ ├── keyframe.py
│ │ ├── local_materials.py
│ │ ├── metadata/
│ │ │ ├── __init__.py
│ │ │ ├── audio_scene_effect.py
│ │ │ ├── effect_meta.py
│ │ │ ├── filter_meta.py
│ │ │ ├── font_meta.py
│ │ │ ├── mask_meta.py
│ │ │ ├── mix_mode_meta.py
│ │ │ ├── speech_to_song.py
│ │ │ ├── text_intro.py
│ │ │ ├── text_loop.py
│ │ │ ├── text_outro.py
│ │ │ ├── tone_effect.py
│ │ │ ├── transition_meta.py
│ │ │ ├── video_character_effect.py
│ │ │ ├── video_group_animation.py
│ │ │ ├── video_intro.py
│ │ │ ├── video_outro.py
│ │ │ └── video_scene_effect.py
│ │ ├── script_file.py
│ │ ├── segment.py
│ │ ├── template_mode.py
│ │ ├── text_segment.py
│ │ ├── time_util.py
│ │ ├── track.py
│ │ ├── util.py
│ │ └── video_segment.py
│ ├── router/
│ │ ├── __init__.py
│ │ └── v1.py
│ ├── schemas/
│ │ ├── __init__.py
│ │ ├── add_audios.py
│ │ ├── add_captions.py
│ │ ├── add_effects.py
│ │ ├── add_filters.py
│ │ ├── add_images.py
│ │ ├── add_keyframes.py
│ │ ├── add_masks.py
│ │ ├── add_sticker.py
│ │ ├── add_text_style.py
│ │ ├── add_videos.py
│ │ ├── audio_infos.py
│ │ ├── audio_timelines.py
│ │ ├── caption_infos.py
│ │ ├── create_draft.py
│ │ ├── easy_create_material.py
│ │ ├── effect_infos.py
│ │ ├── filter_infos.py
│ │ ├── gen_video.py
│ │ ├── gen_video_active_count.py
│ │ ├── gen_video_status.py
│ │ ├── get_audio_duration.py
│ │ ├── get_draft.py
│ │ ├── get_effects.py
│ │ ├── get_filters.py
│ │ ├── get_image_animations.py
│ │ ├── get_text_animations.py
│ │ ├── get_text_effects.py
│ │ ├── get_url.py
│ │ ├── imgs_infos.py
│ │ ├── keyframes_infos.py
│ │ ├── objs_to_str_list.py
│ │ ├── save_draft.py
│ │ ├── search_sticker.py
│ │ ├── str_list_to_objs.py
│ │ ├── str_to_list.py
│ │ ├── timelines.py
│ │ └── video_infos.py
│ ├── service/
│ │ ├── __init__.py
│ │ ├── add_audios.py
│ │ ├── add_captions.py
│ │ ├── add_effects.py
│ │ ├── add_filters.py
│ │ ├── add_images.py
│ │ ├── add_keyframes.py
│ │ ├── add_masks.py
│ │ ├── add_sticker.py
│ │ ├── add_text_style.py
│ │ ├── add_videos.py
│ │ ├── audio_infos.py
│ │ ├── audio_timelines.py
│ │ ├── caption_infos.py
│ │ ├── create_draft.py
│ │ ├── easy_create_material.py
│ │ ├── effect_infos.py
│ │ ├── filter_infos.py
│ │ ├── gen_video.py
│ │ ├── get_audio_duration.py
│ │ ├── get_draft.py
│ │ ├── get_effects.py
│ │ ├── get_filters.py
│ │ ├── get_image_animations.py
│ │ ├── get_text_animations.py
│ │ ├── get_text_effects.py
│ │ ├── get_url.py
│ │ ├── imgs_infos.py
│ │ ├── keyframes_infos.py
│ │ ├── objs_to_str_list.py
│ │ ├── save_draft.py
│ │ ├── search_sticker.py
│ │ ├── str_list_to_objs.py
│ │ ├── str_to_list.py
│ │ ├── text_effect_map_generated.py
│ │ ├── timelines.py
│ │ └── video_infos.py
│ └── utils/
│ ├── __init__.py
│ ├── cos.py
│ ├── download.py
│ ├── draft_cache.py
│ ├── draft_cleanup.py
│ ├── draft_downloader.py
│ ├── draft_lock_manager.py
│ ├── helper.py
│ ├── keyframe_value.py
│ ├── logger.py
│ ├── media.py
│ ├── oss.py
│ ├── points.py
│ ├── storage_upload_retry.py
│ ├── trace_context.py
│ ├── upload_file.py
│ ├── video_task_manager.py
│ └── video_task_store.py
├── template/
│ ├── default/
│ │ ├── draft_agency_config.json
│ │ ├── draft_info.json
│ │ ├── draft_info.json.bak
│ │ ├── draft_meta_info.json
│ │ ├── draft_settings
│ │ └── template.tmp
│ ├── default2/
│ │ ├── attachment_pc_common.json
│ │ ├── draft_agency_config.json
│ │ ├── draft_content.json
│ │ ├── draft_info.json
│ │ ├── draft_meta_info.json
│ │ └── template.tmp
│ └── readme.md
├── tests/
│ ├── __init__.py
│ ├── manual_test_audio_infos.py
│ ├── manual_test_caption_infos.py
│ ├── manual_test_effect_infos.py
│ ├── manual_test_imgs_infos.py
│ ├── manual_test_keyframes_infos.py
│ ├── manual_test_video_infos.py
│ ├── test_add_audios.py
│ ├── test_add_captions_text_effect.py
│ ├── test_add_images.py
│ ├── test_add_keyframes_normalize.py
│ ├── test_add_keyframes_refactor.py
│ ├── test_add_masks.py
│ ├── test_add_videos_concurrent.py
│ ├── test_add_videos_concurrent_demo.py
│ ├── test_add_videos_duration.py
│ ├── test_add_videos_refactor.py
│ ├── test_all_text_effects.py
│ ├── test_api_version.py
│ ├── test_audio_infos.py
│ ├── test_audio_infos_simple.py
│ ├── test_audio_timelines.py
│ ├── test_caption_keywords.py
│ ├── test_caption_transform.py
│ ├── test_caption_transform_fix.py
│ ├── test_chinese_encoding_fix.py
│ ├── test_ci_dependencies.py
│ ├── test_cross_platform.py
│ ├── test_draft_cleanup.py
│ ├── test_draft_downloader_remote_materials.py
│ ├── test_draft_lock_all_apis.py
│ ├── test_draft_lock_manager.py
│ ├── test_draft_service.py
│ ├── test_export_error_handling.py
│ ├── test_file_operations.py
│ ├── test_float_transform.py
│ ├── test_font_alias_resolution.py
│ ├── test_font_size.py
│ ├── test_font_size_debug.py
│ ├── test_font_size_logic.py
│ ├── test_font_size_not_set.py
│ ├── test_get_audio_duration_api.py
│ ├── test_get_text_effects.py
│ ├── test_imgs_infos_multiple_animations.py
│ ├── test_keyframe_value.py
│ ├── test_keyword_font_size.py
│ ├── test_latest_commit_features.py
│ ├── test_logic_validation.py
│ ├── test_media_utils.py
│ ├── test_middleware.py
│ ├── test_param_pass.py
│ ├── test_parse_video_data.py
│ ├── test_search_sticker.py
│ ├── test_search_sticker_basic.py
│ ├── test_search_sticker_simple.py
│ ├── test_storage_upload_retry.py
│ ├── test_text_segment_add_animation.py
│ ├── test_transform_coordinate_fix.py
│ ├── test_upload_file.py
│ ├── test_video_duration_extension.py
│ ├── test_video_task_draft_duration.py
│ ├── test_video_transform.py
│ ├── test_video_transform_fix.py
│ └── verify_get_text_effects_api.py
└── tools/
├── extract_text_effects.py
├── ffprobe
└── query_sticker.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/desktop-client-dev.yml
================================================
name: Build
on:
push:
branches: [ main, dev ]
tags: [ 'v*' ]
pull_request:
branches: [ main, dev ]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: windows-latest
platform: win
artifact_name: windows-build
build_command: build-win
installer_command: build-win-installer
green_command: build-win-green
- os: macos-latest
platform: mac
artifact_name: macos-build
build_command: build-mac
installer_command: build-mac-installer
green_command: build-mac-green
- os: macos-15-intel
platform: mac-x64
artifact_name: macos-build-x64
build_command: build-mac-x64
installer_command: build-mac-x64-installer
green_command: build-mac-x64-green
steps:
- name: 准备代码
uses: actions/checkout@v4
- name: 设置Node.js环境
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
cache-dependency-path: desktop-client/package-lock.json
- name: 安装Electron依赖
run: npm ci
working-directory: ./desktop-client
- name: 安装前端依赖
run: npm ci
working-directory: ./desktop-client/web
- name: 构建前端
run: npm run build
working-directory: ./desktop-client/web
- name: 更新版本号
run: node scripts/update-version.js
working-directory: ./desktop-client
env:
GITHUB_REF: ${{ github.ref }}
- name: 根据平台打包应用程序
run: npm run ${{ matrix.build_command }}
working-directory: ./desktop-client
- name: 根据平台创建安装包
run: npm run ${{ matrix.installer_command }}
working-directory: ./desktop-client
env:
# 添加环境变量以解决macOS构建问题
CSC_IDENTITY_AUTO_DISCOVERY: false
DEBUG: electron-builder
- name: 构建绿色安装包
if: matrix.green_command != 'null'
run: npm run ${{ matrix.green_command }}
working-directory: ./desktop-client
env:
# 添加环境变量以解决macOS构建问题
CSC_IDENTITY_AUTO_DISCOVERY: false
DEBUG: electron-builder
- name: 列出dist目录内容
run: |
echo "当前操作系统: ${{ runner.os }}"
ls desktop-client/dist/
shell: bash
- name: 上传安装包构件
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact_name }}-installer
path: desktop-client/dist/
if-no-files-found: ignore
- name: 上传绿色安装包构件
if: matrix.green_command != 'null'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact_name }}-green
path: desktop-client/dist/*.zip
if-no-files-found: ignore
- name: 发布版本
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
files: |
desktop-client/dist/capcut-mate-windows-x64-installer.exe
desktop-client/dist/capcut-mate-macos-arm64-installer.dmg
desktop-client/dist/capcut-mate-macos-x64-installer.dmg
desktop-client/dist/*.zip
overwrite: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/dev.yml
================================================
name: Docker Image CI Dev
on:
push:
branches: [ "main", "dev" ]
tags:
- 'v*' # 当推送v开头的tag时触发
pull_request:
branches: [ "main", "dev" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 准备代码
uses: actions/checkout@v4
# 安装uv环境
- name: 安装uv
uses: astral-sh/setup-uv@v2
with:
version: "0.8.11"
enable-cache: true
- name: 准备python环境
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: 安装基础依赖
run: uv sync #只安装基础依赖,避免平台特定依赖
- name: 查看文件和目录结构
run: ls -lha
- name: 准备生产环境文件
run: |
mkdir -p dist/etc
# 复制源代码
cp -rf src dist/
cp -rf config dist/
cp -rf template dist/
# 复制依赖配置文件
cp pyproject.toml dist/
cp *.py dist/
cp uv.lock dist/
echo "${{ github.sha }}" > dist/etc/commit_hash
- name: 查看文件和目录结构
run: ls -lha dist -R
- name: 准备打包Docker镜像的环境
uses: docker/setup-buildx-action@v3
# 登录到Docker Hub
- name: 登录Docker Hub
if: github.event_name != 'pull_request' # PR时不登录
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# 提取标签信息 - 使用与登录相同的Secret变量名
- name: 提取镜像标签
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ secrets.DOCKERHUB_USERNAME }}/capcut-mate # 统一使用DOCKERHUB_USERNAME(无下划线)
tags: |
type=ref,event=branch
type=ref,event=tag
type=sha,format=short
type=raw,value=latest,enable={{is_default_branch}}
# 调试步骤:检查生成的标签
- name: 显示生成的镜像标签
run: |
echo "生成的标签: ${{ steps.meta.outputs.tags }}"
# 检查标签是否包含正确的用户名格式
if [[ ! "${{ steps.meta.outputs.tags }}" == *"${{ secrets.DOCKERHUB_USERNAME }}/capcut-mate:"* ]]; then
echo "错误:标签格式不正确,应为 ${secrets.DOCKERHUB_USERNAME}/capcut-mate:标签"
exit 1
fi
# 构建并推送Docker镜像
- name: 构建并推送Docker镜像
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
================================================
FILE: .gitignore
================================================
*.pyc
.venv
./dist
/.qoder
/output
/temp
/logs
/db
================================================
FILE: Dockerfile
================================================
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 /app/bin/
# 从CI构建的dist目录复制所有文件
COPY dist/ .
COPY tools/ffprobe /app/bin/ffprobe
# 安装依赖(仍使用root用户确保权限)
RUN uv sync
# 添加权限
RUN chmod 0755 /app/bin/*
# 暴露应用端口
EXPOSE 30000
# 设置环境变量,指定uv缓存目录和用户主目录
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH="/app/.venv/bin:/app/bin:$PATH" \
HOME="/root" \
UV_CACHE_DIR="/root/.cache/uv"
# 启动命令
CMD ["uv", "run", "main.py", "--workers", "4"]
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2025 gogoshine
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# CapCut Mate API
<div align="center">
### 🌐 Language Switch
[中文版](README.zh.md) | [English](README.md)
</div>
---
## Project Introduction
CapCut Mate API is a **completely open-source and free** Jianying draft automation assistant built on **FastAPI**, supporting **independent deployment**. This project focuses on empowering large models with basic video editing capabilities, providing out-of-the-box video editing **Skills**, and has fully **automated the entire Jianying core functionality workflow**. It can directly **connect with large models** to achieve diverse intelligent video editing, enabling ordinary users to quickly create professional and advanced video works.
Flexible project usage: Can be **independently deployed**, or combined with **Coze or n8n** to build **automated workflows**, and can also connect with Jianying to achieve **cloud rendering**, directly generating final videos from drafts.
## Project Resources
- [⭐ Jianying Assistant](https://github.com/Hommy-master/capcut-mate)
- [🔌 Jianying Assistant - Coze Plugin](https://www.coze.cn/store/plugin/7576197869707722771)
- [🔗 Workflow Examples](https://jcaigc.cn/workflow)
⭐ If you find this project helpful, please give us a Star! Your support is the greatest motivation for me to continuously maintain and improve the project 😊
## Features
- 🎬 Draft Management: Create draft, get draft, save draft
- 🎥 Material Addition: Add videos, audios, images, stickers, subtitles, effects, masks, etc.
- 🔧 Advanced Functions: Keyframe control, text styles, animation effects, etc.
- 📤 Video Export: Cloud rendering to generate final video
- 🛡️ Data Validation: Using Pydantic for request data validation
- 📖 RESTful API: Compliant with standard API design specifications
- 📚 Auto Documentation: FastAPI automatically generates interactive API documentation
## Tech Stack
- Python 3.11+
- FastAPI: High-performance web framework
- Pydantic: Data validation and model definition
- Passlib: Password encryption (if using user authentication)
- Uvicorn: ASGI server
- uv: Python package manager and project management tool
## Quick Start
### Prerequisites
- Python 3.11+
- uv: Python package manager and project management tool
Installation:
#### Windows
```powershell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
#### Linux/macOS
```bash
sh -c "$(curl -LsSf https://astral.sh/uv/install.sh)"
```
### Installation Steps
1. Clone the project
```bash
git clone git@github.com:Hommy-master/capcut-mate.git
cd capcut-mate
```
2. Install dependencies
```bash
# Install dependencies
uv sync
# Additional execution for Windows
uv pip install -e .[windows]
```
3. Start the server
```bash
uv run main.py
```
4. Access API documentation
After starting, visit http://localhost:30000/docs to view the automatically generated interactive API documentation
### Docker Deployment
#### Quick Deployment (Recommended)
📺 **Video Tutorial**: [CapCut Mate Private Deployment Complete Tutorial](https://v.douyin.com/5p-o319uA5o/)
```bash
git clone https://github.com/Hommy-master/capcut-mate.git
cd capcut-mate
docker-compose pull && docker-compose up -d
```
After deployment, access the API documentation at: http://localhost:30000/docs
## One-Click Import Coze Plugin
1. Open Coze platform: https://coze.cn/home

2. Add Plugin

3. Import Plugin

4. Upload the openapi.yaml file in the current project directory

5. Complete file upload

6. Complete logo replacement

7. Enable Plugin

## API Documentation
The following are the core interfaces provided by CapCut Mate API, supporting a complete video creation workflow:
### 🏗️ Draft Management
| Interface | Function | Description | Documentation Link |
|-----------|----------|-------------|-------------------|
| **create_draft** | Create Draft | Create a new Jianying draft project, set canvas size | [📖 View Documentation](./docs/create_draft.md) |
| **save_draft** | Save Draft | Save current draft state, ensure edit content persistence | [📖 View Documentation](./docs/save_draft.md) |
| **get_draft** | Get Draft | Get draft file list and detailed information | [📖 View Documentation](./docs/get_draft.md) |
### 🎥 Video Materials
| Interface | Function | Description | Documentation Link |
|-----------|----------|-------------|-------------------|
| **add_videos** | Add Videos | Batch add video materials, support cropping, scaling, effects | [📖 View Documentation](./docs/add_videos.md) |
| **add_images** | Add Images | Batch add image materials, support animations and transition effects | [📖 View Documentation](./docs/add_images.md) |
| **add_sticker** | Add Stickers | Add decorative stickers, support position and size adjustment | [📖 View Documentation](./docs/add_sticker.md) |
### 🎵 Audio Processing
| Interface | Function | Description | Documentation Link |
|-----------|----------|-------------|-------------------|
| **add_audios** | Add Audios | Batch add audio materials, support volume and fade in/out | [📖 View Documentation](./docs/add_audios.md) |
| **get_audio_duration** | Get Audio Duration | Get precise duration information of audio files | [📖 View Documentation](./docs/get_audio_duration.md) |
### 📝 Text Subtitles
| Interface | Function | Description | Documentation Link |
|-----------|----------|-------------|-------------------|
| **add_captions** | Add Captions | Batch add captions, support keyword highlighting and style settings | [📖 View Documentation](./docs/add_captions.md) |
| **add_text_style** | Text Style | Create rich text styles, support keyword colors and fonts | [📖 View Documentation](./docs/add_text_style.md) |
### ✨ Effects & Animations
| Interface | Function | Description | Documentation Link |
|-----------|----------|-------------|-------------------|
| **add_effects** | Add Effects | Add visual effects, such as filters, borders, dynamic effects | [📖 View Documentation](./docs/add_effects.md) |
| **add_keyframes** | Keyframe Animation | Create property animations for position, scale, rotation, etc. | [📖 View Documentation](./docs/add_keyframes.md) |
| **add_masks** | Mask Effects | Add various shape masks, control visible areas of the screen | [📖 View Documentation](./docs/add_masks.md) |
### 🎨 Animation Resources
| Interface | Function | Description | Documentation Link |
|-----------|----------|-------------|-------------------|
| **get_text_animations** | Text Animations | Get available text entrance, exit, and loop animations | [📖 View Documentation](./docs/get_text_animations.md) |
| **get_image_animations** | Image Animations | Get available image animation effects list | [📖 View Documentation](./docs/get_image_animations.md) |
### 🎬 Video Generation
| Interface | Function | Description | Documentation Link |
|-----------|----------|-------------|-------------------|
| **gen_video** | Generate Video | Submit video rendering task, asynchronous processing | [📖 View Documentation](./docs/gen_video.md) |
| **gen_video_status** | Query Status | Query the progress and status of video generation tasks | [📖 View Documentation](./docs/gen_video_status.md) |
### 🚀 Quick Tools
| Interface | Function | Description | Documentation Link |
|-----------|----------|-------------|-------------------|
| **easy_create_material** | Quick Creation | Add multiple types of materials at once, simplify creation process | [📖 View Documentation](./docs/easy_create_material.md) |
### 🛠️ Utility Tools
| Interface | Function | Description | Documentation Link |
|-----------|----------|-------------|-------------------|
| **get_url** | Extract URL | Extract URL information from input content | [📖 View Documentation](./docs/get_url.md) |
| **search_sticker** | Search Sticker | Search sticker materials by keyword | [📖 View Documentation](./docs/search_sticker.md) |
| **objs_to_str_list** | Objects to String List | Convert object list to string list format | [📖 View Documentation](./docs/objs_to_str_list.md) |
| **str_list_to_objs** | String List to Objects | Convert string list to object list format | [📖 View Documentation](./docs/str_list_to_objs.md) |
| **str_to_list** | String to List | Convert string to list format | [📖 View Documentation](./docs/str_to_list.md) |
| **timelines** | Create Timelines | Generate timeline configurations for video editing | [📖 View Documentation](./docs/timelines.md) |
| **audio_timelines** | Audio Timelines | Calculate timelines based on audio durations | [📖 View Documentation](./docs/audio_timelines.md) |
| **audio_infos** | Audio Information | Generate audio information from URLs and timelines | [📖 View Documentation](./docs/audio_infos.md) |
| **imgs_infos** | Image Information | Generate image information from URLs and timelines | [📖 View Documentation](./docs/imgs_infos.md) |
| **caption_infos** | Caption Information | Generate caption information from text and timelines | [📖 View Documentation](./docs/caption_infos.md) |
| **effect_infos** | Effect Information | Generate effect information from names and timelines | [📖 View Documentation](./docs/effect_infos.md) |
| **keyframes_infos** | Keyframe Information | Generate keyframe information from configurations | [📖 View Documentation](./docs/keyframes_infos.md) |
| **video_infos** | Video Information | Generate video information from URLs and timelines | [📖 View Documentation](./docs/video_infos.md) |
## API Usage Examples
### Workflow Examples
Explore real-world workflow examples to learn how to integrate CapCut Mate with automation platforms like Coze and n8n:
👉 [View Workflow Examples](https://jcaigc.cn/workflow)
### Create Draft
```bash
curl -X POST "http://localhost:30000/openapi/capcut-mate/v1/create_draft" \
-H "Content-Type: application/json" \
-d '{"width": 1080, "height": 1920}'
```
### Add Videos
`video_infos` is a **JSON string** (not a nested JSON array). Each item must include `video_url`, `start`, and `end` (microseconds on the timeline). See [add_videos](./docs/add_videos.md) for optional fields.
```bash
curl -X POST "http://localhost:30000/openapi/capcut-mate/v1/add_videos" \
-H "Content-Type: application/json" \
-d '{
"draft_url": "http://localhost:30000/openapi/capcut-mate/v1/get_draft?draft_id=20251126212753cab03392",
"video_infos": "[{\"video_url\": \"https://example.com/video.mp4\", \"start\": 0, \"end\": 1000000}]"
}'
```
## API Documentation
- Local Access: http://localhost:30000/docs
- ReDoc Version: http://localhost:30000/redoc
## Jianying Assistant Client
The Jianying Assistant client provides a convenient desktop interface. Here are the startup methods:
### macOS Sandbox Permissions Guide
When running on macOS, the application may request access permissions for specific folders. Please follow these steps:
1. If permission prompts appear during the first run, allow the application to access the required folders
2. For manual configuration, go to `System Preferences > Security & Privacy > Privacy > Folder Access`
3. Ensure the CapCut Mate application is added to the allowed list
For more details, please refer to the [macOS Sandbox Permissions Configuration Guide](./docs/macos_sandbox_setup.md).
1. Install Dependencies
```bash
# Switch npm mirror source - for Windows
set ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
# Switch yarn mirror source - for Linux or macOS
export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
# Install dependencies
npm install --verbose
```
2. Start the Project
```bash
npm run web:dev
npm start
```
## Contact
| Type | Method | Description |
|------|--------|-------------|
| 📱 WeChat Group | <div align="center"><img src="./assets/wechat-q.jpg" width="200" alt="Jianying Assistant"></div> | Open Source Community Discussion Group |
| 💬 WeChat | <div align="center"><img src="./assets/wechat.jpg" width="120" alt="Technical Support WeChat"></div> | Business Cooperation |
| 📧 Email | taohongmin51@gmail.com | Technical Support |
---
================================================
FILE: README.zh.md
================================================
# CapCut Mate API
<div align="center">
### 🌐 语言切换
[中文版](README.zh.md) | [English](README.md)
</div>
---
## 项目简介
CapCut Mate API 是一款完全**开源免费**、基于 FastAPI构建的剪映草稿自动化助手,支持**独立部署**。本项目专注于为大模型赋能基础视频编辑能力,提供开箱即用的视频剪辑 **Skills**,已将剪映核心功能全流程自动化。可直接对接大模型实现多样化智能视频剪辑,让普通用户也能快速制作出专业高级的视频作品。
项目使用灵活:既可独立部署,也可**结合 Coze 或 n8n自动化工作流**,还能对接剪映实现**云渲染**,直接将草稿生成最终视频。
## 项目相关资源
- [⭐ 剪映小助手](https://github.com/Hommy-master/capcut-mate)
- [🔌 剪映小助手-扣子插件](https://www.coze.cn/store/plugin/7576197869707722771)
- [🔗 工作流案例](https://jcaigc.cn/workflow)
⭐ 如果您觉得这个项目对您有点帮助,麻烦点个 Star 支持一下!您的支持是我持续维护和改进项目的最大动力 😊
## 功能特点
- 🎬 草稿管理:创建草稿、获取草稿、保存草稿
- 🎥 素材添加:添加视频、音频、图片、贴纸、字幕、特效、遮罩等
- 🔧 高级功能:关键帧控制、文字样式、动画效果等
- 📤 视频导出:云端渲染生成最终视频
- 🛡️ 数据验证:使用 Pydantic 进行请求数据验证
- 📖 RESTful API:符合标准的 API 设计规范
- 📚 自动文档:FastAPI 自动生成交互式 API 文档
## 技术栈
- Python 3.11+
- FastAPI:高性能的 Web 框架
- Pydantic:数据验证和模型定义
- Passlib:密码加密(如果使用用户认证)
- Uvicorn:ASGI 服务器
- uv:Python 包管理器和项目管理工具
## 快速开始
### 前提条件
- Python 3.11+
- uv:Python 包管理器和项目管理工具
安装方法:
#### Windows
```powershell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
#### Linux/macOS
```bash
sh -c "$(curl -LsSf https://astral.sh/uv/install.sh)"
```
### 安装步骤
1. 克隆项目
```bash
git clone git@github.com:Hommy-master/capcut-mate.git
cd capcut-mate
```
2. 安装依赖
```bash
# 安装依赖
uv sync
# windows额外执行
uv pip install -e .[windows]
```
3. 启动服务器
```bash
uv run main.py
```
4. 访问API文档
启动后访问 http://localhost:30000/docs 查看自动生成的交互式API文档
### Docker 部署
#### 快速部署(推荐)
📺 **视频教程**:[CapCut Mate 私有化部署完整教程](https://v.douyin.com/5p-o319uA5o/)
```bash
git clone https://github.com/Hommy-master/capcut-mate.git
cd capcut-mate
docker-compose pull && docker-compose up -d
```
部署完成后,访问 API 文档:http://localhost:30000/docs
## 一键导入扣子插件
1. 打开扣子平台:https://coze.cn/home

2. 添加插件

3. 导入插件

4. 上传当前工程目录下的openapi.yaml文件

5. 完成文件上传

6. 替换logo完成

7. 启用插件

## API 接口文档
以下是 CapCut Mate API 提供的核心接口,支持完整的视频创作工作流程:
### 🏗️ 草稿管理
| 接口 | 功能 | 描述 | 文档链接 |
|------|------|------|----------|
| **create_draft** | 创建草稿 | 创建新的剪映草稿项目,设置画布尺寸 | [📖 查看文档](./docs/create_draft.zh.md) |
| **save_draft** | 保存草稿 | 保存当前草稿状态,确保编辑内容持久化 | [📖 查看文档](./docs/save_draft.zh.md) |
| **get_draft** | 获取草稿 | 获取草稿文件列表和详细信息 | [📖 查看文档](./docs/get_draft.zh.md) |
### 🎥 视频素材
| 接口 | 功能 | 描述 | 文档链接 |
|------|------|------|----------|
| **add_videos** | 添加视频 | 批量添加视频素材,支持裁剪、缩放、特效 | [📖 查看文档](./docs/add_videos.zh.md) |
| **add_images** | 添加图片 | 批量添加图片素材,支持动画和转场效果 | [📖 查看文档](./docs/add_images.zh.md) |
| **add_sticker** | 添加贴纸 | 添加装饰贴纸,支持位置和大小调整 | [📖 查看文档](./docs/add_sticker.zh.md) |
### 🎵 音频处理
| 接口 | 功能 | 描述 | 文档链接 |
|------|------|------|----------|
| **add_audios** | 添加音频 | 批量添加音频素材,支持音量和淡入淡出 | [📖 查看文档](./docs/add_audios.zh.md) |
| **get_audio_duration** | 获取音频时长 | 获取音频文件的精确时长信息 | [📖 查看文档](./docs/get_audio_duration.zh.md) |
### 📝 文本字幕
| 接口 | 功能 | 描述 | 文档链接 |
|------|------|------|----------|
| **add_captions** | 添加字幕 | 批量添加字幕,支持关键词高亮和样式设置 | [📖 查看文档](./docs/add_captions.zh.md) |
| **add_text_style** | 文本样式 | 创建富文本样式,支持关键词颜色和字体 | [📖 查看文档](./docs/add_text_style.zh.md) |
### ✨ 特效动画
| 接口 | 功能 | 描述 | 文档链接 |
|------|------|------|----------|
| **add_effects** | 添加特效 | 添加视觉特效,如滤镜、边框、动态效果 | [📖 查看文档](./docs/add_effects.zh.md) |
| **add_keyframes** | 关键帧动画 | 创建位置、缩放、旋转等属性动画 | [📖 查看文档](./docs/add_keyframes.zh.md) |
| **add_masks** |遮罩效果 | 添加各种形状遮罩,控制画面可见区域 | [📖 查看文档](./docs/add_masks.zh.md) |
### 🎨 动画资源
| 接口 | 功能 | 描述 | 文档链接 |
|------|------|------|----------|
| **get_text_animations** | 文本动画 | 获取可用的文本入场、出场、循环动画 | [📖 查看文档](./docs/get_text_animations.zh.md) |
| **get_image_animations** | 图片动画 | 获取可用的图片动画效果列表 | [📖 查看文档](./docs/get_image_animations.zh.md) |
### 🎬 视频生成
| 接口 | 功能 | 描述 | 文档链接 |
|------|------|------|----------|
| **gen_video** | 生成视频 | 提交视频渲染任务,异步处理 | [📖 查看文档](./docs/gen_video.zh.md) |
| **gen_video_status** | 查询状态 | 查询视频生成任务的进度和状态 | [📖 查看文档](./docs/gen_video_status.zh.md) |
### 🚀 快速工具
| 接口 | 功能 | 描述 | 文档链接 |
|------|------|------|----------|
| **easy_create_material** |快速创建 | 一次性添加多种类型素材,简化创建流程 | [📖 查看文档](./docs/easy_create_material.zh.md) |
### 🛠️工具类接口
|接口 |功能 |描述 | 文档链接 |
|------|------|------|----------|
| **get_url** | 提取URL | 从输入内容中提取URL信息 | [📖 查看文档](./docs/get_url.zh.md) |
| **search_sticker** |搜索贴纸 |根据关键词搜索贴纸素材 | [📖 查看文档](./docs/search_sticker.zh.md) |
| **objs_to_str_list** | 对象转字符串列表 |将对象列表转换为字符串列表格式 | [📖 查看文档](./docs/objs_to_str_list.zh.md) |
| **str_list_to_objs** | 字符串列表转对象 |将字符串列表转换为对象列表格式 | [📖 查看文档](./docs/str_list_to_objs.zh.md) |
| **str_to_list** | 字符串转列表 |将字符串转换为列表格式 | [📖 查看文档](./docs/str_to_list.zh.md) |
| **timelines** | 创建时间线 | 生成视频编辑所需的时间线配置 | [📖 查看文档](./docs/timelines.zh.md) |
| **audio_timelines** |音频时间线 |根据音频时长计算时间线 | [📖 查看文档](./docs/audio_timelines.zh.md) |
| **audio_infos** |音频信息 |根据URL和时间线生成音频信息 | [📖 查看文档](./docs/audio_infos.zh.md) |
| **imgs_infos** | 图片信息 |根据URL和时间线生成图片信息 | [📖 查看文档](./docs/imgs_infos.zh.md) |
| **caption_infos** | 字幕信息 |根据文本和时间线生成字幕信息 | [📖 查看文档](./docs/caption_infos.zh.md) |
| **effect_infos** |特信息 | 根据名称和时间线生成特效信息 | [📖 查看文档](./docs/effect_infos.zh.md) |
| **keyframes_infos** | 关键帧信息 | 根据配置生成关键帧信息 | [📖 查看文档](./docs/keyframes_infos.zh.md) |
| **video_infos** |视信息信息 | 根据URL和时间线生成视频信息 | [📖 查看文档](./docs/video_infos.zh.md) |
## API 使用示例
### 工作流案例
查看完整的真实工作流案例,了解如何将 CapCut Mate 接口与 Coze、n8n 等自动化平台结合使用:
👉 [访问工作流案例](https://jcaigc.cn/workflow)
### 创建草稿
```bash
curl -X POST "http://localhost:30000/openapi/capcut-mate/v1/create_draft" \
-H "Content-Type: application/json" \
-d '{"width": 1080, "height": 1920}'
```
### 添加视频
`video_infos` 为 **JSON 字符串**(请求体里不能写成嵌套数组)。每条记录须包含 `video_url`、`start`、`end`(时间轴上的微秒)。可选字段见 [add_videos](./docs/add_videos.zh.md)。
```bash
curl -X POST "http://localhost:30000/openapi/capcut-mate/v1/add_videos" \
-H "Content-Type: application/json" \
-d '{
"draft_url": "http://localhost:30000/openapi/capcut-mate/v1/get_draft?draft_id=20251126212753cab03392",
"video_infos": "[{\"video_url\": \"https://example.com/video.mp4\", \"start\": 0, \"end\": 1000000}]"
}'
```
## API 文档
- 本地访问: http://localhost:30000/docs
- ReDoc 版本: http://localhost:30000/redoc
## 剪映小助手客户端
剪映小助手客户端提供了桌面端的便捷操作界面,以下是启动方法:
### macOS 沙箱权限说明
在 macOS 上运行时,应用可能会请求访问特定文件夹的权限。请按照以下步骤操作:
1. 如果首次运行时出现权限提示,请允许应用访问所需文件夹
2. 如需手动配置,请前往 `系统偏好设置 > 安全性与隐私 > 隐私 > 文件夹访问`
3. 确保 CapCut Mate 应用已被添加到允许列表中
更多详细信息,请参阅 [macOS 沙箱权限配置指南](./docs/macos_sandbox_setup.md)。
1. 安装依赖
```bash
# 切换npm镜像源 - 适用于windows
set ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
# 切换yarn镜像源 - 适用于linux 或 mac
export ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
# 安装依赖
npm install --verbose
```
2. 启动项目
```bash
npm run web:dev
npm start
```
## 联系方式
| 类型 | 方式 | 说明 |
|------|------|------|
| 📱 微信群 | <div align="center"><img src="./assets/wechat-q.jpg" width="200" alt="剪映小助手"></div> | 开源社区问题交流群 |
| 💬 微信 | <div align="center"><img src="./assets/wechat.jpg" width="120" alt="技术支持微信"></div> | 商业合作 |
| 📧 邮箱 | taohongmin51@gmail.com | 技术支持 |
---
================================================
FILE: config/huazi.json
================================================
[
{
"id": "7539407429763796249",
"title": "红黄火焰综艺花字",
"is_vip": true
},
{
"id": "7351316503771368713",
"title": "综艺-黑暗斑驳红色",
"is_vip": true
},
{
"id": "7403923146862087424",
"title": "蓝白色立体综艺描边花字",
"is_vip": true
},
{
"id": "7527336771223407934",
"title": "花字",
"is_vip": true
},
{
"id": "7506878563723840783",
"title": "黄字橙光花字",
"is_vip": true
},
{
"id": "7351314020114124068",
"title": "综艺-我看看 太夸张了吧!!",
"is_vip": true
},
{
"id": "7404884940837473590",
"title": "黑色描边花字",
"is_vip": true
},
{
"id": "7272728092529986827",
"title": "音乐节-超粗描边",
"is_vip": true
},
{
"id": "7160594825933262087",
"title": "潮酷橙底黄色渐变立体花字",
"is_vip": true
},
{
"id": "7212892794778668345",
"title": "美食-肉",
"is_vip": true
},
{
"id": "7405155739943079178",
"title": "蓝白渐变立体花字",
"is_vip": true
},
{
"id": "7477040473454939454",
"title": "橙黄色描边立体花字",
"is_vip": true
},
{
"id": "7406159958045232435",
"title": "动感黄色发光故障风花字",
"is_vip": true
},
{
"id": "7404758577623289123",
"title": "渐变黄红色发光字",
"is_vip": true
},
{
"id": "7403930784630967604",
"title": "黄色渐变红描边发光字",
"is_vip": true
},
{
"id": "7371391474404986150",
"title": "火焰燃烧花字",
"is_vip": true
},
{
"id": "7508541988401368345",
"title": "618立体",
"is_vip": true
},
{
"id": "7545767280450227481",
"title": "花字",
"is_vip": true
},
{
"id": "7404010442118515994",
"title": "渐变黄色立体描边花字",
"is_vip": true
},
{
"id": "7546806821701504281",
"title": "金箔纹理字",
"is_vip": true
},
{
"id": "7406646972330953994",
"title": "蓝色质感渐变立体",
"is_vip": true
},
{
"id": "7431415454515612963",
"title": "蓝字黄背景字",
"is_vip": true
},
{
"id": "7403728277036125449",
"title": "白色蓝边立体花字",
"is_vip": true
},
{
"id": "7404668885196131603",
"title": "黄色渐变描边花字",
"is_vip": true
},
{
"id": "7508204538659310872",
"title": "黄色花字",
"is_vip": true
},
{
"id": "7405520166701813018",
"title": "白色纹理花字",
"is_vip": true
},
{
"id": "7371423297289866505",
"title": "蓝色冰块立体花字",
"is_vip": true
},
{
"id": "7477792820707757336",
"title": "黄红色渐变立体花字",
"is_vip": true
},
{
"id": "7533685266033347902",
"title": "黄橙渐变立体秋日花字",
"is_vip": true
},
{
"id": "7548286146946616600",
"title": "红金立体发光花字",
"is_vip": true
},
{
"id": "7430745422412549385",
"title": "花字",
"is_vip": true
},
{
"id": "7406860981114015014",
"title": "蓝色渐变花光字",
"is_vip": true
},
{
"id": "7405788077832080659",
"title": "黄色立体字(秋天)",
"is_vip": true
},
{
"id": "7450158325188070668",
"title": "裂缝纹理投影",
"is_vip": true
},
{
"id": "7441868112556739849",
"title": "元旦新年氛围金色闪粉发光花字",
"is_vip": true
},
{
"id": "7479056232117062937",
"title": "红黄描边立体",
"is_vip": true
},
{
"id": "7406015916380605733",
"title": "金色发光镂空花字",
"is_vip": true
},
{
"id": "7311259207590776075",
"title": "运动教程-花字",
"is_vip": true
},
{
"id": "7478970969026022680",
"title": "综艺风红色渐变纹理立体花字",
"is_vip": true
},
{
"id": "7406221865171111208",
"title": "蓝色立体描边文字",
"is_vip": true
},
{
"id": "7447932873845247286",
"title": "25元旦-晕染红描边",
"is_vip": true
},
{
"id": "7404700591949204799",
"title": "蓝色蜡笔纹理立体花字",
"is_vip": true
},
{
"id": "7403915995569474870",
"title": "粉笔拼贴花字(教师节)",
"is_vip": true
},
{
"id": "7523881114054970648",
"title": "黄色渐变粉蓝描边立体花字",
"is_vip": true
},
{
"id": "7480494571168795966",
"title": "蓝色花字",
"is_vip": true
},
{
"id": "7350889130865265970",
"title": "轻复古",
"is_vip": true
},
{
"id": "7127681027346058503",
"title": "综艺 红色渐变",
"is_vip": true
},
{
"id": "7404140347892305202",
"title": "蓝白霓虹灯镂空效果发光花字",
"is_vip": true
},
{
"id": "7404837954532789523",
"title": "黄色立体描边多彩花字",
"is_vip": true
},
{
"id": "7406655431940033792",
"title": "黄字彩色多层投影文字",
"is_vip": true
},
{
"id": "7506824081531243801",
"title": "红色紫色渐变立体描边花字",
"is_vip": true
},
{
"id": "7347907413363789094",
"title": "黄色渐变立体花字",
"is_vip": true
},
{
"id": "7212896770370571557",
"title": "美食-发光白",
"is_vip": true
},
{
"id": "7400711954731371786",
"title": "复古橙黄渐变醒目",
"is_vip": true
},
{
"id": "7430861390933413130",
"title": "冬至立体",
"is_vip": true
},
{
"id": "7278242937488690493",
"title": "黑底白色立体花字",
"is_vip": true
},
{
"id": "7405521516131093795",
"title": "金边浮雕文字",
"is_vip": true
},
{
"id": "7467426470714051902",
"title": "橘黄色渐变温柔发光花字",
"is_vip": true
},
{
"id": "7496504150797274393",
"title": "蓝色闪粉星光闪闪发光划走",
"is_vip": true
},
{
"id": "7368866329337580851",
"title": "上下错落发光花字",
"is_vip": true
},
{
"id": "7362931435809901859",
"title": "蓝色立体",
"is_vip": true
},
{
"id": "7231501825311116577",
"title": "蓝字白边蓝光花字",
"is_vip": true
},
{
"id": "7477883005953051928",
"title": "岩石花字",
"is_vip": true
},
{
"id": "7375227839542480191",
"title": "618-红紫渐变",
"is_vip": true
},
{
"id": "7494576393569733913",
"title": "简约黄蓝方块综艺花字",
"is_vip": true
},
{
"id": "7511243674546867518",
"title": "红色",
"is_vip": true
},
{
"id": "7311259516392197439",
"title": "运动教程-花字",
"is_vip": true
},
{
"id": "7404134454844788018",
"title": "3D蓝字黄边立体综艺花字",
"is_vip": true
},
{
"id": "7485579082764225817",
"title": "黄色渐变纹理粉蓝立体花字",
"is_vip": true
},
{
"id": "7303813440127126836",
"title": "JP冬日-结霜字",
"is_vip": true
},
{
"id": "7405872381320842515",
"title": "红粉渐变花字",
"is_vip": true
},
{
"id": "7406170424935058726",
"title": "紫色阴森情绪发光花字",
"is_vip": true
},
{
"id": "7343614179732966691",
"title": "黄底字",
"is_vip": true
},
{
"id": "7298566943722851594",
"title": "黄色渐变立体花字",
"is_vip": true
},
{
"id": "7404440675225292083",
"title": "红黄渐变背景花字",
"is_vip": true
},
{
"id": "7404352881861659931",
"title": "渐变黄字红边星光立体花字",
"is_vip": true
},
{
"id": "7405221368561700148",
"title": "黄紫撞色复古立体字",
"is_vip": true
},
{
"id": "7404008412607958323",
"title": "霓虹灯花字",
"is_vip": true
},
{
"id": "7308367002253544741",
"title": "红色渐变白霜立体花字",
"is_vip": true
},
{
"id": "7405906746461424930",
"title": "红色复古投影字",
"is_vip": true
},
{
"id": "7488151895048211736",
"title": "像素化花字",
"is_vip": true
},
{
"id": "7492933140210666776",
"title": "蓝橙色立体花字",
"is_vip": true
},
{
"id": "7360526293596671273",
"title": "拼贴多色",
"is_vip": true
},
{
"id": "7546405848860511513",
"title": "黄蓝紫渐变立体花字",
"is_vip": true
},
{
"id": "7160599091750161671",
"title": "复古红色发光立体花字",
"is_vip": true
},
{
"id": "7434585603439742218",
"title": "综艺红黄立体",
"is_vip": true
},
{
"id": "7351319129124506930",
"title": "综艺-巅峰 厉害!!真是太火爆了!!!2",
"is_vip": true
},
{
"id": "7525867881331215640",
"title": "黄红蓝边立体花字",
"is_vip": true
},
{
"id": "7406970077368618274",
"title": "复古黄色立体",
"is_vip": true
},
{
"id": "7431490038736702760",
"title": "黄蓝立体字",
"is_vip": true
},
{
"id": "7533790251915955518",
"title": "花字",
"is_vip": true
},
{
"id": "7408956728529751333",
"title": "黄色霓虹灯发光花字",
"is_vip": true
},
{
"id": "7532883085390548286",
"title": "花字",
"is_vip": true
},
{
"id": "7509743284898794777",
"title": "黄色马卡龙",
"is_vip": true
},
{
"id": "7406334288930557218",
"title": "撞色描边立体字",
"is_vip": true
},
{
"id": "7405871504769961254",
"title": "游戏像素文字效果花字",
"is_vip": true
},
{
"id": "7475271686095506712",
"title": "粉色立体字",
"is_vip": true
},
{
"id": "7330423055900069155",
"title": "霓虹灯花字",
"is_vip": true
},
{
"id": "7389147072064179506",
"title": "黄色红色",
"is_vip": true
},
{
"id": "7539187400808123672",
"title": "红樱桃",
"is_vip": true
},
{
"id": "7474511004676803902",
"title": "粉紫描边立体",
"is_vip": true
},
{
"id": "7495665652816956697",
"title": "花字",
"is_vip": true
},
{
"id": "7405070516706381092",
"title": "渐变黄色中秋圆底花字",
"is_vip": true
},
{
"id": "7430809868333780259",
"title": "复古背景字",
"is_vip": true
},
{
"id": "7259922491185958203",
"title": "蓝紫色粗体描边花字",
"is_vip": true
},
{
"id": "7403962881252805903",
"title": "黄绿发光字",
"is_vip": true
},
{
"id": "7366086107366182153",
"title": "粉蓝色渐变立体发光花字",
"is_vip": true
},
{
"id": "7525463353603640601",
"title": "花字",
"is_vip": true
},
{
"id": "7474605929825193240",
"title": "粉色描边白色字",
"is_vip": true
},
{
"id": "7536671491740634392",
"title": "穿搭立体",
"is_vip": true
},
{
"id": "7264547410817387795",
"title": "好物美妆-黄白跳色",
"is_vip": true
},
{
"id": "7411032759457631515",
"title": "绿色东南亚",
"is_vip": true
},
{
"id": "7520663448003415358",
"title": "蓝色纸纹纹理花字",
"is_vip": true
},
{
"id": "7406976068789210403",
"title": "红黄渐变发光字",
"is_vip": true
},
{
"id": "7396798321739730226",
"title": "粉色星空花字",
"is_vip": true
},
{
"id": "7404321887817452800",
"title": "粉色立体字",
"is_vip": true
},
{
"id": "7405501393248881960",
"title": "金属划痕暗黑立体字",
"is_vip": true
},
{
"id": "7507145578984361241",
"title": "粉色",
"is_vip": true
},
{
"id": "7407078807309503744",
"title": "橘黄色立体字",
"is_vip": true
},
{
"id": "7362054905256758591",
"title": "双色爱心花字",
"is_vip": true
},
{
"id": "7532428202199797016",
"title": "三花猫配色",
"is_vip": true
},
{
"id": "7477511783801163032",
"title": "绿色立体花字",
"is_vip": true
},
{
"id": "7293329973694172435",
"title": "高级幻彩花紫字",
"is_vip": true
},
{
"id": "7406650793631223075",
"title": "红绿撞色发光字",
"is_vip": true
},
{
"id": "7265723229216525620",
"title": "绿色发光花字",
"is_vip": true
},
{
"id": "7404290078723312931",
"title": "绿色渐变背景字",
"is_vip": true
},
{
"id": "7527597707930799422",
"title": "蓝绿纹理花字",
"is_vip": true
},
{
"id": "7376607395046231331",
"title": "粉色立体渐变",
"is_vip": true
},
{
"id": "7405087980685167922",
"title": "黄色立体花字",
"is_vip": true
},
{
"id": "7478268728992419096",
"title": "花字",
"is_vip": true
},
{
"id": "7398456039634406666",
"title": "#花字招募令 彩虹花字",
"is_vip": true
},
{
"id": "7404459246961577257",
"title": "少女粉星星花字",
"is_vip": true
},
{
"id": "7404471553607421222",
"title": "未来科技感发光花字",
"is_vip": true
},
{
"id": "7241759007952735491",
"title": "潮流紫色荧光花字",
"is_vip": true
},
{
"id": "7404263174230297882",
"title": "橙色渐变花字",
"is_vip": true
},
{
"id": "7430667459683831079",
"title": "可爱花字",
"is_vip": true
},
{
"id": "7539752808367574297",
"title": "渐变综艺发光花字",
"is_vip": true
},
{
"id": "7293140122332122368",
"title": "橙色万圣花字",
"is_vip": true
},
{
"id": "7406388990837886234",
"title": "棕色立体粗描边",
"is_vip": true
},
{
"id": "7260043007997562149",
"title": "立体字",
"is_vip": true
},
{
"id": "7481664682638560537",
"title": "酸性质感花字",
"is_vip": true
},
{
"id": "7492430244570303806",
"title": "绿色渐变立体花字",
"is_vip": true
},
{
"id": "7404304312135896360",
"title": "赛博朋克风故障字",
"is_vip": true
},
{
"id": "7404522256929459494",
"title": "粉色立体花字",
"is_vip": true
},
{
"id": "7475398432807521561",
"title": "粉橙立体花字",
"is_vip": true
},
{
"id": "7362833837627378944",
"title": "复古牛皮纸花字",
"is_vip": true
},
{
"id": "7306894668795612442",
"title": "黑色纹理立体花字",
"is_vip": true
},
{
"id": "7349078136480386345",
"title": "圆环花字",
"is_vip": true
},
{
"id": "7509044952912055614",
"title": "薰衣草",
"is_vip": true
},
{
"id": "7404757226583362854",
"title": "清新条纹投影纹理花字",
"is_vip": true
},
{
"id": "7406238235141213440",
"title": "马卡龙色渐变文字",
"is_vip": true
},
{
"id": "7351431205692181786",
"title": "白字红光花字",
"is_vip": true
},
{
"id": "7333249201419160868",
"title": "纹理花字",
"is_vip": true
},
{
"id": "7405049138867424523",
"title": "描边橙色黄色双色立体花字",
"is_vip": true
},
{
"id": "7491540791689530686",
"title": "粉色渐变",
"is_vip": true
},
{
"id": "7371110382393494793",
"title": "黄粉色立体渐变花字",
"is_vip": true
},
{
"id": "7388017781117160745",
"title": "低饱和紫色渐变综艺花字",
"is_vip": true
},
{
"id": "7404083693003853096",
"title": "莫兰迪清新蓝色描边花字",
"is_vip": true
},
{
"id": "7405888865132711220",
"title": "节日花字",
"is_vip": true
},
{
"id": "7174401031399312670",
"title": "3D多层渐变红",
"is_vip": true
},
{
"id": "7389185223600114995",
"title": "红色",
"is_vip": true
},
{
"id": "7405856965332585764",
"title": "多色渐变花字",
"is_vip": true
},
{
"id": "7173927171881323789",
"title": "3D腮绿",
"is_vip": true
},
{
"id": "7431429108791266611",
"title": "黄色渐变纹理花字",
"is_vip": true
},
{
"id": "7404772432323546422",
"title": "黄绿色立体纹理花字",
"is_vip": true
},
{
"id": "7371117571757641011",
"title": "白字橘色描边立体花字",
"is_vip": true
},
{
"id": "7378313478852906280",
"title": "蓝色纹理白描边花字",
"is_vip": true
},
{
"id": "7388024664980770060",
"title": "桃红色渐变立体花字",
"is_vip": true
},
{
"id": "7404058441481866511",
"title": "潮酷粉黄撞色立体花字",
"is_vip": true
},
{
"id": "7345391635267603753",
"title": "复古镂空花字",
"is_vip": true
},
{
"id": "7405944611430092066",
"title": "粉黄渐变立体字",
"is_vip": true
},
{
"id": "7392196588426382629",
"title": "绿橙花字",
"is_vip": true
},
{
"id": "7406225575712443663",
"title": "中式背景框文字",
"is_vip": true
},
{
"id": "7366911458824752410",
"title": "彩色花边花字",
"is_vip": true
},
{
"id": "7539491294188440857",
"title": "节日粉色渐变立体描边花字",
"is_vip": true
},
{
"id": "7476505479364201753",
"title": "黄绿综艺花字",
"is_vip": true
},
{
"id": "7405039371037986089",
"title": "抹茶绿多层描边立体花字",
"is_vip": true
},
{
"id": "7407013513979251978",
"title": "粉紫色渐变立体发光花字",
"is_vip": true
},
{
"id": "7475276656626863385",
"title": "红粉色渐变立体发光花字",
"is_vip": true
},
{
"id": "7543043727103675673",
"title": "花字",
"is_vip": true
},
{
"id": "7265614497119735040",
"title": "粉色亮晶晶花字",
"is_vip": true
},
{
"id": "7336859597287804169",
"title": "樱花粉 粉色花字",
"is_vip": true
},
{
"id": "7405924713400126747",
"title": "蓝绿立体花字",
"is_vip": true
},
{
"id": "7293778917603822848",
"title": "万圣紫色花字",
"is_vip": true
},
{
"id": "7350157127207456037",
"title": "3D粉色立体花字",
"is_vip": true
},
{
"id": "7542084187285703998",
"title": "粉蓝色渐变爱心底花字",
"is_vip": true
},
{
"id": "7359406447718862131",
"title": "五一立体",
"is_vip": true
},
{
"id": "7409954407321783586",
"title": "粉色紫边立体字",
"is_vip": true
},
{
"id": "7537970908221394238",
"title": "立体黄蓝纹理花字",
"is_vip": true
},
{
"id": "7403948957547760906",
"title": "3D粉色渐变立体花字",
"is_vip": true
},
{
"id": "7312845270671232294",
"title": "浅蓝黄渐变立体花字",
"is_vip": true
},
{
"id": "7480506672746794264",
"title": "复古红色立体花字",
"is_vip": true
},
{
"id": "7431433243922107689",
"title": "绿色花字",
"is_vip": true
},
{
"id": "7411406288350874917",
"title": "美妆纹理",
"is_vip": true
},
{
"id": "7404294636656774451",
"title": "黄绿花字",
"is_vip": true
},
{
"id": "7404705863442713910",
"title": "糖果色彩色渐变描边花字",
"is_vip": true
},
{
"id": "7298637894481169701",
"title": "粉色立体花字",
"is_vip": true
},
{
"id": "7252284645998464288",
"title": "蓝色渐变花字",
"is_vip": true
},
{
"id": "7339054041458036006",
"title": "纹理花字",
"is_vip": true
},
{
"id": "7404307108625206563",
"title": "纹理复古深色字",
"is_vip": true
},
{
"id": "7404774919315197195",
"title": "红色描边黄色花字",
"is_vip": true
},
{
"id": "7404884426150235418",
"title": "白字黑边裂痕综艺花字",
"is_vip": true
},
{
"id": "7404394775664708901",
"title": "黄字红边立体粗描边花字",
"is_vip": true
},
{
"id": "7405990788053683482",
"title": "国风水墨",
"is_vip": true
},
{
"id": "7407352720815836443",
"title": "火焰立体",
"is_vip": true
},
{
"id": "7405218557342059816",
"title": "红色描边纹理立体字",
"is_vip": true
},
{
"id": "7495216846946274584",
"title": "蓝色渐变阴影立体花字",
"is_vip": true
},
{
"id": "7405838293843070234",
"title": "红色立体纹理花字",
"is_vip": true
},
{
"id": "7368685720325655817",
"title": "渐变花字",
"is_vip": true
},
{
"id": "7360556929959087397",
"title": "纸质",
"is_vip": true
},
{
"id": "7404520330502458674",
"title": "蓝白色渐变立体花字",
"is_vip": true
},
{
"id": "7547970729258519833",
"title": "花字",
"is_vip": true
},
{
"id": "7507097456283274520",
"title": "蓝色",
"is_vip": true
},
{
"id": "7404819849140063551",
"title": "黑白线条花字",
"is_vip": true
},
{
"id": "7482688482754694462",
"title": "愚人节立体",
"is_vip": true
},
{
"id": "7406740764207713577",
"title": "中秋桂花花字",
"is_vip": true
},
{
"id": "7455608333563874585",
"title": "花字",
"is_vip": true
},
{
"id": "7430822256806284594",
"title": "双十一红黄立体",
"is_vip": true
},
{
"id": "7459686003079630104",
"title": "金色渐变立体红边发光花字",
"is_vip": true
},
{
"id": "7405031205877419305",
"title": "银色渐变描边发光花字",
"is_vip": true
},
{
"id": "7474543369054702910",
"title": "白色立体花字",
"is_vip": true
},
{
"id": "7405927551417306378",
"title": "蓝色渐变镂空描边花字",
"is_vip": true
},
{
"id": "7405716848106310931",
"title": "蓝白立体花字",
"is_vip": true
},
{
"id": "7371368226606943514",
"title": "白色发光花字",
"is_vip": true
},
{
"id": "7404877070158908698",
"title": "金红纸纹理发光字",
"is_vip": true
},
{
"id": "7241953374780804410",
"title": "橙白渐变花字 黑白描边花字",
"is_vip": true
},
{
"id": "7405518341814668544",
"title": "云纹金箔字",
"is_vip": true
},
{
"id": "7478934394141527358",
"title": "综艺风黄色渐变纹理立体花字",
"is_vip": true
},
{
"id": "7371410942061546803",
"title": "蓝红色立体综艺花字",
"is_vip": true
},
{
"id": "7507460201549843736",
"title": "红金国风花字",
"is_vip": true
},
{
"id": "7404667171537767699",
"title": "黄色渐变描边立体花字",
"is_vip": true
},
{
"id": "7509041829556522265",
"title": "白纸纹理蓝阴影花字",
"is_vip": true
},
{
"id": "7406648659976260903",
"title": "国风花字",
"is_vip": true
},
{
"id": "7405933257776172314",
"title": "黑色拼贴方底花字",
"is_vip": true
},
{
"id": "7360986749046213928",
"title": "描边字",
"is_vip": true
},
{
"id": "7465177921276136766",
"title": "花字",
"is_vip": true
},
{
"id": "7406200724171787574",
"title": "点金花字",
"is_vip": true
},
{
"id": "7406693646592003366",
"title": "白字内发光蓝边字",
"is_vip": true
},
{
"id": "7371351770045484338",
"title": "米白厚底立体花字",
"is_vip": true
},
{
"id": "7405529606859607347",
"title": "水墨红底白色花字",
"is_vip": true
},
{
"id": "7404709465209064745",
"title": "条纹纹理黄色立体花字",
"is_vip": true
},
{
"id": "7404872280662166834",
"title": "红色恐怖氛围纹理花字",
"is_vip": true
},
{
"id": "7459675119116373272",
"title": "蓝色折纸",
"is_vip": true
},
{
"id": "7434560086166490418",
"title": "港风立体",
"is_vip": true
},
{
"id": "7431445423283244297",
"title": "红色发光花字",
"is_vip": true
},
{
"id": "7404696990510042402",
"title": "黄色渐变立体字",
"is_vip": true
},
{
"id": "7506829483878649150",
"title": "蓝莓奶酪",
"is_vip": true
},
{
"id": "7451570972550991166",
"title": "新年立体花字",
"is_vip": true
},
{
"id": "7430745414313332006",
"title": "花字",
"is_vip": true
},
{
"id": "7447831886874938678",
"title": "25元旦-红花背景花字",
"is_vip": true
},
{
"id": "7404523157400472869",
"title": "黑色金箔描边立体花字",
"is_vip": true
},
{
"id": "7405537335850306853",
"title": "灰白水墨国风花字",
"is_vip": true
},
{
"id": "7405801186286259466",
"title": "科技感朋克发光立体标题花字",
"is_vip": true
},
{
"id": "7405067510053211446",
"title": "田字格图案蜡笔纹理花字",
"is_vip": true
},
{
"id": "7406637506977877299",
"title": "黄红撞色立体",
"is_vip": true
},
{
"id": "7405203982286720256",
"title": "中式背景文字",
"is_vip": true
},
{
"id": "7472013339640614206",
"title": "日综蓝白方框字",
"is_vip": true
},
{
"id": "7436409520848522546",
"title": "综艺蓝黄立体",
"is_vip": true
},
{
"id": "7405514240779357449",
"title": "水墨风白字黑边红墨点花字",
"is_vip": true
},
{
"id": "7507075178447359282",
"title": "创意立体黄色花字高级感主题文字封面标题字",
"is_vip": true
},
{
"id": "7509055757908806937",
"title": "白色",
"is_vip": true
},
{
"id": "7406683118108806437",
"title": "黄字黑边",
"is_vip": true
},
{
"id": "7411036229677878554",
"title": "大理石花纹字",
"is_vip": true
},
{
"id": "7404409329991879988",
"title": "中秋黄色字",
"is_vip": true
},
{
"id": "7481983816001834265",
"title": "综艺感黄色立体描边花字",
"is_vip": true
},
{
"id": "7548895672402185497",
"title": "月饼花字",
"is_vip": true
},
{
"id": "7406980293233560859",
"title": "蓝色渐变微立体花字",
"is_vip": true
},
{
"id": "7371372494336396570",
"title": "白字橘色发光花字",
"is_vip": true
},
{
"id": "7404700217553063209",
"title": "几何纹理黑色阴影花字",
"is_vip": true
},
{
"id": "7411046109285485861",
"title": "悬疑剧字幕",
"is_vip": true
},
{
"id": "7479073211918044441",
"title": "蓝色纹理花字",
"is_vip": true
},
{
"id": "7369127125569342731",
"title": "划重点花字",
"is_vip": true
},
{
"id": "7533453859830713662",
"title": "橙色底纹花字",
"is_vip": true
},
{
"id": "7405034038135655719",
"title": "雪花图案渐变蓝色立体花字",
"is_vip": true
},
{
"id": "7455983000291937586",
"title": "蓝色渐变描边简约风格花字",
"is_vip": true
},
{
"id": "7495033287438781758",
"title": "黄色渐变橘色阴影立体花字",
"is_vip": true
},
{
"id": "7296357486490144036",
"title": "双十一-立体紫色",
"is_vip": true
},
{
"id": "7533293069123390744",
"title": "黄色贴纸描边字效",
"is_vip": true
},
{
"id": "7283715592316554555",
"title": "渐变蓝色阴影",
"is_vip": true
},
{
"id": "7405536862133046565",
"title": "黑白水墨花字",
"is_vip": true
},
{
"id": "7405517504128273676",
"title": "复古黄沙水彩纹理花字",
"is_vip": true
},
{
"id": "7461550488073538841",
"title": "红色渐变",
"is_vip": true
},
{
"id": "7431460080228257039",
"title": "潮酷背景字",
"is_vip": true
},
{
"id": "7404391553164135715",
"title": "撞色描边字",
"is_vip": true
},
{
"id": "7406690026009972004",
"title": "紫色立体花字",
"is_vip": true
},
{
"id": "7431012567369125161",
"title": "冬季渐变蓝色立体花字",
"is_vip": true
},
{
"id": "7405414031072169250",
"title": "红黄复古浮雕纹理字",
"is_vip": true
},
{
"id": "7404702615671508263",
"title": "3D渐变橘红色立体花字",
"is_vip": true
},
{
"id": "7404522414941424923",
"title": "粉蓝渐变花字",
"is_vip": true
},
{
"id": "7511273485730237758",
"title": "花字",
"is_vip": true
},
{
"id": "7491617722359565630",
"title": "花字",
"is_vip": true
},
{
"id": "7405795232748490025",
"title": "黑紫星空花字",
"is_vip": true
},
{
"id": "7430642926293732658",
"title": "冷色调简单花字",
"is_vip": true
},
{
"id": "7371420451526020389",
"title": "金色渐变立体花字",
"is_vip": true
},
{
"id": "7404507481205984539",
"title": "红色金箔纹理立体花字",
"is_vip": true
},
{
"id": "7405570848041487666",
"title": "黄蓝撞色纹理立体花字",
"is_vip": true
},
{
"id": "7365356770652376330",
"title": "花字",
"is_vip": true
},
{
"id": "7406353145938382130",
"title": "渐变圆底花字",
"is_vip": true
},
{
"id": "7444510136296541465",
"title": "白字蓝粉相间底色花字",
"is_vip": true
},
{
"id": "7505458612001852697",
"title": "综艺风黄色立体描边花字",
"is_vip": true
},
{
"id": "7430855417703435529",
"title": "蓝色纸张质感立体花字",
"is_vip": true
},
{
"id": "7407037141584203059",
"title": "彩色带图案花字",
"is_vip": true
},
{
"id": "7481302843849329982",
"title": "红蓝橙描边立体花字",
"is_vip": true
},
{
"id": "7407464175347272998",
"title": "红色印章花字",
"is_vip": true
},
{
"id": "7493107948286250302",
"title": "五一立体",
"is_vip": true
},
{
"id": "7371414308770647346",
"title": "淡黄色渐变发光花字",
"is_vip": true
},
{
"id": "7405931282632412442",
"title": "白色方底拼贴花字",
"is_vip": true
},
{
"id": "7548337425781935422",
"title": "红金立体国风花字",
"is_vip": true
},
{
"id": "7405492993878281510",
"title": "暗黑金泼墨风花字",
"is_vip": true
},
{
"id": "7545366362924043582",
"title": "花字",
"is_vip": true
},
{
"id": "7442261279013604644",
"title": "红色描边花字",
"is_vip": true
},
{
"id": "7506868020917226777",
"title": "金色渐变立体花字",
"is_vip": true
},
{
"id": "7405152529522101531",
"title": "橙色立体花字",
"is_vip": true
},
{
"id": "7412523765768178944",
"title": "红色锈迹文字",
"is_vip": true
},
{
"id": "7398455661513674035",
"title": "紫色渐变",
"is_vip": true
},
{
"id": "7398454655505763593",
"title": "黄色",
"is_vip": true
},
{
"id": "7406687421921791282",
"title": "黑色渐变白蓝描边",
"is_vip": true
},
{
"id": "7506872589642665240",
"title": "端午61立体字效",
"is_vip": true
},
{
"id": "7405120470477065507",
"title": "黄色立体文字",
"is_vip": true
},
{
"id": "7431452163181792524",
"title": "花字",
"is_vip": true
},
{
"id": "7236984607575461154",
"title": "炫彩模糊花字",
"is_vip": true
},
{
"id": "7494656119529393470",
"title": "五四青年立体",
"is_vip": true
},
{
"id": "7406389812925680933",
"title": "复古方底立体",
"is_vip": true
},
{
"id": "7467033569848839486",
"title": "喜庆花字",
"is_vip": true
},
{
"id": "7546585357555649816",
"title": "中秋黄白立体字效",
"is_vip": true
},
{
"id": "7403927160563551528",
"title": "黄蓝色立体综艺描边花字",
"is_vip": true
},
{
"id": "7405229843220106534",
"title": "白紫色立体花字",
"is_vip": true
},
{
"id": "7372363920864005386",
"title": "金色渐变立体发光花字",
"is_vip": true
},
{
"id": "7547731905500794174",
"title": "花字",
"is_vip": true
},
{
"id": "7471910410766109977",
"title": "蓝色描边立体花字",
"is_vip": true
},
{
"id": "7505771535878098200",
"title": "黄色白色",
"is_vip": true
},
{
"id": "7406364344176414003",
"title": "渐变色白边立体花字",
"is_vip": true
},
{
"id": "7403728040653573387",
"title": "橘猫花字",
"is_vip": true
},
{
"id": "7409333268195101979",
"title": "综艺字立体",
"is_vip": true
},
{
"id": "7455529495043525950",
"title": "红橘新年花字",
"is_vip": true
},
{
"id": "7449034603760749839",
"title": "红包花字",
"is_vip": true
},
{
"id": "7231489008126266679",
"title": "花字 经典黄色加深蓝经典配色凸显文字",
"is_vip": true
},
{
"id": "7519880279205448984",
"title": "橙色花字",
"is_vip": true
},
{
"id": "7371415414817000754",
"title": "淡蓝色渐变发光花字",
"is_vip": true
},
{
"id": "7406385391265156362",
"title": "紫色双层描边花字",
"is_vip": true
},
{
"id": "7455254263888104766",
"title": "新年红金花字",
"is_vip": true
},
{
"id": "7357027100324367627",
"title": "晕染蓝",
"is_vip": true
},
{
"id": "7431440010152316169",
"title": "黑色渐变立体花字",
"is_vip": true
},
{
"id": "7360540744035142953",
"title": "拼贴绿",
"is_vip": true
},
{
"id": "7404370982238014747",
"title": "橘黄色波点渐变发光花字",
"is_vip": true
},
{
"id": "7403764204420730122",
"title": "红黄白多层渐变立体花字",
"is_vip": true
},
{
"id": "7364604452323495204",
"title": "蓝色渐变",
"is_vip": true
},
{
"id": "7404415905066782004",
"title": "黄绿高饱和多重描边字",
"is_vip": true
},
{
"id": "7400335293565455679",
"title": "粉色发光花字",
"is_vip": true
},
{
"id": "7430397468082228543",
"title": "简约雪纹理立体花字",
"is_vip": true
},
{
"id": "7450496790354234674",
"title": "白字红边重影风格花字",
"is_vip": true
},
{
"id": "7385227292521418018",
"title": "蓝色渐变",
"is_vip": true
},
{
"id": "7366060581410901286",
"title": "粉蓝色渐变立体发光花字",
"is_vip": true
},
{
"id": "7405831511003417871",
"title": "黄色奶酪字",
"is_vip": true
},
{
"id": "7406673678412418354",
"title": "彩虹色描边白字",
"is_vip": true
},
{
"id": "7406360821216988416",
"title": "橙黄色渐变立体花字",
"is_vip": true
},
{
"id": "7430856547934211379",
"title": "蓝色纸张质感黄底花字",
"is_vip": true
},
{
"id": "7533174868930645273",
"title": "花字",
"is_vip": true
},
{
"id": "7474476846223101209",
"title": "粉色爱心立体字",
"is_vip": true
},
{
"id": "7406335734044577035",
"title": "蓝色纹理立体描边花字",
"is_vip": true
},
{
"id": "7360960769703398695",
"title": "拼贴浅红",
"is_vip": true
},
{
"id": "7359358208286215464",
"title": "红色花字 ",
"is_vip": true
},
{
"id": "7347989608908606783",
"title": "故障字",
"is_vip": true
},
{
"id": "7538998611628084542",
"title": "橙色秋叶立体花字",
"is_vip": true
},
{
"id": "7546423084874599705",
"title": "国庆黄红立体字效",
"is_vip": true
},
{
"id": "7548711671317974334",
"title": "黄红渐变纹理花字",
"is_vip": true
},
{
"id": "7538711238725946649",
"title": "黄橙玻璃质感秋日花字",
"is_vip": true
},
{
"id": "7406380674057358642",
"title": "复古黄色方底背景",
"is_vip": true
},
{
"id": "7539626317688425753",
"title": "花字",
"is_vip": true
},
{
"id": "7548813025013419289",
"title": "花字",
"is_vip": true
},
{
"id": "7540868241737141529",
"title": "花字",
"is_vip": true
},
{
"id": "7546349045032439102",
"title": "立体桔黄",
"is_vip": true
},
{
"id": "7538719944897236286",
"title": "花字",
"is_vip": true
},
{
"id": "7509793945480613144",
"title": "618黑边",
"is_vip": true
},
{
"id": "7508042807811280190",
"title": "综艺风红色立体描边花字",
"is_vip": true
},
{
"id": "7509930498681163032",
"title": "高考立体",
"is_vip": true
},
{
"id": "7545871911138577726",
"title": "糖炒栗子",
"is_vip": true
},
{
"id": "7540131523937357118",
"title": "花字",
"is_vip": true
},
{
"id": "7546127896943840536",
"title": "花字",
"is_vip": true
},
{
"id": "7546131418620071192",
"title": "斜纹花字",
"is_vip": true
},
{
"id": "7507853100984667416",
"title": "黄色渐变蓝色描边立体花字",
"is_vip": true
},
{
"id": "7527398816782454040",
"title": "三原色",
"is_vip": true
},
{
"id": "7546032665510841662",
"title": "糖炒栗子",
"is_vip": true
},
{
"id": "7544777148205190425",
"title": "花字",
"is_vip": true
},
{
"id": "7511339634761420057",
"title": "黄色纹理蓝棕色阴影描边立体花字",
"is_vip": true
},
{
"id": "7533092158820142360",
"title": "橙色渐变立体花字",
"is_vip": true
},
{
"id": "7532701961364278553",
"title": "立体花字",
"is_vip": true
},
{
"id": "7535694140227456280",
"title": "毛绒字",
"is_vip": true
},
{
"id": "7506898516468370750",
"title": "我的潮流指南",
"is_vip": true
},
{
"id": "7507101495339568446",
"title": "蓝莓奶酪",
"is_vip": true
},
{
"id": "7495312625169911065",
"title": "综艺风蓝色立体描边花字",
"is_vip": true
},
{
"id": "7477620313522703678",
"title": "彩铅渐变黄色花字",
"is_vip": true
},
{
"id": "7474582555853901080",
"title": "彩色",
"is_vip": true
},
{
"id": "7480089681586130238",
"title": "膨胀感字",
"is_vip": true
},
{
"id": "7492216396290542873",
"title": "花字",
"is_vip": true
},
{
"id": "7507526398710435097",
"title": "花字",
"is_vip": true
},
{
"id": "7482733632910675262",
"title": "花字",
"is_vip": true
},
{
"id": "7236599551984028939",
"title": "蓝紫色混合花字",
"is_vip": true
},
{
"id": "7481665617796369689",
"title": "蓝色",
"is_vip": true
},
{
"id": "7477756249665342744",
"title": "彩铅渐变粉色花字",
"is_vip": true
},
{
"id": "7260020603044826427",
"title": "渐变花字",
"is_vip": true
},
{
"id": "7506874577159572755",
"title": "绿色花字发光",
"is_vip": true
},
{
"id": "7350563191123938611",
"title": "可爱彩色涂鸦花字",
"is_vip": true
},
{
"id": "7508005459065097497",
"title": "花字",
"is_vip": true
},
{
"id": "7507082793592032536",
"title": "粉色闪闪芭比花字",
"is_vip": true
},
{
"id": "7469677410414382398",
"title": "粉色渐变",
"is_vip": true
},
{
"id": "7509757725908225304",
"title": "马卡龙",
"is_vip": true
},
{
"id": "7348369625215749388",
"title": "发光字",
"is_vip": true
},
{
"id": "7403964791372533027",
"title": "粉笔字",
"is_vip": true
},
{
"id": "7508363172798270744",
"title": "蓝白",
"is_vip": true
},
{
"id": "7477149973520583961",
"title": "黄绿渐变立体字",
"is_vip": true
},
{
"id": "7495692617561181502",
"title": "花字",
"is_vip": true
},
{
"id": "7494493486155042110",
"title": "多层描边彩色多巴胺花字",
"is_vip": true
},
{
"id": "7492310644704841022",
"title": "蓝粉",
"is_vip": true
},
{
"id": "7507164704448679193",
"title": "节日绿色立体描边花字",
"is_vip": true
},
{
"id": "7347171058488823066",
"title": "蓝绿色花字",
"is_vip": true
},
{
"id": "7405934415567736074",
"title": "粉色立体拼贴花字",
"is_vip": true
},
{
"id": "7492411773329476889",
"title": "彩色描边立体可爱花字",
"is_vip": true
},
{
"id": "7492716248091004222",
"title": "绿色立体",
"is_vip": true
},
{
"id": "7471905506001669401",
"title": "花字",
"is_vip": true
},
{
"id": "7479683834464898329",
"title": "春日综艺感渐变纹理花字",
"is_vip": true
},
{
"id": "7478608447794187582",
"title": "绿紫黄紫立体字",
"is_vip": true
},
{
"id": "7480097920361073945",
"title": "膨胀感字",
"is_vip": true
},
{
"id": "7403676308145802522",
"title": "立体综艺花字",
"is_vip": false
},
{
"id": "7405202500493610275",
"title": "白色纹理描边花字",
"is_vip": false
},
{
"id": "7441152469352090889",
"title": "复古淡黄花字",
"is_vip": false
},
{
"id": "7405564299122429219",
"title": "白色发光字",
"is_vip": false
},
{
"id": "7403679510702378278",
"title": "黄色渐变立体白描边花字",
"is_vip": false
},
{
"id": "7403960732490157364",
"title": "白字红边立体字",
"is_vip": false
},
{
"id": "7405107629137186082",
"title": "蓝色立体字",
"is_vip": false
},
{
"id": "7410649194110733602",
"title": "美拉德立体文字",
"is_vip": false
},
{
"id": "7404477237837270299",
"title": "绿色立体通用花字",
"is_vip": false
},
{
"id": "7405105991651544360",
"title": "绿色镂空透明文字",
"is_vip": false
},
{
"id": "7405410790867586344",
"title": "绿色描边投影字",
"is_vip": false
},
{
"id": "7405203773066415360",
"title": "绿色透明纹理花字",
"is_vip": false
},
{
"id": "7543157780769803582",
"title": "综艺火焰",
"is_vip": true
},
{
"id": "7347967906669415716",
"title": "系统故障字",
"is_vip": true
},
{
"id": "7532041202787487038",
"title": "蓝色黄色渐变立体描边花字",
"is_vip": true
},
{
"id": "7127670164996328740",
"title": "综艺 黄色",
"is_vip": true
},
{
"id": "7260340249581128996",
"title": "黑白黄色花字",
"is_vip": true
},
{
"id": "7405896759987227931",
"title": "红色火焰燃烧花字",
"is_vip": true
},
{
"id": "7160595602236116232",
"title": "复古紫光蓝色渐变立体花字",
"is_vip": true
},
{
"id": "7494932494253608216",
"title": "综艺风蓝色描边立体花字",
"is_vip": true
},
{
"id": "7411046111760125211",
"title": "喷溅红立体",
"is_vip": true
},
{
"id": "7313160248175398154",
"title": "红黄渐变纹理立体花字",
"is_vip": true
},
{
"id": "7403899942944705819",
"title": "白字蓝框综艺花字",
"is_vip": true
},
{
"id": "7205144150390443301",
"title": "美食-金色渐变",
"is_vip": true
},
{
"id": "7406328633205312820",
"title": "红色火焰字",
"is_vip": true
},
{
"id": "7404690754590821632",
"title": "镂空发光字",
"is_vip": true
},
{
"id": "7405902936175381787",
"title": "蓝色纹理花字",
"is_vip": true
},
{
"id": "7310113812168871177",
"title": "白色质感纹理立体花字",
"is_vip": true
},
{
"id": "7430781079058976026",
"title": "黄色花字",
"is_vip": true
},
{
"id": "7448962185159609625",
"title": "综艺立体",
"is_vip": true
},
{
"id": "7494493305716378905",
"title": "五一复古立体",
"is_vip": true
},
{
"id": "7264501278175202572",
"title": "好物美妆-双层投影",
"is_vip": true
},
{
"id": "7350578203905232166",
"title": "白字绿底花字",
"is_vip": true
},
{
"id": "7406249723423640871",
"title": "渐变错位花字",
"is_vip": true
},
{
"id": "7474546033763224894",
"title": "彩色",
"is_vip": true
},
{
"id": "7406866881144966409",
"title": "像素格背景字",
"is_vip": true
},
{
"id": "7404777689518738728",
"title": "橙黄渐变花字",
"is_vip": true
},
{
"id": "7342020000812731658",
"title": "彩色手绘线条花字",
"is_vip": true
},
{
"id": "7262979013637967119",
"title": "立体麻布花纹字体",
"is_vip": true
},
{
"id": "7406013385969569062",
"title": "红色渐变波点底纹立体花字",
"is_vip": true
},
{
"id": "7478945314318241086",
"title": "综艺风蓝色渐变纹理立体花字",
"is_vip": true
},
{
"id": "7404293089377930536",
"title": "高饱和彩虹字",
"is_vip": true
},
{
"id": "7404132140365008179",
"title": "3D蓝红色立体综艺花字",
"is_vip": true
},
{
"id": "7272729157895769355",
"title": "音乐节-杂点黄字",
"is_vip": true
},
{
"id": "7343806780583038247",
"title": "拼贴位移字",
"is_vip": true
},
{
"id": "7347548073897364746",
"title": "彩色立体底框花字",
"is_vip": true
},
{
"id": "7495656020006669592",
"title": "综艺风蓝色立体描边花字",
"is_vip": true
},
{
"id": "7230694221513035020",
"title": "黑字底红光",
"is_vip": true
},
{
"id": "7405947244395924770",
"title": "海浪卡通立体字",
"is_vip": true
},
{
"id": "7261598257762045219",
"title": "浪花紫",
"is_vip": true
},
{
"id": "7405953030996184335",
"title": "裂纹立体文字",
"is_vip": true
},
{
"id": "7406307881865301258",
"title": "漫画层叠花字",
"is_vip": true
},
{
"id": "7403686755486010634",
"title": "节点营销直播主题立体字蓝色",
"is_vip": true
},
{
"id": "7251715329162841347",
"title": "黑色立体投影紫色发光镭射纹理花字 艺术字体",
"is_vip": true
},
{
"id": "7405563025169632562",
"title": "复古白蓝色立体花字",
"is_vip": true
},
{
"id": "7430816571443940659",
"title": "爆款热卖",
"is_vip": true
},
{
"id": "7403937403397885184",
"title": "蓝紫渐变多重投影字",
"is_vip": true
},
{
"id": "7404868077101255988",
"title": "综艺白色立体描边纹理花字",
"is_vip": true
},
{
"id": "7547984081930161470",
"title": "红金渐变国风立体花字",
"is_vip": true
},
{
"id": "7409964157296020751",
"title": "立体字粉色背景",
"is_vip": true
},
{
"id": "7330165240576970021",
"title": "金色渐变红底立体花字",
"is_vip": true
},
{
"id": "7431487397017226507",
"title": "热销字体",
"is_vip": true
},
{
"id": "7343541738537061651",
"title": "位移字",
"is_vip": true
},
{
"id": "7205148909730024762",
"title": "美食-立体描边",
"is_vip": true
},
{
"id": "7404037981952068879",
"title": "格子背景双色字",
"is_vip": true
},
{
"id": "7174051263578000678",
"title": "落日鸡尾酒",
"is_vip": true
},
{
"id": "7187622568717749565",
"title": "春节-半透明",
"is_vip": true
},
{
"id": "7241429233287925044",
"title": "黑色综艺花字",
"is_vip": true
},
{
"id": "7405060175322795276",
"title": "白/黄方块图案质感花字",
"is_vip": true
},
{
"id": "7284906593399950647",
"title": "时尚黑蓝粉",
"is_vip": true
},
{
"id": "7403911656587234597",
"title": "3D蓝色渐变综艺花字",
"is_vip": true
},
{
"id": "7241398402125253903",
"title": "白色蓝色描边红色荧光花字",
"is_vip": true
},
{
"id": "7371129776494365990",
"title": "白色仿3D立体花字",
"is_vip": true
},
{
"id": "7406357450166635776",
"title": "蓝色立体描边花字",
"is_vip": true
},
{
"id": "7404701167156088116",
"title": "破碎裂开文字",
"is_vip": true
},
{
"id": "7270881305070423356",
"title": "黄边黑字立体花字",
"is_vip": true
},
{
"id": "7405886722011172150",
"title": "立体星星花字",
"is_vip": true
},
{
"id": "7405917295421263158",
"title": "多色花字",
"is_vip": true
},
{
"id": "7481488244421741848",
"title": "立体方块花字",
"is_vip": true
},
{
"id": "7252151198805986572",
"title": "水墨纹花字",
"is_vip": true
},
{
"id": "7529442177953352985",
"title": "花字",
"is_vip": true
},
{
"id": "7368858909295136010",
"title": "白字蓝底花字",
"is_vip": true
},
{
"id": "7430724518248729919",
"title": "橙色纹理立体发光花字",
"is_vip": true
},
{
"id": "7407014154613116210",
"title": "红黄绿复古花字",
"is_vip": true
},
{
"id": "7404037530980453647",
"title": "橙黄色渐变立体描边花字",
"is_vip": true
},
{
"id": "7404380953893735714",
"title": "潮酷薄膜纹理字",
"is_vip": true
},
{
"id": "7265614510084443444",
"title": "粉色贝壳光泽花字",
"is_vip": true
},
{
"id": "7348679900477279507",
"title": "四色蜡笔花字",
"is_vip": true
},
{
"id": "7404828145255288075",
"title": "蓝色立体描边发光花字",
"is_vip": true
},
{
"id": "7510183639066627352",
"title": "限时抢购",
"is_vip": true
},
{
"id": "7404883759012597030",
"title": "游戏综艺风蓝色波点渐变花字",
"is_vip": true
},
{
"id": "7334687695660272947",
"title": "紫色梦幻 白字紫底红醒目花字",
"is_vip": true
},
{
"id": "7435551949266701580",
"title": "蓝色渐变综艺",
"is_vip": true
},
{
"id": "7289732660077874491",
"title": "黑色粉色阴影花字",
"is_vip": true
},
{
"id": "7259399609452088637",
"title": "黑体蓝紫边发光花字",
"is_vip": true
},
{
"id": "7405546666498985227",
"title": "粉笔涂鸦花字(教师节)",
"is_vip": true
},
{
"id": "7430667612146666764",
"title": "可爱花字",
"is_vip": true
},
{
"id": "7431814893415812362",
"title": "黑粉甜酷拼贴文字",
"is_vip": true
},
{
"id": "7506818824885390616",
"title": "彩色立体",
"is_vip": true
},
{
"id": "7328771445960592640",
"title": "浅棕色描边花字",
"is_vip": true
},
{
"id": "7543482227871599896",
"title": "蓝红蜡笔质感纹理花字",
"is_vip": true
},
{
"id": "7410369831503006988",
"title": "黄色渐变",
"is_vip": true
},
{
"id": "7404072480870026534",
"title": "综艺风方块背景立体花字",
"is_vip": true
},
{
"id": "7252116303329217824",
"title": "彩色花字",
"is_vip": true
},
{
"id": "7482027387266469145",
"title": "综艺感蓝色立体描边花字",
"is_vip": true
},
{
"id": "7406321401969364264",
"title": "彩色透明花字",
"is_vip": true
},
{
"id": "7369415539795529012",
"title": "橙色蓝色花字",
"is_vip": true
},
{
"id": "7406010573961317670",
"title": "黑字黄绿拼贴花字",
"is_vip": true
},
{
"id": "7504864758944927001",
"title": "蓝橙白立体花字",
"is_vip": true
},
{
"id": "7435272797611429172",
"title": "黄蓝撞色描边字",
"is_vip": true
},
{
"id": "7407015583444782375",
"title": "玫粉黑花字",
"is_vip": true
},
{
"id": "7405183112906378522",
"title": "芭比粉背景白字",
"is_vip": true
},
{
"id": "7407047445240139071",
"title": "万圣节多色花字",
"is_vip": true
},
{
"id": "7406318872862674185",
"title": "复古风花字",
"is_vip": true
},
{
"id": "7231502419723603239",
"title": "深红白边黄影立体花字",
"is_vip": true
},
{
"id": "7431429796434890021",
"title": "APT花字",
"is_vip": true
},
{
"id": "7270171712136776997",
"title": "粉底黄边黑色立体花字",
"is_vip": true
},
{
"id": "7405789476561095986",
"title": "未来科技感立体厚重标题花字",
"is_vip": true
},
{
"id": "7405944078992559411",
"title": "白字带描边花字",
"is_vip": true
},
{
"id": "7411583332707863835",
"title": "美妆方底",
"is_vip": true
},
{
"id": "7337839774079798566",
"title": "酒红风格 黄字酒红底色花字",
"is_vip": true
},
{
"id": "7406589254157061439",
"title": "多色花字",
"is_vip": true
},
{
"id": "7405065396648283455",
"title": "黄绿撕纸拼贴质感花字",
"is_vip": true
},
{
"id": "7405186414284999971",
"title": "橙黄色立体霓虹花字",
"is_vip": true
},
{
"id": "7544660134732057881",
"title": "黄色渐变粉色花朵底纹立体花字",
"is_vip": true
},
{
"id": "7348639844198878515",
"title": "青团底纹花字",
"is_vip": true
},
{
"id": "7382058294157774107",
"title": "黄蓝渐变立体字",
"is_vip": true
},
{
"id": "7252346023656394042",
"title": "紫色描边发光小字体",
"is_vip": true
},
{
"id": "7404290790391860530",
"title": "粉蓝色渐变黑边立体花字",
"is_vip": true
},
{
"id": "7406979682911931657",
"title": "红色渐变黄绿描边",
"is_vip": true
},
{
"id": "7411563961381817610",
"title": "美妆拼贴",
"is_vip": true
},
{
"id": "7404883418774818086",
"title": "游戏综艺风黄红紫渐变花字",
"is_vip": true
},
{
"id": "7430759634757061926",
"title": "彩色花字",
"is_vip": true
},
{
"id": "7543299507744967960",
"title": "蓝橙波点纹理玻璃质感立体花字",
"is_vip": true
},
{
"id": "7406011366865161481",
"title": "蓝色纹理立体花字",
"is_vip": true
},
{
"id": "7404009350399937792",
"title": "放射背景字",
"is_vip": true
},
{
"id": "7406011150829194546",
"title": "白字黄绿拼贴花字",
"is_vip": true
},
{
"id": "7548102481977593113",
"title": "夏日蓝描边立体",
"is_vip": true
},
{
"id": "7405537186436648201",
"title": "白色国风水墨花字",
"is_vip": true
},
{
"id": "7405530102324415807",
"title": "金箔纹理阴影花字",
"is_vip": true
},
{
"id": "7405519026367122727",
"title": "书法墨迹白色花字",
"is_vip": true
},
{
"id": "7405512855434382611",
"title": "泼墨书法纹理花字",
"is_vip": true
},
{
"id": "7475566213477977368",
"title": "红色斑驳",
"is_vip": true
},
{
"id": "7546579616576720152",
"title": "红色立体",
"is_vip": true
},
{
"id": "7405499580399357210",
"title": "金色质感立体花字",
"is_vip": true
},
{
"id": "7406643508242582825",
"title": "国风花字",
"is_vip": true
},
{
"id": "7405516433863511348",
"title": "黑白水墨字",
"is_vip": true
},
{
"id": "7435884430620691739",
"title": "复古红色立体花字",
"is_vip": true
},
{
"id": "7406646658768882983",
"title": "国风花字",
"is_vip": true
},
{
"id": "7405497799036407090",
"title": "水墨风晕染花字",
"is_vip": true
},
{
"id": "7405510219633036555",
"title": "白金花字",
"is_vip": true
},
{
"id": "7483351934074817817",
"title": "古风质感花字",
"is_vip": true
},
{
"id": "7405504415408409865",
"title": "暗黑系红色火焰纹理花字",
"is_vip": true
},
{
"id": "7405500731253411108",
"title": "红金国风花字",
"is_vip": true
},
{
"id": "7405517111231073575",
"title": "点墨金银花字",
"is_vip": true
},
{
"id": "7404078955344448777",
"title": "春节新年福字背景花字",
"is_vip": true
},
{
"id": "7405512551879970067",
"title": "银色花字",
"is_vip": true
},
{
"id": "7405501851887586611",
"title": "红色暗黑花字",
"is_vip": true
},
{
"id": "7406643758231571766",
"title": "国风花字",
"is_vip": true
},
{
"id": "7405506413524569363",
"title": "黑红渐变立体描边花字",
"is_vip": true
},
{
"id": "7405527291209469196",
"title": "书法水痕阴影花字",
"is_vip": true
},
{
"id": "7405534702221790515",
"title": "水墨背景白色花字",
"is_vip": true
},
{
"id": "7405499186109533494",
"title": "国风金红花字",
"is_vip": true
},
{
"id": "7507132514088062233",
"title": "红金国风花字",
"is_vip": true
},
{
"id": "7405498270568418611",
"title": "黑白水墨花字",
"is_vip": true
},
{
"id": "7405503477444644106",
"title": "暗黑红色立体花字",
"is_vip": true
},
{
"id": "7405513478645091636",
"title": "暗黑墨迹字",
"is_vip": true
},
{
"id": "7405879747340700937",
"title": "青绿色水墨风古典边框花字",
"is_vip": true
},
{
"id": "7405514792724745484",
"title": "水墨书法纹理花字",
"is_vip": true
},
{
"id": "7405500890620120358",
"title": "黑灰色质感立体花字",
"is_vip": true
},
{
"id": "7405494488019275059",
"title": "暗黑火焰红边花字",
"is_vip": true
},
{
"id": "7405528972135583030",
"title": "暗红色墨痕书法花字",
"is_vip": true
},
{
"id": "7405504097429867815",
"title": "银色国风花字",
"is_vip": true
},
{
"id": "7405524745959034124",
"title": "书法墨环图案花字",
"is_vip": false
},
{
"id": "7405523665145613631",
"title": "金箔描边书法水墨花字",
"is_vip": false
},
{
"id": "7127823728267791647",
"title": "综艺金色花字",
"is_vip": true
},
{
"id": "7160598356237012261",
"title": "潮酷发光立体花字",
"is_vip": true
},
{
"id": "7160595759375666446",
"title": "潮酷金色发光花字",
"is_vip": true
},
{
"id": "7269602984844102947",
"title": "光芒万丈",
"is_vip": true
},
{
"id": "7160596923781598472",
"title": "综艺立体花字",
"is_vip": true
},
{
"id": "7205150731035266341",
"title": "美食-渐变小字",
"is_vip": true
},
{
"id": "7406007163417529638",
"title": "金色渐变立体发光花字",
"is_vip": true
},
{
"id": "7127655008715296031",
"title": "粉色花字",
"is_vip": true
},
{
"id": "7403924857282432271",
"title": "粉色发光字",
"is_vip": true
},
{
"id": "7346895765458947366",
"title": "蓝色发光",
"is_vip": true
},
{
"id": "7179606734166592825",
"title": "元旦透明燥点花字-2022元旦",
"is_vip": true
},
{
"id": "7406005354070379802",
"title": "红色渐变黄色发光花字",
"is_vip": true
},
{
"id": "7408957503892884774",
"title": "蓝色霓虹灯发光花字",
"is_vip": true
},
{
"id": "7404896582182767908",
"title": "黄色发光花字",
"is_vip": true
},
{
"id": "7459717947620363582",
"title": "金色渐变立体发光花字",
"is_vip": true
},
{
"id": "7404751791503576339",
"title": "蓝色发光花字",
"is_vip": true
},
{
"id": "7174330567222185253",
"title": "圣诞红白条",
"is_vip": true
},
{
"id": "7127839722893774087",
"title": "粉色花字",
"is_vip": true
},
{
"id": "7160597532043644174",
"title": "潮酷白色发光立体花字",
"is_vip": true
},
{
"id": "7160596088011951373",
"title": "综艺立体渐变",
"is_vip": true
},
{
"id": "7273017604837625151",
"title": "黄色渐变花字",
"is_vip": true
},
{
"id": "7346916622247955763",
"title": "发光",
"is_vip": true
},
{
"id": "7179634097906519356",
"title": "闪光的新年花字-2022元旦",
"is_vip": true
},
{
"id": "7265622933702184232",
"title": "红色渐变描边花字",
"is_vip": true
},
{
"id": "7362142403416952115",
"title": "粉色发光",
"is_vip": true
},
{
"id": "7322482076958149914",
"title": "霓虹灯黄红发光花字",
"is_vip": true
},
{
"id": "7179628047832730941",
"title": "洒金粉花字-2022元旦",
"is_vip": true
},
{
"id": "7179616970399124795",
"title": "元旦透明飘雪花字-2022元旦",
"is_vip": true
},
{
"id": "7281951975275597114",
"title": "浅蓝色发光花字",
"is_vip": true
},
{
"id": "7405197593808096527",
"title": "红色内发光文字",
"is_vip": true
},
{
"id": "7240995033393007931",
"title": "克莱因蓝发光字体",
"is_vip": true
},
{
"id": "7403941808302066979",
"title": "红黄配色花字",
"is_vip": true
},
{
"id": "7128327279804976397",
"title": "红色发光花字",
"is_vip": true
},
{
"id": "7241397134128352551",
"title": "黄色橙色描边花字",
"is_vip": true
},
{
"id": "7404014524900199706",
"title": "霓虹灯发光红黄花字",
"is_vip": true
},
{
"id": "7312709252928277812",
"title": "薄荷冰花字",
"is_vip": true
},
{
"id": "7241480073759575357",
"title": "荧光绿炫酷字体",
"is_vip": true
},
{
"id": "7260439366953110825",
"title": "渐变花字",
"is_vip": true
},
{
"id": "7245610210386136357",
"title": "烟雾纹理花字",
"is_vip": true
},
{
"id": "7243255465822506255",
"title": "红配蓝发光炫酷字体",
"is_vip": true
},
{
"id": "7160595918226525453",
"title": "潮酷发光立体花字",
"is_vip": true
},
{
"id": "7406289529096719625",
"title": "电商节日直播贴片标题立体字",
"is_vip": true
},
{
"id": "7336848964819504434",
"title": "渐变 蓝紫色花字",
"is_vip": true
},
{
"id": "7241432857447583028",
"title": "蓝色渐变花字",
"is_vip": true
},
{
"id": "7241389070943866164",
"title": "黄色字荧光描边花字",
"is_vip": true
},
{
"id": "7265621281838533923",
"title": "粉色渐变描边花字",
"is_vip": true
},
{
"id": "7322679348106906918",
"title": "圆环发光花字",
"is_vip": true
},
{
"id": "7265622422022262051",
"title": "绿色渐变描边花字",
"is_vip": true
},
{
"id": "7390410514976804122",
"title": "白紫立体发光",
"is_vip": true
},
{
"id": "7266447274115419449",
"title": "甜粉",
"is_vip": true
},
{
"id": "7408956912089206067",
"title": "红色霓虹灯发光花字",
"is_vip": true
},
{
"id": "7266696486363106616",
"title": "金色花字",
"is_vip": true
},
{
"id": "7404503527617301770",
"title": "空心白色描边发光花字",
"is_vip": true
},
{
"id": "7351422706086169866",
"title": "白字蓝光花字",
"is_vip": true
},
{
"id": "7404047060221037851",
"title": "亮黄字橙色描边发光花字",
"is_vip": true
},
{
"id": "7434806614781168947",
"title": "冬季发光",
"is_vip": true
},
{
"id": "7231824394559982886",
"title": "黄的红边花字重叠",
"is_vip": true
},
{
"id": "7405056348200684827",
"title": "渐变彩虹色发光花字",
"is_vip": true
},
{
"id": "7322881735522290995",
"title": "霓虹灯发光花字",
"is_vip": true
},
{
"id": "7391283375606156585",
"title": "绿色纹理立体花字",
"is_vip": true
},
{
"id": "7322678574719339802",
"title": "红色霓虹灯发光字",
"is_vip": true
},
{
"id": "7266724384205786427",
"title": "星空",
"is_vip": true
},
{
"id": "7212896736849841467",
"title": "美食-中间渐变",
"is_vip": true
},
{
"id": "7259709733790125366",
"title": "夏日的亮丽 ",
"is_vip": true
},
{
"id": "7274035971207744824",
"title": "纯黑底色,荧光绿和黑色描边 立体 发光 花字",
"is_vip": true
},
{
"id": "7241392284686683395",
"title": "黄色蓝色发发光花字",
"is_vip": true
},
{
"id": "7241477841567649080",
"title": "梦幻蓝紫色简约渐变花字",
"is_vip": true
},
{
"id": "7241410291521670400",
"title": "红色荧光花字",
"is_vip": true
},
{
"id": "7390315130128452890",
"title": "彩色发光立体",
"is_vip": true
},
{
"id": "7404001083665812771",
"title": "黄色渐变发光字",
"is_vip": true
},
{
"id": "6926827744189779207",
"title": "发光灯箱感红色花字",
"is_vip": true
},
{
"id": "7322422789355392265",
"title": "霓虹灯发光花字",
"is_vip": true
},
{
"id": "7231468045976292645",
"title": "黑色红边柔光花字",
"is_vip": true
},
{
"id": "7404385123975613706",
"title": "粉色渐变温柔发光花字",
"is_vip": true
},
{
"id": "7241393396575735040",
"title": "渐变紫色花字",
"is_vip": true
},
{
"id": "7243262147210267944",
"title": "红配绿发光拼色字体",
"is_vip": true
},
{
"id": "7273831317136035133",
"title": "黑底荧光绿描边 发光 花字",
"is_vip": true
},
{
"id": "7322380988430994715",
"title": "霓虹灯发光花字",
"is_vip": true
},
{
"id": "7403932533995425039",
"title": "绿字蓝白描边荧光字",
"is_vip": true
},
{
"id": "7494822504427539737",
"title": "粉色渐变双层立体发光花字",
"is_vip": true
},
{
"id": "7411034104415685939",
"title": "东南亚渐变",
"is_vip": true
},
{
"id": "7241398727125011746",
"title": "蓝色渐变花字",
"is_vip": true
},
{
"id": "7404089520070593843",
"title": "黄红色霓虹灯镂空发光花字",
"is_vip": true
},
{
"id": "7403922592194710834",
"title": "粉色渐变圆圈",
"is_vip": true
},
{
"id": "7248870704752397579",
"title": "紫色发光花字",
"is_vip": true
},
{
"id": "7361004787967495462",
"title": "粉色发光",
"is_vip": true
},
{
"id": "7260373127249595687",
"title": "纯色黄色字体",
"is_vip": true
},
{
"id": "7403992509212314920",
"title": "紫色发光字",
"is_vip": true
},
{
"id": "7496497861224516926",
"title": "粉色闪粉星光闪闪发光划走",
"is_vip": true
},
{
"id": "7270129109974469945",
"title": "绿底黑边黄色立体花字",
"is_vip": true
},
{
"id": "7264481843301354813",
"title": "简约蓝",
"is_vip": true
},
{
"id": "7241230847741791521",
"title": "花粉绿",
"is_vip": true
},
{
"id": "7404070348263607603",
"title": "粉色发光立体花字",
"is_vip": true
},
{
"id": "7406241968847670569",
"title": "绿色渐变立体描边花字",
"is_vip": true
},
{
"id": "7291429737774255412",
"title": "粉色糖果风格花字",
"is_vip": true
},
{
"id": "7355608527144062217",
"title": "紫色花字",
"is_vip": true
},
{
"id": "7238624559178485031",
"title": "渐变发光花字",
"is_vip": true
},
{
"id": "7405916937353465128",
"title": "荧光绿线条发光字",
"is_vip": true
},
{
"id": "7270718850256211259",
"title": "渐变花字",
"is_vip": true
},
{
"id": "7274771737999379749",
"title": "粉色发光花字",
"is_vip": true
},
{
"id": "7404388775264030003",
"title": "粉色闪粉白色描边发光花字",
"is_vip": true
},
{
"id": "7405417769446968610",
"title": "紫红发光字",
"is_vip": true
},
{
"id": "7248130865094561036",
"title": "彩色渐变花字",
"is_vip": true
},
{
"id": "7241415162345852194",
"title": "绿色立体花字",
"is_vip": true
},
{
"id": "7275250557386788156",
"title": "条纹黄色综艺发光花字",
"is_vip": true
},
{
"id": "7404321217110396187",
"title": "梦幻紫星光双层立体花字",
"is_vip": true
},
{
"id": "7529808923725925657",
"title": "粉色闪闪",
"is_vip": true
},
{
"id": "7405939554047233295",
"title": "荧光线条发光字",
"is_vip": true
},
{
"id": "7327845943305358646",
"title": "机械装甲绿色科技感文字标题",
"is_vip": true
},
{
"id": "7404100687820229922",
"title": "发光灯箱感绿色描边立体花字",
"is_vip": true
},
{
"id": "7259233733964811572",
"title": "白花纹发光花字",
"is_vip": true
},
{
"id": "7334225752663149850",
"title": "清新绿色 绿色花字",
"is_vip": true
},
{
"id": "7334229773402606886",
"title": "浅绿色 绿色花字底发光",
"is_vip": true
},
{
"id": "7249749880611015988",
"title": "夏日青春派对",
"is_vip": true
},
{
"id": "7406201706456960256",
"title": "紫色发光字",
"is_vip": true
},
{
"id": "7404708538926353700",
"title": "白色描边芭比粉发光花字",
"is_vip": true
},
{
"id": "7232089500518862140",
"title": "花字-雪花彩粉渐变立体字",
"is_vip": true
},
{
"id": "7405875861712342307",
"title": "赛博朋克纹理发光字",
"is_vip": true
},
{
"id": "7281283804235402533",
"title": "浅梦幻少女色",
"is_vip": true
},
{
"id": "7404330497574309129",
"title": "彩色镭射渐变花字",
"is_vip": true
},
{
"id": "7245923862574009635",
"title": "紫色发光立体花字",
"is_vip": true
},
{
"id": "7404021791427005723",
"title": "薄荷绿花字",
"is_vip": true
},
{
"id": "7241393660334574848",
"title": "青色 红色 荧光花字",
"is_vip": true
},
{
"id": "7351303614104636699",
"title": "绿色花字",
"is_vip": true
},
{
"id": "7241904291722693944",
"title": "紫宝石",
"is_vip": true
},
{
"id": "7241388504381541666",
"title": "粉橙色花字",
"is_vip": true
},
{
"id": "7260122300564000012",
"title": "格子纹理花字",
"is_vip": true
},
{
"id": "7297906734755073319",
"title": "复古格子清新蓝花字",
"is_vip": true
},
{
"id": "7231501962041117955",
"title": "深绿色黑边紫光花字",
"is_vip": true
},
{
"id": "7291157036098735401",
"title": "紫色粉边花字",
"is_vip": true
},
{
"id": "6896138122774514951",
"title": "清新蓝色发光花字",
"is_vip": false
},
{
"id": "7127615338035924238",
"title": "潮酷 白色橙边",
"is_vip": false
},
{
"id": "7166445713029729568",
"title": "简约白色发光立体花字",
"is_vip": false
},
{
"id": "6896141886055107854",
"title": "超酷发光镂空花字、潮人必备",
"is_vip": false
},
{
"id": "6896141886055091470",
"title": "潮酷蓝色发光镂空花字",
"is_vip": false
},
{
"id": "7127654126997048607",
"title": "综艺 橙色",
"is_vip": false
},
{
"id": "6896138122774531335",
"title": "清新粉色发光灯箱感花字",
"is_vip": false
},
{
"id": "6896141886055058702",
"title": "炫彩发光跳色花字,",
"is_vip": false
},
{
"id": "7127817897061125413",
"title": "潮酷 橙色",
"is_vip": false
},
{
"id": "6926796566346960141",
"title": "潮酷黄色霓虹灯花字",
"is_vip": false
},
{
"id": "6926825801258126599",
"title": "红色镂空发光花字",
"is_vip": false
},
{
"id": "6926827744189795591",
"title": "潮酷蓝色霓虹灯发光花字",
"is_vip": false
},
{
"id": "7187616139642522936",
"title": "潮酷黄底白色发光立体花字",
"is_vip": false
},
{
"id": "6927159112887176459",
"title": "蓝色镂空发光花字",
"is_vip": false
},
{
"id": "7127819154018602277",
"title": "潮酷 白色粉边",
"is_vip": false
},
{
"id": "6926825801258159367",
"title": "暗黑潮酷黑色花字",
"is_vip": false
},
{
"id": "6896143968241798408",
"title": "超酷黄色发光花字",
"is_vip": false
},
{
"id": "7127680616283295006",
"title": "小清新 白色",
"is_vip": false
},
{
"id": "7405565480678739200",
"title": "黄色发光字",
"is_vip": false
},
{
"id": "6896141886055075086",
"title": "炫彩发光花字,跳字变色",
"is_vip": false
},
{
"id": "6896144021568179469",
"title": "发光灯箱感绿色花字",
"is_vip": false
},
{
"id": "6926825801384021256",
"title": "潮酷黄色发光花字",
"is_vip": false
},
{
"id": "7127827287826779428",
"title": "复古 红色",
"is_vip": false
},
{
"id": "7404088879780826406",
"title": "赛博朋克未来科技感立体发光花字",
"is_vip": false
},
{
"id": "6927160254996253967",
"title": "红色潮酷外发光花字",
"is_vip": false
},
{
"id": "6927160144421866752",
"title": "红色朦胧港风复古花字",
"is_vip": false
},
{
"id": "7127675252410289445",
"title": "Y2k粉色立体灯箱发光花字",
"is_vip": false
},
{
"id": "6896143968241782024",
"title": "潮酷粉色发光镂空花字",
"is_vip": false
},
{
"id": "7197333872466611513",
"title": "梦幻粉色发光立体花字",
"is_vip": false
},
{
"id": "7127669605199351048",
"title": "潮酷发光青色",
"is_vip": false
},
{
"id": "7403926640260123944",
"title": "黄橙渐变黑红描边立体字",
"is_vip": true
},
{
"id": "7430703360409554212",
"title": "蓝色纹理立体发光花字",
"is_vip": true
},
{
"id": "7407014765907774747",
"title": "黄色渐变红边发光花字",
"is_vip": true
},
{
"id": "7160596855456320776",
"title": "潮酷发光立体花字",
"is_vip": true
},
{
"id": "7317088712154696969",
"title": "立体金属字",
"is_vip": true
},
{
"id": "7244940532298829090",
"title": "黑金色立体花字",
"is_vip": true
},
{
"id": "7281947750139219257",
"title": "黑灰色花字【严肃】",
"is_vip": true
},
{
"id": "7212896770370587941",
"title": "美食-黄网格",
"is_vip": true
},
{
"id": "7388020661312146751",
"title": "金属灰渐变立体白边花字",
"is_vip": true
},
{
"id": "7260358084772547903",
"title": "一窝时光标题花字字体设计美食海报大气简约醒目小龙虾",
"is_vip": true
},
{
"id": "7405125461438762267",
"title": "蓝色渐变3D立体花字",
"is_vip": true
},
{
"id": "7274581371975142710",
"title": "立体效果",
"is_vip": true
},
{
"id": "7212897121249283383",
"title": "美食-金色网格",
"is_vip": true
},
{
"id": "7160599091750145287",
"title": "土酷蓝色渐变立体花字",
"is_vip": true
},
{
"id": "7220003213171281192",
"title": "蓝色渐变花字",
"is_vip": true
},
{
"id": "7265625223381273891",
"title": "黄色渐变花字",
"is_vip": true
},
{
"id": "7493083674158796094",
"title": "黄色渐变花字",
"is_vip": true
},
{
"id": "7369091570345282866",
"title": "黄白涂鸦花字",
"is_vip": true
},
{
"id": "7224762483448237345",
"title": "黑灰渐变",
"is_vip": true
},
{
"id": "7369985913310448911",
"title": "彩色渐变描边",
"is_vip": true
},
{
"id": "7439987370033728807",
"title": "黄色渐变花字",
"is_vip": true
},
{
"id": "7405889740081237285",
"title": "橘黄色渐变波点底纹立体花字",
"is_vip": true
},
{
"id": "7431533312738348314",
"title": "大雪渐变",
"is_vip": true
},
{
"id": "7268912246900772135",
"title": "黑白配",
"is_vip": true
},
{
"id": "7252679635027168567",
"title": "美食-黄白跳色",
"is_vip": true
},
{
"id": "7511237110914125080",
"title": "蓝色渐变立体描边花字",
"is_vip": true
},
{
"id": "7212885712495070519",
"title": "美食-弹幕",
"is_vip": true
},
{
"id": "7264536942832848165",
"title": "蓝色花字",
"is_vip": true
},
{
"id": "7265622781008629032",
"title": "橘色渐变描边花字",
"is_vip": true
},
{
"id": "7405056217225104681",
"title": "黄橙色渐变描边立体花字",
"is_vip": true
},
{
"id": "7328610126296796468",
"title": "金色渐变 金灿灿花字 富贵",
"is_vip": true
},
{
"id": "7491562659268119870",
"title": "花字",
"is_vip": true
},
{
"id": "7205151372805754167",
"title": "暗黑红黑渐立体花字",
"is_vip": true
},
{
"id": "7404684532756073791",
"title": "粉色渐变红色底花字",
"is_vip": true
},
{
"id": "7313119295792352539",
"title": "黄色渐变立体花字",
"is_vip": true
},
{
"id": "7160601969629891847",
"title": "综艺立体花字",
"is_vip": true
},
{
"id": "7233363221497842977",
"title": "扁平化请新白蓝",
"is_vip": true
},
{
"id": "7187770975822433594",
"title": "春节-兔彩头-银色立体",
"is_vip": true
},
{
"id": "7404899700970753321",
"title": "蓝色渐变花字",
"is_vip": true
},
{
"id": "7530918113899105561",
"title": "花字",
"is_vip": true
},
{
"id": "7265298421341277452",
"title": "七夕-粉白渐变",
"is_vip": true
},
{
"id": "7324218891222240522",
"title": "金色红底春节喜庆花字",
"is_vip": true
},
{
"id": "7431462520835099955",
"title": "花字",
"is_vip": true
},
{
"id": "7324255228310654235",
"title": "金色渐变红底立体花字",
"is_vip": true
},
{
"id": "7431549062475762959",
"title": "黄红渐变黑边立体花字",
"is_vip": true
},
{
"id": "7205154202757172541",
"title": "美食-红黄渐变",
"is_vip": true
},
{
"id": "7212896808798801213",
"title": "美食-划痕渐变",
"is_vip": true
},
{
"id": "7330967545240964404",
"title": "蓝色渐变白色描边花字",
"is_vip": true
},
{
"id": "7384325883584056617",
"title": "渐变蓝色花字",
"is_vip": true
},
{
"id": "7391023993802804521",
"title": "红色描边双色渐变立体花字",
"is_vip": true
},
{
"id": "7404880919582018854",
"title": "橙色渐变波点双层立体花字",
"is_vip": true
},
{
"id": "7312840128949505307",
"title": "浅蓝粉渐变立体花字",
"is_vip": true
},
{
"id": "7399918916232826123",
"title": "紫色立体花字",
"is_vip": true
},
{
"id": "7248118492111703357",
"title": "简约蓝色渐变立体花字",
"is_vip": true
},
{
"id": "7405583007098195237",
"title": "黄蓝撞色渐变立体花字",
"is_vip": true
},
{
"id": "7369988046277594383",
"title": "彩色渐变",
"is_vip": true
},
{
"id": "7410717398510128424",
"title": "黄橘渐变",
"is_vip": true
},
{
"id": "7405253473299696931",
"title": "红色渐变透明花字",
"is_vip": true
},
{
"id": "7298358091664362793",
"title": "雪花字",
"is_vip": true
},
{
"id": "7205147811573271864",
"title": "美食-辣",
"is_vip": true
},
{
"id": "7493079330654899480",
"title": "黄白色渐变立体花字",
"is_vip": true
},
{
"id": "7369460089767480614",
"title": "彩色",
"is_vip": true
},
{
"id": "7406294702212877619",
"title": "白字霓虹灯渐变花字",
"is_vip": true
},
{
"id": "7263267444020596005",
"title": "冬日寒冷发光花字",
"is_vip": true
},
{
"id": "7405953290271198491",
"title": "彩色渐变花字",
"is_vip": true
},
{
"id": "7406253347746876706",
"title": "黄绿渐变发光字",
"is_vip": true
},
{
"id": "7383803879730842931",
"title": "黄色渐变描边立体花字",
"is_vip": true
},
{
"id": "7236638821901733175",
"title": "简约渐变花字",
"is_vip": true
},
{
"id": "7505100141288901950",
"title": "黄色渐变橙蓝色描边立体花字",
"is_vip": true
},
{
"id": "7127664822887402759",
"title": "白绿紫渐变",
"is_vip": true
},
{
"id": "7391445684953681192",
"title": "蓝绿渐变花字",
"is_vip": true
},
{
"id": "7376115629230673204",
"title": "紫色立体渐变",
"is_vip": true
},
{
"id": "7430709931411623204",
"title": "蓝色纹理发光立体花字",
"is_vip": true
},
{
"id": "7265636111211449634",
"title": "黄色渐变双色描边花字",
"is_vip": true
},
{
"id": "7285696655989411133",
"title": "蓝色渐变花字",
"is_vip": true
},
{
"id": "7404026606869613864",
"title": "黄绿花纹立体字",
"is_vip": true
},
{
"id": "7404369195875487016",
"title": "星空梦幻炫彩立体花字",
"is_vip": true
},
{
"id": "7527575726220987672",
"title": "紫色 立体 渐变 花字",
"is_vip": true
},
{
"id": "7241433848943365436",
"title": "花字",
"is_vip": true
},
{
"id": "7404026005389708595",
"title": "蓝字彩虹渐变描边花字",
"is_vip": true
},
{
"id": "7406640534036532490",
"title": "国风粉色渐变",
"is_vip": true
},
{
"id": "7405867875317173516",
"title": "多色渐变花字",
"is_vip": true
},
{
"id": "7371124565839301925",
"title": "蓝色渐变立体花字",
"is_vip": true
},
{
"id": "7405949704904658203",
"title": "渐变白色描边花字",
"is_vip": true
},
{
"id": "7366899343451852058",
"title": "黄色手绘蜡笔质感花字",
"is_vip": true
},
{
"id": "7404710833344892196",
"title": "3D渐变绿色立体花字",
"is_vip": true
},
{
"id": "7497111940762995993",
"title": "简约双层描边蓝色渐变花字",
"is_vip": true
},
{
"id": "7430992115376704819",
"title": "五色花字",
"is_vip": true
},
{
"id": "6896143862222327047",
"title": "炫彩星空花字",
"is_vip": true
},
{
"id": "7482318463755734334",
"title": "美妆立体",
"is_vip": true
},
{
"id": "7481306716752219417",
"title": "忧郁蓝",
"is_vip": true
},
{
"id": "7407010177842482459",
"title": "黑底纹粉渐变描边发光花字",
"is_vip": true
},
{
"id": "7406359623545933093",
"title": "粉色渐变镂空描边",
"is_vip": true
},
{
"id": "7391015553818692927",
"title": "金色渐变描边花字",
"is_vip": true
},
{
"id": "7404038278057332005",
"title": "白字花字",
"is_vip": true
},
{
"id": "7249649958297783589",
"title": "暗色花字",
"is_vip": true
},
{
"id": "7296106361153293618",
"title": "双十一-彩色立体字",
"is_vip": true
},
{
"id": "7241433473796394255",
"title": "天蓝色渐变花字",
"is_vip": true
},
{
"id": "7406232498734157090",
"title": "红色渐变立体文字",
"is_vip": true
},
{
"id": "7404129182244031782",
"title": "粉色梦幻立体",
"is_vip": true
},
{
"id": "7405578926489160998",
"title": "粉色渐变发光花字",
"is_vip": true
},
{
"id": "7369459252290718986",
"title": "彩色",
"is_vip": true
},
{
"id": "7495776303799618878",
"title": "黄色渐变粉色阴影立体花字",
"is_vip": true
},
{
"id": "7388019320686693686",
"title": "低饱和蓝色渐变立体白边花字",
"is_vip": true
},
{
"id": "7315437477425155368",
"title": "绿色渐变蓝紫色描边花字",
"is_vip": true
},
{
"id": "7475023258228788505",
"title": "粉色渐变",
"is_vip": true
},
{
"id": "7405837403782384906",
"title": "红色燃烧花字",
"is_vip": true
},
{
"id": "7460547039252909337",
"title": "春节喜庆金字红边立体花字",
"is_vip": true
},
{
"id": "7405244303586397476",
"title": "斜线纹理黑白漫画感花字",
"is_vip": true
},
{
"id": "7509039282737302808",
"title": "白纸纹理蓝边拼贴花字",
"is_vip": true
},
{
"id": "7545325777781280024",
"title": "花字",
"is_vip": true
},
{
"id": "7538694611150130457",
"title": "粉笔质感纸张花字",
"is_vip": true
},
{
"id": "7405846768010661157",
"title": "黄色立体纹理花字",
"is_vip": true
},
{
"id": "7488161196357487934",
"title": "像素化花字",
"is_vip": true
},
{
"id": "7406014922078965001",
"title": "白色纸质纹理立体",
"is_vip": true
},
{
"id": "7492626374239243545",
"title": "黄红立体字",
"is_vip": true
},
{
"id": "7482734426015730968",
"title": "像素化花字",
"is_vip": true
},
{
"id": "7480452404811615512",
"title": "花字",
"is_vip": true
},
{
"id": "7405140394662530354",
"title": "金属质感硬朗立体花字",
"is_vip": true
},
{
"id": "7407272554445999411",
"title": "冰雪大世界立体雪花字",
"is_vip": true
},
{
"id": "7449585330547625228",
"title": "不织布新年红",
"is_vip": true
},
{
"id": "7404377624690101544",
"title": "复古纸张纹理字",
"is_vip": true
},
{
"id": "7541849024001740056",
"title": "花字",
"is_vip": true
},
{
"id": "7482761022504275262",
"title": "像素化游戏花字",
"is_vip": true
},
{
"id": "7405126783332404517",
"title": "未来科技感赛博斜体字",
"is_vip": true
},
{
"id": "7406192655488519433",
"title": "复古格纹立体花字",
"is_vip": true
},
{
"id": "7405853759911333172",
"title": "清爽冰块纹理字",
"is_vip": true
},
{
"id": "7435107467366878503",
"title": "绿叶绿色纹理花字",
"is_vip": true
},
{
"id": "7451442109753675070",
"title": "港风图案纹理花字",
"is_vip": true
},
{
"id": "7405824092479196431",
"title": "冰块立体字",
"is_vip": true
},
{
"id": "7405857800208928037",
"title": "蓝色星空花字",
"is_vip": true
},
{
"id": "7405855842072808755",
"title": "红色纹理立体花字",
"is_vip": true
},
{
"id": "7483893116274117950",
"title": "复古红轴",
"is_vip": true
},
{
"id": "7481535145284160792",
"title": "红黄质感立体花字",
"is_vip": true
},
{
"id": "7405843250960993586",
"title": "蓝紫色发光纹理花字",
"is_vip": true
},
{
"id": "7532883438072778008",
"title": "牛奶花字",
"is_vip": true
},
{
"id": "7405870250916384015",
"title": "木纹雕刻立体字",
"is_vip": true
},
{
"id": "7486311409861528894",
"title": "像素化花字",
"is_vip": true
},
{
"id": "7405550386234281235",
"title": "粉笔黑板花字(教师节)",
"is_vip": true
},
{
"id": "7330983004631878964",
"title": "梦幻爱心纹理底花字",
"is_vip": true
},
{
"id": "7405693659536051492",
"title": "流光立体花字",
"is_vip": true
},
{
"id": "7371332005948083494",
"title": "蓝色渐变DIY纹理立体花字",
"is_vip": true
},
{
"id": "7407265065272937778",
"title": "冬日冰花",
"is_vip": true
},
{
"id": "7406984542742924582",
"title": "红色黑条纹字",
"is_vip": true
},
{
"id": "7406190866626366770",
"title": "蓝色天空纹理立体花字",
"is_vip": true
},
{
"id": "7404383053906267392",
"title": "荧光紫渐变字",
"is_vip": true
},
{
"id": "7405523650423639308",
"title": "红色洒墨花字(书法古风)",
"is_vip": true
},
{
"id": "7405919974411242791",
"title": "蓝色渐变立体描边花字",
"is_vip": true
},
{
"id": "7306473747953863975",
"title": "圣诞-四色纹理",
"is_vip": true
},
{
"id": "7506817303296675123",
"title": "渐变纹理花字",
"is_vip": true
},
{
"id": "7486231125992623385",
"title": "游戏像素化花字",
"is_vip": true
},
{
"id": "7471979945447836952",
"title": "花石榴",
"is_vip": true
},
{
"id": "7405866412570348836",
"title": "紫色纹理描边立体花字",
"is_vip": true
},
{
"id": "7404145370399329587",
"title": "蓝色毛毡绒毛立体花字",
"is_vip": true
},
{
"id": "7430717597039054143",
"title": "紫色纹理立体发光花字",
"is_vip": true
},
{
"id": "7405201103903624463",
"title": "粉笔蓝白色立体花字",
"is_vip": true
},
{
"id": "7546407203654159678",
"title": "绿粉圈圈纹理综艺花字",
"is_vip": true
},
{
"id": "7405573811107663155",
"title": "红色棋盘格纹理立体花字",
"is_vip": true
},
{
"id": "7477911542575516952",
"title": "方块游戏花字",
"is_vip": true
},
{
"id": "7406205168200568115",
"title": "彩色纹理花字",
"is_vip": true
},
{
"id": "7405201692775451904",
"title": "绿色粉笔描边花字",
"is_vip": true
},
{
"id": "7406173713428745509",
"title": "3D蓝粉色渐变立体花字",
"is_vip": true
},
{
"id": "7405864219809287433",
"title": "红砖纹理立体花字",
"is_vip": true
},
{
"id": "7405917544126647602",
"title": "蓝黄拼色立体花字",
"is_vip": true
},
{
"id": "7481938079507418430",
"title": "红色花字",
"is_vip": true
},
{
"id": "7405856104946748723",
"title": "光影立体花字",
"is_vip": true
},
{
"id": "7404891005968747802",
"title": "镭射荧光酸性纹理花字",
"is_vip": true
},
{
"id": "7405104737386892584",
"title": "潮酷镭射立体文字",
"is_vip": true
},
{
"id": "7480467236327820606",
"title": "绿色立体花字",
"is_vip": true
},
{
"id": "7482727212375035160",
"title": "花字",
"is_vip": true
},
{
"id": "7405130183306415397",
"title": "芭比闪粉星光花字",
"is_vip": true
},
{
"id": "7405647754199895305",
"title": "黄绿格纹立体花字",
"is_vip": true
},
{
"id": "7442563568295218441",
"title": "青草绿纹理花字",
"is_vip": true
},
{
"id": "7405919944526892315",
"title": "粉蓝格纹立体花字",
"is_vip": true
},
{
"id": "7405860859177717032",
"title": "双色纹理立体字",
"is_vip": true
},
{
"id": "7405844279479913766",
"title": "绿色波点纹理花字",
"is_vip": true
},
{
"id": "7405245402917735691",
"title": "粉色纹理多层阴影花字",
"is_vip": true
},
{
"id": "7542359139469626649",
"title": "粉橙色条纹纹理立体发光花字",
"is_vip": true
},
{
"id": "7405645973613022515",
"title": "粉黄纹理立体花字",
"is_vip": true
},
{
"id": "7406387389809069321",
"title": "粉色格纹立体字",
"is_vip": true
},
{
"id": "7404875825729850659",
"title": "黄色纹理描边发光花字",
"is_vip": false
},
{
"id": "7410762405778705715",
"title": "毛笔质感",
"is_vip": false
},
{
"id": "7321972094949018921",
"title": "春节-立体红白",
"is_vip": true
},
{
"id": "7457575657376238910",
"title": "春节火焰",
"is_vip": true
},
{
"id": "7404876992962759999",
"title": "红色渐变花字",
"is_vip": true
},
{
"id": "7404314496833015077",
"title": "红色渐变裂痕综艺花字",
"is_vip": true
},
{
"id": "7401445200071003404",
"title": "红色描边花字",
"is_vip": true
},
{
"id": "7405812611427749158",
"title": "白色纹理红色字",
"is_vip": true
},
{
"id": "7403692022239956274",
"title": "白字红蓝描边",
"is_vip": true
},
{
"id": "7270171000652696893",
"title": "红色黑边立体花字",
"is_vip": true
},
{
"id": "7328997429544488244",
"title": "重阴影红白渐变黑描边花字",
"is_vip": true
},
{
"id": "7294156228794535207",
"title": "万圣-血滴字",
"is_vip": true
},
{
"id": "7462945508533931288",
"title": "开工立体",
"is_vip": true
},
{
"id": "7404769759432084748",
"title": "红色白色描边花字",
"is_vip": true
},
{
"id": "7403672172897553715",
"title": "红纹理立体白描边花字",
"is_vip": true
},
{
"id": "7329003799433973027",
"title": "多层红色渐变描边黑色花字",
"is_vip": true
},
{
"id": "7294182924587502889",
"title": "万圣-红木板字",
"is_vip": true
},
{
"id": "7489037914584681790",
"title": "像素化花字",
"is_vip": true
},
{
"id": "7294992987908541715",
"title": "双11-红白",
"is_vip": true
},
{
"id": "7399184087103196428",
"title": "大红色描边花字",
"is_vip": true
},
{
"id": "7406678794901130534",
"title": "白字带红划白黑描边",
"is_vip": true
},
{
"id": "7407014800204549413",
"title": "金箔字喜庆圆底花字",
"is_vip": true
},
{
"id": "7127646385628908807",
"title": "暗红花字",
"is_vip": true
},
{
"id": "7166470216396885280",
"title": "友友红色渐变图案立体花字",
"is_vip": true
},
{
"id": "7252964174744096003",
"title": "红黑渐变花字",
"is_vip": true
},
{
"id": "7127624093628697864",
"title": "综艺 红色渐变",
"is_vip": true
},
{
"id": "7404416840476265780",
"title": "红色复古文字",
"is_vip": true
},
{
"id": "7348241821694233867",
"title": "镂空印章花字",
"is_vip": true
},
{
"id": "7404888947479825715",
"title": "红底雪花纹理花字",
"is_vip": true
},
{
"id": "7447922811793853732",
"title": "25元旦-福圈背景花字",
"is_vip": true
},
{
"id": "7245603807105699106",
"title": "红色光斑纹理立体深红影花字",
"is_vip": true
},
{
"id": "7388867127597403428",
"title": "怀旧红",
"is_vip": true
},
{
"id": "7233578306912767271",
"title": "立体效果花字",
"is_vip": true
},
{
"id": "7460441811627035929",
"title": "复古红蓝",
"is_vip": true
},
{
"id": "7296357051788168467",
"title": "双十一-霓虹立体",
"is_vip": true
},
{
"id": "7405143396869770534",
"title": "暗黑橙色渐变描边花字",
"is_vip": true
},
{
"id": "7462291141325688088",
"title": "黄红新年花字",
"is_vip": true
},
{
"id": "7404082176163106099",
"title": "春节喜庆金粉红边黑色花字",
"is_vip": true
},
{
"id": "7457924478878928152",
"title": "红色立体",
"is_vip": true
},
{
"id": "7400944971932536099",
"title": "红色渐变花字",
"is_vip": true
},
{
"id": "7309137807929281831",
"title": "元旦-红白",
"is_vip": true
},
{
"id": "7404681840377875766",
"title": "金色描边红色纹理花字",
"is_vip": true
},
{
"id": "7400213633055198503",
"title": "红色描边花字",
"is_vip": true
},
{
"id": "7404068280916397362",
"title": "综艺红蓝撞色立体花字",
"is_vip": true
},
{
"id": "7404893190593072393",
"title": "红色细闪黑色投影花字",
"is_vip": true
},
{
"id": "7127822719047011621",
"title": "白红渐变花字",
"is_vip": true
},
{
"id": "7322728803560754482",
"title": "年味-红字金边",
"is_vip": true
},
{
"id": "7404036215848144179",
"title": "红色渐变黑边立体花字",
"is_vip": true
},
{
"id": "7334612804831431987",
"title": "橙色热情简洁 橙色立体花字",
"is_vip": true
},
{
"id": "7494900604641365310",
"title": "星星立体花字",
"is_vip": true
},
{
"id": "7266696776747486523",
"title": "老电影",
"is_vip": true
},
{
"id": "7160597344935890206",
"title": "复古红色渐变立体花字",
"is_vip": true
},
{
"id": "7405737574372756772",
"title": "红白立体花字",
"is_vip": true
},
{
"id": "7310234093625691404",
"title": "毛衣花字",
"is_vip": true
},
{
"id": "7187739440347958589",
"title": "春节-奇怪兔-红底白花字",
"is_vip": true
},
{
"id": "7404028453063888155",
"title": "黑红渐变",
"is_vip": true
},
{
"id": "7296352415060626699",
"title": "双十一-霓虹立体黄",
"is_vip": true
},
{
"id": "7335713356629822730",
"title": "红色蓝白边花字",
"is_vip": true
},
{
"id": "7404769483220405531",
"title": "红色渐变裂痕花字",
"is_vip": true
},
{
"id": "7300919700102401316",
"title": "社媒-网格红白子",
"is_vip": true
},
{
"id": "7390391149338348800",
"title": "红色 花字",
"is_vip": true
},
{
"id": "7406174570966781221",
"title": "3D红色渐变星光立体花字",
"is_vip": true
},
{
"id": "7371379435443948809",
"title": "红色渐变立体花字",
"is_vip": true
},
{
"id": "7319136118539078922",
"title": "港风复古蓝字红底花字",
"is_vip": true
},
{
"id": "7313169456081947931",
"title": "红黄渐变纹理立体花字",
"is_vip": true
},
{
"id": "7181327362708098359",
"title": "简约黄底橙色渐变花字",
"is_vip": true
},
{
"id": "7404035148204739867",
"title": "红色渐变立体波点底纹花字",
"is_vip": true
},
{
"id": "7430675317255179574",
"title": "红色立体发光花字",
"is_vip": true
},
{
"id": "7403928233030241587",
"title": "春节对联质感花字",
"is_vip": true
},
{
"id": "7349746427217710377",
"title": "射线红色花字",
"is_vip": true
},
{
"id": "7365464569642323252",
"title": "儿童节花字",
"is_vip": true
},
{
"id": "7493087421102411033",
"title": "红色立体花字",
"is_vip": true
},
{
"id": "7404782201583324466",
"title": "红色内投影白边立体花字",
"is_vip": true
},
{
"id": "7273017574063901991",
"title": "红色渐变花字",
"is_vip": true
},
{
"id": "7399922623116840231",
"title": "粉色描边花字",
"is_vip": true
},
{
"id": "7405025997860490506",
"title": "红字双层描边纸张纹理花字",
"is_vip": true
},
{
"id": "7312747055447854390",
"title": "元旦-红黄质感",
"is_vip": true
},
{
"id": "7319408651859397926",
"title": "港风复古红底花字",
"is_vip": true
},
{
"id": "7127669886762945805",
"title": "红黄立体花字",
"is_vip": true
},
{
"id": "7410765061796416768",
"title": "红黄立体字",
"is_vip": true
},
{
"id": "7404521144532929819",
"title": "白字红边渐变立体加厚花字",
"is_vip": true
},
{
"id": "7430448068283206950",
"title": "红色填充白色描边",
"is_vip": true
},
{
"id": "7459730150943395134",
"title": "粉金新年花字",
"is_vip": true
},
{
"id": "7305806489069833491",
"title": "圣诞-纹理红",
"is_vip": true
},
{
"id": "7187743354308873529",
"title": "春节-奇怪兔-白底红花字",
"is_vip": true
},
{
"id": "7371354957989055782",
"title": "米色橘色描边立体花字",
"is_vip": true
},
{
"id": "7404112581427858703",
"title": "红色复古立体描边花字",
"is_vip": true
},
{
"id": "7404796157727083814",
"title": "元旦红色立体花字",
"is_vip": true
},
{
"id": "7405243169991855423",
"title": "橙色描边立体综艺花字",
"is_vip": true
},
{
"id": "7402051434893593919",
"title": "红色描边花字",
"is_vip": true
},
{
"id": "7405204082987683123",
"title": "红底雪花纹理黑边立体字",
"is_vip": true
},
{
"id": "7405947349379452211",
"title": "渐变黑荧光绿花字",
"is_vip": true
},
{
"id": "7321977363233803574",
"title": "春节-立体红",
"is_vip": true
},
{
"id": "7320257181046082870",
"title": "春节-花窗底花字",
"is_vip": true
},
{
"id": "7329740101192387878",
"title": "招财猫花字",
"is_vip": true
},
{
"id": "7273028546514193675",
"title": "23带货-红白花字",
"is_vip": true
},
{
"id": "7312419048623541545",
"title": "圣诞-雪花红色字",
"is_vip": true
},
{
"id": "7406644388358540544",
"title": "复古红绿撞色立体字",
"is_vip": true
},
{
"id": "7332292224668994867",
"title": "122",
"is_vip": true
},
{
"id": "7187615351868280121",
"title": "春节-隐藏",
"is_vip": true
},
{
"id": "7406863699895389449",
"title": "红色绿色发光字",
"is_vip": true
},
{
"id": "7245154816765234488",
"title": "渐变黄色阴影花字",
"is_vip": true
},
{
"id": "7397798364848393481",
"title": "东北大花修改版",
"is_vip": true
},
{
"id": "7483443907032911166",
"title": "红色渐变花字",
"is_vip": true
},
{
"id": "7402043271733628172",
"title": "粉色立体花字",
"is_vip": true
},
{
"id": "7460455706701892889",
"title": "简约描边红色纹理花字",
"is_vip": true
},
{
"id": "7328403746214464819",
"title": "红色渐变立体发光花字",
"is_vip": true
},
{
"id": "7407340226189757733",
"title": "互动立体",
"is_vip": true
},
{
"id": "7328988831762484480",
"title": "重阴影金色金属渐变纹理伪三维花字",
"is_vip": true
},
{
"id": "7277814401518800147",
"title": "黄面红底黑边双重花字",
"is_vip": true
},
{
"id": "7160596855686991140",
"title": "潮酷发光立体花字",
"is_vip": true
},
{
"id": "7328988266768764194",
"title": "阴影金色金属纹理立体伪三维花字",
"is_vip": true
},
{
"id": "7402109946025790747",
"title": "火焰燃烧花字",
"is_vip": true
},
{
"id": "7160601605233052959",
"title": "复古橙色渐变立体花字",
"is_vip": true
},
{
"id": "7260019709662219576",
"title": "黄色立体花字",
"is_vip": true
},
{
"id": "7166483277631540492",
"title": "复古橙色渐变立体花字",
"is_vip": true
},
{
"id": "7465587976928660760",
"title": "金色纹理花字",
"is_vip": true
},
{
"id": "7160603032248405285",
"title": "复古橙色渐变发光立体花字",
"is_vip": true
},
{
"id": "7398576754434067723",
"title": "黄色黑底古典中国风风格花字",
"is_vip": true
},
{
"id": "7343599630678019362",
"title": "黄色底字",
"is_vip": true
},
{
"id": "7445226210377927977",
"title": "面包黄渐变花字",
"is_vip": true
},
{
"id": "7460434187036691737",
"title": "渐变星星花字",
"is_vip": true
},
{
"id": "7181467986249796920",
"title": "金镂空花字",
"is_vip": true
},
{
"id": "7273052950707145996",
"title": "黄色立体花字",
"is_vip": true
},
{
"id": "7401444618681847103",
"title": "黄色描边花字",
"is_vip": true
},
{
"id": "7322735036669758729",
"title": "年味-金箔字",
"is_vip": true
},
{
"id": "7187743885479791932",
"title": "春节-奇怪兔-黄针织花字",
"is_vip": true
},
{
"id": "7403927207162203402",
"title": "3D黄色渐变立体综艺花字",
"is_vip": true
},
{
"id": "7203613972434685242",
"title": "清新黄色立体花字",
"is_vip": true
},
{
"id": "7245162195829460263",
"title": "淡黄色花字",
"is_vip": true
},
{
"id": "7431549056674991375",
"title": "黄字黑边红底花字",
"is_vip": true
},
{
"id": "7351315241428471090",
"title": "综艺-宇宙一番",
"is_vip": true
},
{
"id": "7127667703048965389",
"title": "黄粉立体",
"is_vip": true
},
{
"id": "7406743750933810471",
"title": "中秋灯笼星星花字",
"is_vip": true
},
{
"id": "7328737068006378787",
"title": "黄色渐变纹理描边花字",
"is_vip": true
},
{
"id": "7495311379738397976",
"title": "黄绸缎",
"is_vip": true
},
{
"id": "7407412458370944294",
"title": "浪漫中秋渐变 ",
"is_vip": true
},
{
"id": "7448948322427047230",
"title": "黄色花字",
"is_vip": true
},
{
"id": "7349752453350395155",
"title": "渐变金色花字",
"is_vip": true
},
{
"id": "7404135722242067722",
"title": "3D综艺风蓝黄渐变立体花字",
"is_vip": true
},
{
"id": "7260815156861619493",
"title": "芭比黄色",
"is_vip": true
},
{
"id": "7160597556869795102",
"title": "综艺立体花字",
"is_vip": true
},
{
"id": "7311260697751457063",
"title": "黄色渐变花字",
"is_vip": true
},
{
"id": "7324728355134147876",
"title": "描边四色花字-黄",
"is_vip": true
},
{
"id": "7309138668319444287",
"title": "元旦-黄红",
"is_vip": true
},
{
"id": "7399157478648253732",
"title": "纹理花字",
"is_vip": true
},
{
"id": "7263114818876476729",
"title": "橙子",
"is_vip": true
},
{
"id": "7405945244237303091",
"title": "格纹复古立体花字",
"is_vip": true
},
{
"id": "7406205299100536074",
"title": "粉黄撞色星星装饰花字",
"is_vip": true
},
{
"id": "7460131684537601331",
"title": "金黄色渐变多色复合描边花字",
"is_vip": true
},
{
"id": "7325388931430763812",
"title": "邮票字",
"is_vip": true
},
{
"id": "7371660746725330217",
"title": "黄色",
"is_vip": true
},
{
"id": "7405224102115527936",
"title": "黄色渐变波点纹理花字",
"is_vip": true
},
{
"id": "7244522111643946275",
"title": "红背景用浅黄色无边无影花字",
"is_vip": true
},
{
"id": "7160597869638978824",
"title": "简约花字",
"is_vip": true
},
{
"id": "7409320679838846234",
"title": "综艺字星星",
"is_vip": true
},
{
"id": "7480466283088235801",
"title": "黄色立体质感花字",
"is_vip": true
},
{
"id": "7402069935075151123",
"title": "黄色描边花字",
"is_vip": true
},
{
"id": "7307096095828528395",
"title": "描边新年花字",
"is_vip": true
},
{
"id": "7328738345616510242",
"title": "浅黄色渐变发光花字",
"is_vip": true
},
{
"id": "7187774415130643769",
"title": "金属金色立体花字",
"is_vip": true
},
{
"id": "7265639510296300852",
"title": "黄白字体重复花字",
"is_vip": true
},
{
"id": "7405023729782164747",
"title": "黄色立体描边花字",
"is_vip": true
},
{
"id": "7371124431713832201",
"title": "黄色渐变立体发光花字",
"is_vip": true
},
{
"id": "7434103306181528882",
"title": "可爱风立体描边",
"is_vip": true
},
{
"id": "7264858160744221971",
"title": "好物美妆黄白渐变",
"is_vip": true
},
{
"id": "7406269205164592396",
"title": "金花字",
"is_vip": true
},
{
"id": "7406979588020047104",
"title": "黄色发光透明字",
"is_vip": true
},
{
"id": "7294994395907018025",
"title": "双11-黄色渐变",
"is_vip": true
},
{
"id": "7389657424883387699",
"title": "白色立体字",
"is_vip": true
},
{
"id": "7340552492331142454",
"title": "黄边橙底花字",
"is_vip": true
},
{
"id": "7404825166351469860",
"title": "黄色线条花字",
"is_vip": true
},
{
"id": "7405239905443482919",
"title": "黄色立体描边花字",
"is_vip": true
},
{
"id": "7405078751823809801",
"title": "黄色立体发光字",
"is_vip": true
},
{
"id": "7349078549061504275",
"title": "渐变白色花字",
"is_vip": true
},
{
"id": "7407448816653258036",
"title": "黄色描边花字",
"is_vip": true
},
{
"id": "7127675251604966669",
"title": "黄蓝立体",
"is_vip": true
},
{
"id": "7406349356347002138",
"title": "黄色镂空描边花字",
"is_vip": true
},
{
"id": "7328608627542002998",
"title": "奶酪花字",
"is_vip": true
},
{
"id": "7400210254580944169",
"title": "橙色立体花字",
"is_vip": true
},
{
"id": "7275153233226616124",
"title": "纯黑底色 黄色黑色描边 立体 花字",
"is_vip": true
},
{
"id": "7380754518914518287",
"title": "黄色花字",
"is_vip": true
},
{
"id": "7283170032912256310",
"title": "国庆旅行-手绘黄",
"is_vip": true
},
{
"id": "7404023782316313890",
"title": "黄底纸张撕边字",
"is_vip": true
},
{
"id": "7404881915871825186",
"title": "黄色波点描边立体花字",
"is_vip": true
},
{
"id": "7329011018632269108",
"title": "红色渐变伪三维多层描边花字",
"is_vip": true
},
{
"id": "7405879107424111910",
"title": "黄色",
"is_vip": true
},
{
"id": "7345385438401580307",
"title": "复古阴影描边花字",
"is_vip": true
},
{
"id": "7270426004617825593",
"title": "黄色黑白描边花字",
"is_vip": true
},
{
"id": "7402075098393365823",
"title": "黄色描边花字",
"is_vip": true
},
{
"id": "7265643261631417635",
"title": "黄白纯色花字",
"is_vip": true
},
{
"id": "7264502894546767116",
"title": "好物美妆-双层投影",
"is_vip": true
},
{
"id": "7251576577530531110",
"title": "白底橙描黄字",
"is_vip": true
},
{
"id": "7311260579992227091",
"title": "运动教程-花字",
"is_vip": true
},
{
"id": "7212892034623950141",
"title": "美食-白网格",
"is_vip": true
},
{
"id": "7387594122032385321",
"title": "描边白蓝字体",
"is_vip": true
},
{
"id": "7127676763148143885",
"title": "黑白描边",
"is_vip": true
},
{
"id": "7351313732443671827",
"title": "综艺-黑暗斑驳白色",
"is_vip": true
},
{
"id": "7160601239800040712",
"title": "简约透明渐变",
"is_vip": true
},
{
"id": "7272727186036116755",
"title": "音乐节-杂点白字",
"is_vip": true
},
{
"id": "7114534269543828766",
"title": "黑白 动漫 波普 美漫 复古",
"is_vip": true
},
{
"id": "7351311491821276452",
"title": "韩国综艺-紧张的瞬间",
"is_vip": true
},
{
"id": "7252680796429897021",
"title": "美食-白色躁点",
"is_vip": true
},
{
"id": "7345748543577099547",
"title": "黑色手绘质感花字",
"is_vip": true
},
{
"id": "7325238973809298742",
"title": "黑色白边花字",
"is_vip": true
},
{
"id": "7343223006396828968",
"title": "纸张背景字",
"is_vip": true
},
{
"id": "7371395905561365770",
"title": "白色DIY纹理立体花字",
"is_vip": true
},
{
"id": "7166468321125207299",
"title": "复古黑色渐变立体花字",
"is_vip": true
},
{
"id": "7369126670915226899",
"title": "立体花字",
"is_vip": true
},
{
"id": "7166477143159868710",
"title": "复古白色图案立体花字",
"is_vip": true
},
{
"id": "7337938878139010355",
"title": "纹理花字",
"is_vip": true
},
{
"id": "7181453824148753702",
"title": "撒银粉花字",
"is_vip": true
},
{
"id": "7166490848820038945",
"title": "暗黑白边黑色立体花字",
"is_vip": true
},
{
"id": "7181336409813372197",
"title": "透明渐变-白",
"is_vip": true
},
{
"id": "7311952196956917033",
"title": "运动教程-纹理花字",
"is_vip": true
},
{
"id": "7160595742489382151",
"title": "潮酷灰色立体花字",
"is_vip": true
},
{
"id": "7273018315025550628",
"title": "黑白花字",
"is_vip": true
},
{
"id": "7343809832324975891",
"title": "纸张背景字",
"is_vip": true
},
{
"id": "7194356393271446843",
"title": "元宵-黑字发光",
"is_vip": true
},
{
"id": "7260344475921190207",
"title": "黑白复古红色",
"is_vip": true
},
{
"id": "7313563919245643008",
"title": "拼贴白纸底纹理花字",
"is_vip": true
},
{
"id": "7313511240523959604",
"title": "拼贴底黑白纹理花字",
"is_vip": true
},
{
"id": "7343584149648772352",
"title": "撕边纸张背景字",
"is_vip": true
},
{
"id": "7241426840395549985",
"title": "白色立体花字",
"is_vip": true
},
{
"id": "7173539578815483149",
"title": "3D白字",
"is_vip": true
},
{
"id": "7435890198455536923",
"title": "复古花字",
"is_vip": true
},
{
"id": "7343449320475151627",
"title": "描边纸纹花字",
"is_vip": true
},
{
"id": "7343160086795242788",
"title": "纸张背景字",
"is_vip": true
},
{
"id": "7349124649973730599",
"title": "黑白花字",
"is_vip": true
},
{
"id": "7160602457658117384",
"title": "运动-潮流运动-黑色纸纹",
"is_vip": true
},
{
"id": "7310103573377846538",
"title": "黑色纹理立体花字",
"is_vip": true
},
{
"id": "7400199119807008036",
"title": "黑色立体花字",
"is_vip": true
},
{
"id": "7285632742400740645",
"title": "斑马纹字",
"is_vip": true
},
{
"id": "7266689977793269048",
"title": "黑份星空体",
"is_vip": true
},
{
"id": "7294186899491654951",
"title": "万圣-白木板字",
"is_vip": true
},
{
"id": "7265615157953334562",
"title": "白色毛绒豹纹花字",
"is_vip": true
},
{
"id": "7365355573036059913",
"title": "潮酷花字",
"is_vip": true
},
{
"id": "7200668850155801893",
"title": "潮流运动-纸纹描边",
"is_vip": true
},
{
"id": "6927160144421784832",
"title": "简约黑色描边立体花字",
"is_vip": false
},
{
"id": "6896137990788091143",
"title": "简约白色黑边花字",
"is_vip": false
},
{
"id": "6896143808942066952",
"title": "灰色金属质感花字",
"is_vip": false
},
{
"id": "7166467215410187552",
"title": "简约黑字白边花字",
"is_vip": false
},
{
"id": "7166472183814950183",
"title": "简约白色花字",
"is_vip": false
},
{
"id": "7127681015732096270",
"title": "综艺黑白立体花字",
"is_vip": false
},
{
"id": "7127668616656506149",
"title": "232",
"is_vip": false
},
{
"id": "7166473306248465703",
"title": "网感-黑字白边外发光花字",
"is_vip": false
},
{
"id": "6896137661153676552",
"title": "简约黑白镂空花字",
"is_vip": false
},
{
"id": "6896137924853648648",
"title": "简约黑白花字",
"is_vip": false
},
{
"id": "6896137727012637959",
"title": "白色裂纹花字",
"is_vip": false
},
{
"id": "7127830659275459871",
"title": "综艺 白色",
"is_vip": false
},
{
"id": "7127540233750596871",
"title": "综艺 白色 裂纹",
"is_vip": false
},
{
"id": "7166476751420329248",
"title": "简约白色镂空花字",
"is_vip": false
},
{
"id": "7127830631601474824",
"title": "绿边黑底白色花字",
"is_vip": false
},
{
"id": "6896144074487696654",
"title": "简约白色镂空花字,排版适用",
"is_vip": false
},
{
"id": "6896138188792843527",
"title": "金属感渐变灰色花字,日本综艺",
"is_vip": false
},
{
"id": "7021075312532393247",
"title": "综艺 白色黑边",
"is_vip": false
},
{
"id": "7181337352327941431",
"title": " 投影红底白色花字",
"is_vip": false
},
{
"id": "6896138254819577102",
"title": "白色镂空感简约花字",
"is_vip": false
},
{
"id": "6896138254819560718",
"title": "简约黑灰色拖影花字",
"is_vip": false
},
{
"id": "6896144074487729422",
"title": "简约黑白色花字",
"is_vip": false
},
{
"id": "6926796566347025677",
"title": "简约黑白花字",
"is_vip": false
},
{
"id": "7127823728070741278",
"title": "小清新 白色 ",
"is_vip": false
},
{
"id": "7127669342325542158",
"title": "简约透明白色花字",
"is_vip": false
},
{
"id": "7166475342436224267",
"title": "暗黑白色渐变发光花字",
"is_vip": false
},
{
"id": "7166474083817884966",
"title": "简约白色立体花字",
"is_vip": false
},
{
"id": "7127674303260265764",
"title": "潮酷 白色 ",
"is_vip": false
},
{
"id": "7127676414962224421",
"title": "白底橙色波点花字",
"is_vip": false
},
{
"id": "6896137727012654343",
"title": "简约黑白几何立体花字",
"is_vip": false
},
{
"id": "7304198748958199076",
"title": "丝印纹理花字",
"is_vip": false
},
{
"id": "6896144234013854990",
"title": "半透明灰色立体花字",
"is_vip": false
},
{
"id": "6896137793022545159",
"title": "白色大理石纹理立体花字",
"is_vip": false
},
{
"id": "6927160139363388684",
"title": "潮酷星空立体花字",
"is_vip": false
},
{
"id": "7194356906171927866",
"title": "潮酷黑色绿边发光立体花字 ",
"is_vip": false
},
{
"id": "7127594686541286687",
"title": "综艺 黑色",
"is_vip": false
},
{
"id": "7304122881682853161",
"title": "黑丝印蓝阴影字",
"is_vip": false
},
{
"id": "7200660554552331575",
"title": "潮流运动2-黑色纹理",
"is_vip": false
},
{
"id": "7405917902894927114",
"title": "深蓝白色立体花字",
"is_vip": true
},
{
"id": "7265628111796964643",
"title": "蓝色渐变描边花字",
"is_vip": true
},
{
"id": "7236980379452787968",
"title": "蓝色渐变文字",
"is_vip": true
},
{
"id": "7431507293306506533",
"title": "蓝白色立体花字",
"is_vip": true
},
{
"id": "7405874090348711218",
"title": "3D蓝色渐变立体花字",
"is_vip": true
},
{
"id": "7127828208690482463",
"title": "蓝白花字",
"is_vip": true
},
{
"id": "7478297038023871769",
"title": "花字",
"is_vip": true
},
{
"id": "7297087768889494847",
"title": "蓝色立体描边花字",
"is_vip": true
},
{
"id": "7404757920535055679",
"title": "蓝色渐变星星花字",
"is_vip": true
},
{
"id": "7390775733812989199",
"title": "蓝色 花字",
"is_vip": true
},
{
"id": "7404828637326757172",
"title": "蓝色立体字",
"is_vip": true
},
{
"id": "7284086330060033334",
"title": "蓝色白边立体字",
"is_vip": true
},
{
"id": "7234332653498027325",
"title": "蓝色星空填充花字",
"is_vip": true
},
{
"id": "7339051729943661851",
"title": "蓝色花字 ",
"is_vip": true
},
{
"id": "7404341814565539110",
"title": "蓝色渐变立体",
"is_vip": true
},
{
"id": "7403983551021993243",
"title": "蓝色描边字",
"is_vip": true
},
{
"id": "7315430777976655139",
"title": "伪三维多层描边花字",
"is_vip": true
},
{
"id": "7274827617654656308",
"title": "蓝色描边花字",
"is_vip": true
},
{
"id": "7424738578648894732",
"title": "蓝色渐变动漫风格花字",
"is_vip": true
},
{
"id": "7252223990217837862",
"title": "蓝色雪花花字",
"is_vip": true
},
{
"id": "7511286098283351320",
"title": "蓝色立体花字",
"is_vip": true
},
{
"id": "7298723012642229523",
"title": "冬天花字",
"is_vip": true
},
{
"id": "7317914423186820391",
"title": "知识-花字",
"is_vip": true
},
{
"id": "7404710098255269139",
"title": "双层描边白蓝双色花字",
"is_vip": true
},
{
"id": "7306901916288666906",
"title": "蓝色质感纹理立体花字",
"is_vip": true
},
{
"id": "7274824941151800610",
"title": "复古蓝色花字",
"is_vip": true
},
{
"id": "7283010376986299663",
"title": "深蓝色立体花字",
"is_vip": true
},
{
"id": "7300921005386566931",
"title": "白蓝色粗描边立体字",
"is_vip": true
},
{
"id": "7400713144886119730",
"title": "冷酷蓝色渐变",
"is_vip": true
},
{
"id": "7291342429117107471",
"title": "蓝色霓虹灯",
"is_vip": true
},
{
"id": "7287492960478973238",
"title": "蓝色立体 白字",
"is_vip": true
},
{
"id": "7317913619340070207",
"title": "知识-花字2",
"is_vip": true
},
{
"id": "7378305489609706752",
"title": "蓝色白描边字",
"is_vip": true
},
{
"id": "7302303263188159779",
"title": "冬日-发光蓝",
"is_vip": true
},
{
"id": "7245601258441133369",
"title": "冰爽蓝色花字",
"is_vip": true
},
{
"id": "7404004705740786996",
"title": "蓝色投影字",
"is_vip": true
},
{
"id": "7360972639780850978",
"title": "背景字",
"is_vip": true
},
{
"id": "7273026280830946572",
"title": "黑蓝花字",
"is_vip": true
},
{
"id": "7404089887411965199",
"title": "蓝黑渐变综艺描边立体花字",
"is_vip": true
},
{
"id": "7404876048438938895",
"title": "蓝黑双描边冰块冰雪万花筒花字",
"is_vip": true
},
{
"id": "7300920494520356108",
"title": "蓝边白花字",
"is_vip": true
},
{
"id": "7259925979139722553",
"title": "蓝白描边花字",
"is_vip": true
},
{
"id": "7400998328315448627",
"title": "蓝色科技花字带阴影",
"is_vip": true
},
{
"id": "7400211255723642151",
"title": "蓝色描边花字",
"is_vip": true
},
{
"id": "7400215751618989331",
"title": "蓝色描边花字",
"is_vip": true
},
{
"id": "7245935944744946944",
"title": "韩式综艺",
"is_vip": true
},
{
"id": "7265626134212054324",
"title": "蓝色渐变花字",
"is_vip": true
},
{
"id": "7363764911773699340",
"title": "闪烁蓝",
"is_vip": true
},
{
"id": "7343225910864153896",
"title": "蓝底拼贴字",
"is_vip": true
},
{
"id": "7406384565951941914",
"title": "蓝色双层描边",
"is_vip": true
},
{
"id": "7300919051906321727",
"title": "蓝色花字",
"is_vip": true
},
{
"id": "7401436090340576563",
"title": "蓝色梦幻立体花字",
"is_vip": true
},
{
"id": "7267373226962095415",
"title": "清新简化单色花字",
"is_vip": true
},
{
"id": "7399182466470169919",
"title": "蓝色小清新花字",
"is_vip": true
},
{
"id": "7379206506035662117",
"title": "白字蓝底拼贴花字",
"is_vip": true
},
{
"id": "7448931302520278296",
"title": "蓝色花字",
"is_vip": true
},
{
"id": "7241417086294166836",
"title": "蓝色花字",
"is_vip": true
},
{
"id": "7460439436510301464",
"title": "简约描边纸纹理蓝色花字",
"is_vip": true
},
{
"id": "7400200671015783716",
"title": "蓝色渐变花字",
"is_vip": true
},
{
"id": "7430995853440994570",
"title": "白色纸张质感立体花字",
"is_vip": true
},
{
"id": "7434900706798161203",
"title": "蓝白描边",
"is_vip": true
},
{
"id": "7252220565577026828",
"title": "深蓝色渐变花字",
"is_vip": true
},
{
"id": "7260765036711251261",
"title": "浅色格子布纹花字",
"is_vip": true
},
{
"id": "7431505103326137615",
"title": "白蓝纹理字",
"is_vip": true
},
{
"id": "7366638884362390803",
"title": "蓝白花字",
"is_vip": true
},
{
"id": "7405953919085595930",
"title": "浅蓝内阴影白色描边字",
"is_vip": true
},
{
"id": "7404362111041735974",
"title": "蓝色冰块效果立体花字",
"is_vip": true
},
{
"id": "7247317471550623009",
"title": "白色描边字",
"is_vip": true
},
{
"id": "7471593256606895385",
"title": "蓝黄综艺花字",
"is_vip": true
},
{
"id": "7526161513816739097",
"title": "花字",
"is_vip": true
},
{
"id": "7329779937915702537",
"title": "白色蓝紫渐变立体花字",
"is_vip": true
},
{
"id": "7497604377235049790",
"title": "冰冰凉",
"is_vip": true
},
{
"id": "7525043694467255614",
"title": "蓝色立体花字",
"is_vip": true
},
{
"id": "7450314918068243739",
"title": "白字多层次描边花字",
"is_vip": true
},
{
"id": "7248079950924893451",
"title": "蓝色立体拆痕花字",
"is_vip": true
},
{
"id": "7404526221230443785",
"title": "蓝白色冬季冰雪花字",
"is_vip": true
},
{
"id": "7405801528612769060",
"title": "游戏立体字",
"is_vip": true
},
{
"id": "7245076686734167329",
"title": "赛博花样字体",
"is_vip": true
},
{
"id": "7430824690727275802",
"title": "白色纸张质感立体花字",
"is_vip": true
},
{
"id": "7404076575030922505",
"title": "白色石材质感立体蓝阴影花字",
"is_vip": true
},
{
"id": "7400212292211641663",
"title": "蓝色立体花字",
"is_vip": true
},
{
"id": "7256676293956128055",
"title": "多巴胺蓝色花字",
"is_vip": true
},
{
"id": "7510996426575449368",
"title": "白色花字",
"is_vip": true
},
{
"id": "7377956281291672842",
"title": "蓝色描边投影立体花字",
"is_vip": true
},
{
"id": "7346455592367623443",
"title": "蓝色阴影花字",
"is_vip": true
},
{
"id": "7511159840157453592",
"title": "蓝色立体花字",
"is_vip": true
},
{
"id": "7331609291226402102",
"title": "蓝色阴影花字",
"is_vip": true
},
{
"id": "7405224199884737827",
"title": "蓝色渐变波点纹理花字",
"is_vip": true
},
{
"id": "7314956298682928384",
"title": "像素风游戏风纹理花字蓝色伪三维",
"is_vip": true
},
{
"id": "7404762475582786852",
"title": "浅蓝色纹理立体花字",
"is_vip": true
},
{
"id": "7291337904947776802",
"title": "蓝色渐变卡通花字",
"is_vip": true
},
{
"id": "7430797889141509416",
"title": "复古蓝色字",
"is_vip": true
},
{
"id": "7404381121615613210",
"title": "白字蓝边粗描边花字",
"is_vip": true
},
{
"id": "7400214111411293451",
"title": "蓝色描边花字",
"is_vip": true
},
{
"id": "7402114255383760166",
"title": "卡通条纹渐变花字",
"is_vip": true
},
{
"id": "7480096931411266840",
"title": "立体字",
"is_vip": true
},
{
"id": "7430854925019565321",
"title": "冬至圆底",
"is_vip": true
},
{
"id": "7252216909721029899",
"title": "蓝色渐变花字",
"is_vip": true
},
{
"id": "7405238192510602546",
"title": "蓝色渐变方底花字",
"is_vip": true
},
{
"id": "7527223959767764248",
"title": "互动引导立体",
"is_vip": true
},
{
"id": "7332635756839718179",
"title": "特殊纹理粉色渐变花字白色描边",
"is_vip": true
},
{
"id": "7403931785077329167",
"title": "粉色黑投影立体字",
"is_vip": true
},
{
"id": "7268272864770460991",
"title": "时尚亮粉色花字",
"is_vip": true
},
{
"id": "7389651692385570075",
"title": "白色立体字",
"is_vip": true
},
{
"id": "7399162410034105636",
"title": "粉色花字",
"is_vip": true
},
{
"id": "7506871646129573182",
"title": "端午61立体字效",
"is_vip": true
},
{
"id": "7265147554952711465",
"title": "七夕-粉色渐变",
"is_vip": true
},
{
"id": "7350942991793622335",
"title": "描边阴影花字",
"is_vip": true
},
{
"id": "7526125596955659545",
"title": "美妆立体",
"is_vip": true
},
{
"id": "7263028102610144575",
"title": "粉色描边白色花字",
"is_vip": true
},
{
"id": "7350941310355868991",
"title": "粉色渐变花字",
"is_vip": true
},
{
"id": "7399826245703175487",
"title": "粉色描边花字",
"is_vip": true
},
{
"id": "7371412248163568905",
"title": "粉蓝色多层立体综艺风花字",
"is_vip": true
},
{
"id": "7471642975651564862",
"title": "粉黄描边立体",
"is_vip": true
},
{
"id": "7160605820927872292",
"title": "复古发光立体花字",
"is_vip": true
},
{
"id": "7496412960647286078",
"title": "母亲节立体",
"is_vip": true
},
{
"id": "7405576947159387443",
"title": "粉色渐变立体爱心背景花字",
"is_vip": true
},
{
"id": "7273263711744232741",
"title": "粉色系花字",
"is_vip": true
},
{
"id": "7471951122425515288",
"title": "小清新粉绿渐变立体花字",
"is_vip": true
},
{
"id": "7401443574719483155",
"title": "粉色立体花字",
"is_vip": true
},
{
"id": "7476028091077430552",
"title": "粉色立体描边花字",
"is_vip": true
},
{
"id": "7405950908644723977",
"title": "发光花字",
"is_vip": true
},
{
"id": "7401438526962666788",
"title": "粉色发光花字",
"is_vip": true
},
{
"id": "7265599528579943714",
"title": "粉色草莓熊花字",
"is_vip": true
},
{
"id": "7351316363849354534",
"title": "综艺-超期待",
"is_vip": true
},
{
"id": "7278850102503001403",
"title": "鼠鼻红 黑描边",
"is_vip": true
},
{
"id": "7474566247460441368",
"title": "粉白描边立体",
"is_vip": true
},
{
"id": "7404367331842936115",
"title": "蓝粉色渐变多层立体花字",
"is_vip": true
},
{
"id": "7337322283540696347",
"title": "玫红色 玫红色黑边花字",
"is_vip": true
},
{
"id": "7127666013495102750",
"title": "粉绿花字",
"is_vip": true
},
{
"id": "7469667482442222910",
"title": "粉色立体",
"is_vip": true
},
{
"id": "7362783053573262629",
"title": "红边立体字",
"is_vip": true
},
{
"id": "6896144127935761672",
"title": "可爱渐变粉色立体花字,少女漫画",
"is_vip": true
},
{
"id": "7403924486346509606",
"title": "红色发光",
"is_vip": true
},
{
"id": "7355780050513382668",
"title": "黑粉撞色",
"is_vip": true
},
{
"id": "7257044199663602998",
"title": "立体字",
"is_vip": true
},
{
"id": "7348036600766483751",
"title": "立体樱花花字",
"is_vip": true
},
{
"id": "7252103474719051020",
"title": "红色立体花字",
"is_vip": true
},
{
"id": "7241808652640865595",
"title": "玻璃质感",
"is_vip": true
},
{
"id": "7403773847754902810",
"title": "粉紫色渐变发光花字",
"is_vip": true
},
{
"id": "7442237073668508978",
"title": "清新粉色立体花字",
"is_vip": true
},
{
"id": "7494574052934241560",
"title": "粉黄立体花字",
"is_vip": true
},
{
"id": "7404309195387882786",
"title": "粉色渐隐字",
"is_vip": true
},
{
"id": "7198021796891757882",
"title": "梦幻粉色渐变立体花字",
"is_vip": true
},
{
"id": "7252148714372943136",
"title": "蓝紫色花字",
"is_vip": true
},
{
"id": "7447461222691261731",
"title": "圣诞落雪-粉",
"is_vip": true
},
{
"id": "7259354579664375077",
"title": "芭比花字",
"is_vip": true
},
{
"id": "7532077639864208665",
"title": "花字",
"is_vip": true
},
{
"id": "7283431566179585343",
"title": "国庆旅行-粉",
"is_vip": true
},
{
"id": "7371338640280161545",
"title": "粉色渐变仿3d立体花字",
"is_vip": true
},
{
"id": "7197315212834377016",
"title": "文艺粉色渐变花字",
"is_vip": true
},
{
"id": "7363797275652443455",
"title": "闪烁浅粉",
"is_vip": true
},
{
"id": "7127678663583157517",
"title": "粉粉描边",
"is_vip": true
},
{
"id": "7434113204139117850",
"title": "立体粉色描边",
"is_vip": true
},
{
"id": "7483781507337817406",
"title": "透明果冻粉",
"is_vip": true
},
{
"id": "7278851099656768805",
"title": "合欢红 黑白描边",
"is_vip": true
},
{
"id": "7406010312467434779",
"title": "紫粉色星光发光花字",
"is_vip": true
},
{
"id": "7347229028467608869",
"title": "仿3d粉色",
"is_vip": true
},
{
"id": "7517639254835612937",
"title": "红白色炫彩花字",
"is_vip": true
},
{
"id": "7187770600503512381",
"title": "春节-兔彩头-粉色",
"is_vip": true
},
{
"id": "7362836205475548470",
"title": "磨砂",
"is_vip": true
},
{
"id": "7404359079063244067",
"title": "清新粉色立体描边花字",
"is_vip": true
},
{
"id": "7404870544413281536",
"title": "粉白描边立体节日花字",
"is_vip": true
},
{
"id": "7343590343138446604",
"title": "花朵形状花字",
"is_vip": true
},
{
"id": "7405224954368642319",
"title": "粉色渐变波点纹理花字",
"is_vip": true
},
{
"id": "7270134110692085029",
"title": "紫底橙边渐变色立体花字",
"is_vip": true
},
{
"id": "7535298048642108697",
"title": "粉蓝弥散渐变立体花字",
"is_vip": true
},
{
"id": "7362188947243404596",
"title": "粉色花字 ",
"is_vip": true
},
{
"id": "7312854311854148890",
"title": "黄粉渐变立体花字",
"is_vip": true
},
{
"id": "7362367983555005733",
"title": "粉色花字",
"is_vip": true
},
{
"id": "7366060800315788570",
"title": "粉色渐变发光花字",
"is_vip": true
},
{
"id": "7404520184062430491",
"title": "粉白色渐变立体花字",
"is_vip": true
},
{
"id": "7406172056645078299",
"title": "黑粉甜酷渐变花字",
"is_vip": true
},
{
"id": "7362058534923554111",
"title": "粉色水彩花字",
"is_vip": true
},
{
"id": "7260824497358409020",
"title": "芭比白色描边",
"is_vip": true
},
{
"id": "7244717011618532640",
"title": "纯色系花字",
"is_vip": true
},
{
"id": "7260778139385695549",
"title": "镭射粉边厚投影",
"is_vip": true
},
{
"id": "7403951797972339979",
"title": "立体渐变花字(综艺)",
"is_vip": true
},
{
"id": "7241938590169713923",
"title": "白色综艺感花字",
"is_vip": true
},
{
"id": "7114574351407533342",
"title": "粉色 立体 白色 蒸汽波 像素风",
"is_vip": true
},
{
"id": "7284091009229704487",
"title": "粉色黑边花字",
"is_vip": true
},
{
"id": "7324622240555765046",
"title": "粉色蜡笔花字",
"is_vip": true
},
{
"id": "7481670126689946942",
"title": "粉色",
"is_vip": true
},
{
"id": "7404035812284779827",
"title": "粉色渐变花字",
"is_vip": true
},
{
"id": "7406638428864924954",
"title": "粉色渐变发光",
"is_vip": true
},
{
"id": "7405198458337889586",
"title": "白芭比花字",
"is_vip": true
},
{
"id": "7505772084703022361",
"title": "粉蓝闪闪花字",
"is_vip": true
},
{
"id": "7537151663212268825",
"title": "立体紫粉",
"is_vip": true
},
{
"id": "7283169557890501924",
"title": "国庆旅行-手绘粉白",
"is_vip": true
},
{
"id": "7337558715559611686",
"title": "粉色立体节日女神节",
"is_vip": true
},
{
"id": "7263270863359724856",
"title": "高级美式配色花字",
"is_vip": true
},
{
"id": "7403763886584777984",
"title": "可爱粉黄渐变立体花字",
"is_vip": true
},
{
"id": "7371118955500555571",
"title": "白粉色仿3D立体花字",
"is_vip": true
},
{
"id": "7470023899539967257",
"title": "粉紫色气球花字",
"is_vip": true
},
{
"id": "7404876152554278154",
"title": "黄粉圆底心星点缀花字",
"is_vip": true
},
{
"id": "7311627613137620278",
"title": "黑色描边深粉色渐变",
"is_vip": true
},
{
"id": "7541231272509574424",
"title": "蛋糕卷",
"is_vip": true
},
{
"id": "7400688551689555210",
"title": "渐变粉色花字",
"is_vip": true
},
{
"id": "7263379569594436900",
"title": "芭比粉",
"is_vip": true
},
{
"id": "7296704810148007219",
"title": "粉蓝彩色渐变立体花字",
"is_vip": true
},
{
"id": "7361330845342371113",
"title": "涂鸦字",
"is_vip": true
},
{
"id": "7459711214587776318",
"title": "粉色闪闪花字",
"is_vip": true
},
{
"id": "7402071915386408203",
"title": "紫色描边花字",
"is_vip": true
},
{
"id": "7403721451993304370",
"title": "甜酷芭比粉色立体花字",
"is_vip": true
},
{
"id": "7402123078743919923",
"title": "粉色千层浪漫花字",
"is_vip": true
},
{
"id": "7328249466295733544",
"title": "爱心背景字",
"is_vip": true
},
{
"id": "7406377074849566003",
"title": "粉色紫色渐变立体",
"is_vip": true
},
{
"id": "7260816673165364541",
"title": "芭比黄色描边",
"is_vip": true
},
{
"id": "7403767866266324261",
"title": "粉紫色多层渐变立体花字",
"is_vip": true
},
{
"id": "7403755765573471500",
"title": "粉色y2k风花字",
"is_vip": true
},
{
"id": "7408393528163716404",
"title": "红字黄边立体字",
"is_vip": true
},
{
"id": "7400336012813159699",
"title": "紫色渐变花字",
"is_vip": true
},
{
"id": "7260309891452013883",
"title": "粉红色描边花字",
"is_vip": true
},
{
"id": "7284083822910655756",
"title": "粉色黄边红底立体字体",
"is_vip": true
},
{
"id": "7265636585973009704",
"title": "粉色渐变双色描边花字",
"is_vip": true
},
{
"id": "7405756302271483155",
"title": "粉色樱花花字",
"is_vip": true
},
{
"id": "7546485148498431256",
"title": "粉绿纹理综艺花字",
"is_vip": true
},
{
"id": "7345309219098201370",
"title": "春日辣妹",
"is_vip": true
},
{
"id": "7523240490314173721",
"title": "粉蓝色立体字效",
"is_vip": true
},
{
"id": "7404713728219925801",
"title": "粉黑色描边甜酷花字",
"is_vip": true
},
{
"id": "7405254623050599732",
"title": "粉色渐变透明花字",
"is_vip": true
},
{
"id": "7404706418848271670",
"title": "多层描边粉紫色渐变花字",
"is_vip": true
},
{
"id": "7522895833600380222",
"title": "糖果",
"is_vip": true
},
{
"id": "7266702065966107959",
"title": "粉色少女",
"is_vip": true
},
{
"id": "7340848509379251468",
"title": "皇冠字",
"is_vip": true
},
{
"id": "7251733111518579979",
"title": "粉紫色花字 ",
"is_vip": true
},
{
"id": "7297042051802172698",
"title": "纹理花字",
"is_vip": true
},
{
"id": "7405086290414144777",
"title": "粉色花字",
"is_vip": true
},
{
"id": "7328707180419386676",
"title": "粉色渐变发光花字 多层描边",
"is_vip": true
},
{
"id": "7405929528134077734",
"title": "橘色渐变镂空描边花字",
"is_vip": true
},
{
"id": "7404493990520802598",
"title": "亮绿色拼接花字",
"is_vip": true
},
{
"id": "7403996884856999194",
"title": "绿色渐变花字",
"is_vip": true
},
{
"id": "7268270899432852799",
"title": "亮绿色综艺花字",
"is_vip": true
},
{
"id": "7160596905548942622",
"title": "运动-潮流运动-渐变描边",
"is_vip": true
},
{
"id": "7473670543162641689",
"title": "白色立体花字",
"is_vip": true
},
{
"id": "7278133287623707965",
"title": "生鲜 绿色 花字",
"is_vip": true
},
{
"id": "7371122063710391561",
"title": "青色渐变立体花字",
"is_vip": true
},
{
"id": "7187772431149305143",
"title": "复古绿色渐变立体花字",
"is_vip": true
},
{
"id": "7475754844909882649",
"title": "绿色立体花字",
"is_vip": true
},
{
"id": "7404747598109609228",
"title": "绿色蓝色描边花字",
"is_vip": true
},
{
"id": "7406966103861169408",
"title": "黄绿渐变立体字",
"is_vip": true
},
{
"id": "7298613319999540507",
"title": "浅绿渐变立体花字",
"is_vip": true
},
{
"id": "7294165467973897526",
"title": "绿巨人花字",
"is_vip": true
},
{
"id": "7348241222261050663",
"title": "渐变青色花字",
"is_vip": true
},
{
"id": "7281934860015406391",
"title": "黑加绿花字",
"is_vip": true
},
{
"id": "7265646083169193231",
"title": "白绿色字体重复花字",
"is_vip": true
},
{
"id": "7388017961174404415",
"title": "潮酷简约渐变绿色花字",
"is_vip": true
},
{
"id": "7283056755100208443",
"title": "草绿色渐变花字",
"is_vip": true
},
{
"id": "7404080787638799651",
"title": "高饱和撞色渐变立体花字",
"is_vip": true
},
{
"id": "7473821452597316926",
"title": "运动立体",
"is_vip": true
},
{
"id": "7291929593328504100",
"title": "综艺活泼亮色花字",
"is_vip": true
},
{
"id": "7472017607768673598",
"title": "绿色花字",
"is_vip": true
},
{
"id": "7398445914676874505",
"title": "tiffany波纹面",
"is_vip": true
},
{
"id": "7473921287983795481",
"title": "黄色渐变立体花字",
"is_vip": true
},
{
"id": "7400209808361622825",
"title": "清新绿色描边花字",
"is_vip": true
},
{
"id": "7334624542985391411",
"title": "绿色质感花字 绿色金属质感反光花字",
"is_vip": true
},
{
"id": "7239898171730595110",
"title": "绿色阴影描边花字",
"is_vip": true
},
{
"id": "7367570395483983143",
"title": "绿色纹理",
"is_vip": true
},
{
"id": "7344963566241336639",
"title": "薄荷绿拼贴花字",
"is_vip": true
},
{
"id": "7346463952278244618",
"title": "港风",
"is_vip": true
},
{
"id": "7404093067151658274",
"title": "简约绿色镂空花字",
"is_vip": true
},
{
"id": "7260286417681599784",
"title": "绿色黑边花字",
"is_vip": true
},
{
"id": "7137931766576205093",
"title": "花字-金属立体绿",
"is_vip": true
},
{
"id": "7259935584053972284",
"title": "绿色描边花字",
"is_vip": true
},
{
"id": "7372039427452865819",
"title": "白字蓝绿渐变描边花字",
"is_vip": true
},
{
"id": "7298573318259477770",
"title": "浅绿渐变立体花字",
"is_vip": true
},
{
"id": "7405127816867597605",
"title": "绿色清新条纹渐变立体花字",
"is_vip": true
},
{
"id": "7298614541112397083",
"title": "绿色渐变立体花字",
"is_vip": true
},
{
"id": "7367605728321801509",
"title": "浅绿色渐变花字",
"is_vip": true
},
{
"id": "7252153542847319307",
"title": "渐变绿色花字",
"is_vip": true
},
{
"id": "7404768610100497700",
"title": "黄绿色纹理花字",
"is_vip": true
},
{
"id": "7407443209355332864",
"title": "绿色描边花字",
"is_vip": true
},
{
"id": "7327621248937151785",
"title": "黑板绿色复古简单极简风格标题",
"is_vip": true
},
{
"id": "7236568168368491814",
"title": "简约渐变花字",
"is_vip": true
},
{
"id": "7174293913962827016",
"title": "圣诞青字",
"is_vip": true
},
{
"id": "7310093916974419210",
"title": "黑色纹理立体花字",
"is_vip": true
},
{
"id": "7298617654846295305",
"title": "浅绿渐变立体花字",
"is_vip": true
},
{
"id": "7411774424355065088",
"title": "黄绿描边花字",
"is_vip": true
},
{
"id": "7114570857992703269",
"title": "立体 白色 蒸汽波 像素风 黄绿色黄色绿色",
"is_vip": true
},
{
"id": "7345749275839597874",
"title": "绿色渐变立体花字",
"is_vip": true
},
{
"id": "7347215675548634406",
"title": "港风 ",
"is_vip": true
},
{
"id": "7254739710776593724",
"title": "综艺绿色描边花字",
"is_vip": true
},
{
"id": "7342427659030383883",
"title": "描边纸纹花字",
"is_vip": true
},
{
"id": "7397647341706104090",
"title": "绿色紫色",
"is_vip": true
},
{
"id": "7366841667820752140",
"title": "绿色",
"is_vip": true
},
{
"id": "7431507395127282954",
"title": "绿色立体花字",
"is_vip": true
},
{
"id": "7406004095309450546",
"title": "绿色条纹渐变发光花字",
"is_vip": true
},
{
"id": "7274503640545627404",
"title": "绿色渐变花字",
"is_vip": true
},
{
"id": "7361014988858789120",
"title": "绿色描边",
"is_vip": true
},
{
"id": "7405962322373578024",
"title": "蓝绿色立体花字",
"is_vip": true
},
{
"id": "7368761827230092595",
"title": "清新花字",
"is_vip": true
},
{
"id": "7430467479744335142",
"title": "双十一黄绿立体",
"is_vip": true
},
{
"id": "7344956185780456743",
"title": "绿色渐变阴影花字",
"is_vip": true
},
{
"id": "7405561923728690458",
"title": "复古绿色立体花字",
"is_vip": true
},
{
"id": "7404854087830867234",
"title": "绿色渐变立体字",
"is_vip": true
},
{
"id": "7405128752167963914",
"title": "蓝绿色运动风渐变花字",
"is_vip": true
},
{
"id": "7283122934682504460",
"title": "国庆旅行-手绘字",
"is_vip": true
},
{
"id": "7273732632578493755",
"title": "蓝绿色纹理渐变立体花字",
"is_vip": true
},
{
"id": "7431502293394099506",
"title": "白色立体花字",
"is_vip": true
},
{
"id": "7348234501983636799",
"title": "青色纹理花字",
"is_vip": true
},
{
"id": "7474572068676357401",
"title": "粉绿色渐变多层立体花字",
"is_vip": true
},
{
"id": "7312852084502564146",
"title": "黄蓝渐变立体花字",
"is_vip": true
},
{
"id": "7406256498252188968",
"title": "三色渐变发光字",
"is_vip": true
},
{
"id": "7305827683798224191",
"title": "圣诞-复古绿点",
"is_vip": true
},
{
"id": "7360585289733098771",
"title": "绿色剪纸纹理",
"is_vip": true
},
{
"id": "7203615859544182053",
"title": "亲子-绿色饼干立体字",
"is_vip": true
},
{
"id": "7293142782896590114",
"title": "绿色紫色花字",
"is_vip": true
},
{
"id": "7347236230674844937",
"title": "仿3d水波纹薄荷",
"is_vip": true
},
{
"id": "7298600104972307722",
"title": "浅绿渐变立体花字",
"is_vip": true
},
{
"id": "7272324394641280319",
"title": "好物推荐-眼前一黑",
"is_vip": true
},
{
"id": "7430436359287868682",
"title": "绿字描边绿草茵茵经典风格花字",
"is_vip": true
},
{
"id": "7348238901154221323",
"title": "青团花字",
"is_vip": true
},
{
"id": "7266049922468695353",
"title": "清新配色哈密瓜色",
"is_vip": true
},
{
"id": "7349548116372180260",
"title": "青绿色渐变白描边花字",
"is_vip": true
},
{
"id": "7430785639781567753",
"title": "蓝黄渐变绿色描边花字",
"is_vip": true
},
{
"id": "7369021564211318028",
"title": "青色",
"is_vip": true
},
{
"id": "7389681541141597478",
"title": "绿色国风",
"is_vip": true
},
{
"id": "7357047867233602855",
"title": "晕染绿",
"is_vip": true
},
{
"id": "7351694267858865462",
"title": "格子蓝绿",
"is_vip": true
},
{
"id": "7348986730529262899",
"title": "绿色花字",
"is_vip": true
},
{
"id": "7404139316554779914",
"title": "绿色纸张拼贴背景综艺花字",
"is_vip": true
},
{
"id": "7280818803355700499",
"title": "复古花字",
"is_vip": true
},
{
"id": "7346213993691794699",
"title": "立体花字",
"is_vip": true
},
{
"id": "7344606077083864357",
"title": "花字",
"is_vip": true
},
{
"id": "7272741033979546943",
"title": "音乐-杂点绿色",
"is_vip": true
},
{
"id": "7403935407680834851",
"title": "绿色荧光细黑描边字",
"is_vip": true
},
{
"id": "7351681114013994252",
"title": "格子绿",
"is_vip": true
},
{
"id": "7160596892773027079",
"title": "运动-潮流运动-绿蓝色纸纹",
"is_vip": true
},
{
"id": "7239892464302034214",
"title": "绿白渐变花字",
"is_vip": true
},
{
"id": "7298617928423902502",
"title": "浅绿渐变立体花字",
"is_vip": true
},
{
"id": "7312358171530595623",
"title": "圣诞-圣诞快乐",
"is_vip": true
},
{
"id": "7360990469402283298",
"title": "双色描边",
"is_vip": true
},
{
"id": "7351302410180005157",
"title": "绿色花字",
"is_vip": true
},
{
"id": "7406991694668795163",
"title": "绿色渐变黑边字",
"is_vip": true
},
{
"id": "7523990414601260350",
"title": "小荷漫漫",
"is_vip": true
},
{
"id": "7406685269446905125",
"title": "白字绿边带格纹",
"is_vip": true
},
{
"id": "7312853585660857637",
"title": "紫绿渐变立体花字",
"is_vip": true
},
{
"id": "7406011060521667866",
"title": "绿色水晶立体渐变花字",
"is_vip": true
},
{
"id": "7404043957887372571",
"title": "港风复古墨绿圆边花字",
"is_vip": true
},
{
"id": "7334619118340951322",
"title": "清新豆绿色 白字绿底花字",
"is_vip": true
},
{
"id": "7366841083415874835",
"title": "绿色",
"is_vip": true
},
{
"id": "7348239399705972009",
"title": "青色纹理花字",
"is_vip": true
},
{
"id": "7281933472610929981",
"title": "草绿色花字",
"is_vip": true
},
{
"id": "7241410366796811555",
"title": "绿色粉描边花字",
"is_vip": true
},
{
"id": "7330397394950966568",
"title": "绿色背景圈花字",
"is_vip": true
},
{
"id": "7405130126477757722",
"title": "白绿多层渐变投影花字",
"is_vip": true
},
{
"id": "7279301469516434747",
"title": "绿色立体花字",
"is_vip": true
},
{
"id": "7312427317089848617",
"title": "圣诞-圣诞色渐变",
"is_vip": true
},
{
"id": "7330567349382286644",
"title": "黄绿色渐变圆形纹理底白色花字",
"is_vip": true
},
{
"id": "7279304624253701434",
"title": "绿色同系花字",
"is_vip": true
},
{
"id": "7343445448100810025",
"title": "纸纹花字",
"is_vip": true
},
{
"id": "7298262240036146458",
"title": "绿色立体花字",
"is_vip": true
},
{
"id": "7343820951823355170",
"title": "伪三维拼贴纹理薄荷绿花字",
"is_vip": true
},
{
"id": "7367375630180076850",
"title": "绿色渐变花字",
"is_vip": true
},
{
"id": "7345386966076165412",
"title": "复古圆底花字",
"is_vip": true
},
{
"id": "7404137941632552202",
"title": "蓝绿色渐变多层投影立体花字",
"is_vip": true
},
{
"id": "7243593806409436474",
"title": "小清新绿色立体花字",
"is_vip": true
},
{
"id": "7260765133243288887",
"title": "格子布纹花字",
"is_vip": true
},
{
"id": "7404510647829957914",
"title": "绿色渐变白边花字",
"is_vip": true
},
{
"id": "7346195217466363148",
"title": "毛毡薄荷绿花字",
"is_vip": true
},
{
"id": "7224819211233676556",
"title": "古朴青",
"is_vip": true
},
{
"id": "7280421022845668669",
"title": "绿色时尚",
"is_vip": true
},
{
"id": "7370971660947705099",
"title": "青色",
"is_vip": true
},
{
"id": "7359509585222208778",
"title": "绿色手绘涂鸦花字",
"is_vip": true
},
{
"id": "7404713810730241319",
"title": "绿色渐变立体描边花字",
"is_vip": true
},
{
"id": "7406323483690470696",
"title": "绿色渐变立体花字",
"is_vip": true
},
{
"id": "7282316784424865078",
"title": "浅绿色白边花字",
"is_vip": true
},
{
"id": "7351685926277352723",
"title": "黄绿格",
"is_vip": true
},
{
"id": "7298573839447903498",
"title": "浅绿渐变立体花字",
"is_vip": true
},
{
"id": "7304160131338571044",
"title": "麻将花字",
"is_vip": true
},
{
"id": "7405636378769313065",
"title": "绿色描边立体花字",
"is_vip": true
},
{
"id": "7244834053323492611",
"title": "综艺花字",
"is_vip": true
},
{
"id": "7231522690144685315",
"title": "清风土黄花边可爱花字",
"is_vip": true
},
{
"id": "7404777605955734793",
"title": "复古质感肌理花字",
"is_vip": true
},
{
"id": "7245959768349691195",
"title": "韩综艺术",
"is_vip": true
},
{
"id": "7338390981055761704",
"title": "清新点亮朦胧立体花字",
"is_vip": true
},
{
"id": "7405124477803171124",
"title": "紫色立体文字",
"is_vip": true
},
{
"id": "7347627316031311115",
"title": "赛博朋克故障字",
"is_vip": true
},
{
"id": "7265622486312652047",
"title": "紫色渐变描边花字",
"is_vip": true
},
{
"id": "7407080664236870964",
"title": "紫色多重描边字",
"is_vip": true
},
{
"id": "7406236406151925007",
"title": "紫色渐变立体字",
"is_vip": true
},
{
"id": "7241956897010552124",
"title": "蓝紫渐变花字 黑白描边花字",
"is_vip": true
},
{
"id": "7430766119671139595",
"title": "紫色花字",
"is_vip": true
},
{
"id": "7507256223939530009",
"title": "618紫色渐变立体字效",
"is_vip": true
},
{
"id": "7236965265383230760",
"title": "紫色彩虹字",
"is_vip": true
},
{
"id": "7402066866572741927",
"title": "紫色描边花字",
"is_vip": true
},
{
"id": "7405948653761744137",
"title": "赛博故障风荧光花字",
"is_vip": true
},
{
"id": "7349028882974018835",
"title": "故障风花字",
"is_vip": true
},
{
"id": "7406657094851562792",
"title": "紫色立体字",
"is_vip": true
},
{
"id": "7475389169183837502",
"title": "橙紫立体花字",
"is_vip": true
},
{
"id": "7389866725287709979",
"title": "紫色蓝边立体花字",
"is_vip": true
},
{
"id": "7424524996350905612",
"title": "紫红色描边立体花字",
"is_vip": true
},
{
"id": "7352837737730592015",
"title": "紫色花字",
"is_vip": true
},
{
"id": "7312852437327547658",
"title": "蓝紫渐变立体花字",
"is_vip": true
},
{
"id": "7265657776012004648",
"title": "蓝粉纯色花字",
"is_vip": true
},
{
"id": "7388023559047761191",
"title": "综艺潮流淡紫色渐变白边立体花字",
"is_vip": true
},
{
"id": "7312836005227302195",
"title": "粉紫渐变立体花字",
"is_vip": true
},
{
"id": "7404055341010390324",
"title": "紫色渐变投影字",
"is_vip": true
},
{
"id": "7430666396389969164",
"title": "紫色立体发光花字",
"is_vip": true
},
{
"id": "7405053909191904566",
"title": "蓝紫色渐变描边立体花字",
"is_vip": true
},
{
"id": "7265615178446720256",
"title": "紫色闪烁花字",
"is_vip": true
},
{
"id": "7405043787539549452",
"title": "白色立体描边花字",
"is_vip": true
},
{
"id": "7241714501995875639",
"title": "星空",
"is_vip": true
},
{
"id": "7231020400791129400",
"title": "星空",
"is_vip": true
},
{
"id": "7405191566295420199",
"title": "白色描边立体花字",
"is_vip": true
},
{
"id": "7243961568067603744",
"title": "渐变花字",
"is_vip": true
},
{
"id": "7404673172978650431",
"title": "紫色渐变立体描边花字",
"is_vip": true
},
{
"id": "7278520644478782775",
"title": "颜色渐变花字",
"is_vip": true
},
{
"id": "7406011763457576201",
"title": "紫色渐变立体花字",
"is_vip": true
},
{
"id": "7481958256655486233",
"title": "紫玫瑰",
"is_vip": true
},
{
"id": "7249741698094468412",
"title": "多彩文字",
"is_vip": true
},
{
"id": "7274825472574262528",
"title": "黄紫色描边花字",
"is_vip": true
},
{
"id": "7406974135018048820",
"title": "紫红渐变透明字",
"is_vip": true
},
{
"id": "7127673746902502670",
"title": "紫绿立体",
"is_vip": true
},
{
"id": "7252144476603403524",
"title": "蓝紫色黑边花字",
"is_vip": true
},
{
"id": "7405967249992879410",
"title": "发光粉赛博故障风立体花字",
"is_vip": true
},
{
"id": "7351302252562337062",
"title": "科技花字",
"is_vip": true
},
{
"id": "7267344857406967096",
"title": "星空之恋",
"is_vip": true
},
{
"id": "7265636153896750336",
"title": "紫色渐变花字",
"is_vip": true
},
{
"id": "7127822319824735519",
"title": "紫绿描边",
"is_vip": true
},
{
"id": "7404469048517414153",
"title": "万圣节主题色描边花字",
"is_vip": true
},
{
"id": "7399634464659279131",
"title": "星空花字",
"is_vip": true
},
{
"id": "7281948081925475644",
"title": "浅紫色花字",
"is_vip": true
},
{
"id": "7406649743616740642",
"title": "紫色立体字",
"is_vip": true
},
{
"id": "7265635918487293219",
"title": "紫色渐变双色描边花字",
"is_vip": true
},
{
"id": "7244842014347545889",
"title": "紫色立体花字",
"is_vip": true
},
{
"id": "7434403828629245223",
"title": "简约双层描边渐变紫色花字",
"is_vip": true
},
{
"id": "7424527557699079487",
"title": "紫色骷髅立体花字",
"is_vip": true
},
{
"id": "7351056144141487375",
"title": "紫色花字音符纹理",
"is_vip": true
},
{
"id": "7265645422692109568",
"title": "紫粉纯色花字",
"is_vip": true
},
{
"id": "7279303499140107581",
"title": "紫色花字",
"is_vip": true
},
{
"id": "7231341549659917625",
"title": "蓝紫渐变花字",
"is_vip": true
},
{
"id": "7259998381869763851",
"title": "纯色紫色",
"is_vip": true
},
{
"id": "7268274152124075299",
"title": "简约紫色花字",
"is_vip": true
},
{
"id": "7296422791732071717",
"title": "粉色渐变立体花字",
"is_vip": true
},
{
"id": "7405210233917787446",
"title": "紫色描边立体发光花字",
"is_vip": true
},
{
"id": "7289731248933850429",
"title": "渐变花字",
"is_vip": true
},
{
"id": "7231466623775903032",
"title": "粉紫渐变黑边边花字",
"is_vip": true
},
{
"id": "7231026233994235173",
"title": "粉色渐变花字",
"is_vip": true
},
{
"id": "7289731761637002551",
"title": "渐变花字",
"is_vip": true
},
{
"id": "7283154062273465612",
"title": "国庆旅行-手绘紫",
"is_vip": true
},
{
"id": "7312021669739007232",
"title": "紫色格子花字",
"is_vip": true
},
{
"id": "7254765522745675046",
"title": "可爱莫兰迪粉紫花字",
"is_vip": true
},
{
"id": "7400682062262406426",
"title": "白色斑点透明字体",
"is_vip": true
},
{
"id": "7430746445961022759",
"title": "紫色花字",
"is_vip": true
},
{
"id": "7231693783568551208",
"title": "浅紫星空花字",
"is_vip": true
},
{
"id": "7265651955123359011",
"title": "粉紫纯色花字",
"is_vip": true
},
{
"id": "7231341416465714490",
"title": "紫色格子立体花字",
"is_vip": true
},
{
"id": "7231001538473233723",
"title": "圆点浅紫花字",
"is_vip": true
},
{
"id": "7020634468826238244",
"title": "潮酷 黑色紫光",
"is_vip": false
},
{
"id": "6927160254996172047",
"title": "可爱紫色立体花字",
"is_vip": false
},
{
"id": "6926825801383939336",
"title": "清新白色蓝色描边花字",
"is_vip": false
},
{
"id": "6896144127935696136",
"title": "紫色渐变立体花字",
"is_vip": false
},
{
"id": "6896137661153643784",
"title": "梦幻渐变紫边白色发光花字",
"is_vip": false
},
{
"id": "6926827744189828359",
"title": "潮酷紫色闪闪花字",
"is_vip": false
},
{
"id": "6896143915192306958",
"title": "清新紫色立体字",
"is_vip": false
},
{
"id": "7127655008715279647",
"title": "蓝紫渐变花字",
"is_vip": false
},
{
"id": "6896144180993625357",
"title": "紫色投影立体字",
"is_vip": false
},
{
"id": "6896137727012506887",
"title": "清新粉紫色立体花字",
"is_vip": false
}
]
================================================
FILE: config/sticker.json
================================================
[File too large to display: 58.3 MB]
================================================
FILE: config.py
================================================
# 项目常量定义
import os
# 项目根目录
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
# 保存剪映草稿的目录
DRAFT_DIR = os.path.join(PROJECT_ROOT, "output", "draft")
# 日志目录
LOG_DIR = os.path.join(PROJECT_ROOT, "logs")
# 临时文件目录
TEMP_DIR = os.path.join(PROJECT_ROOT, "temp")
# 视频生成任务完成结果(SQLite 持久化)
VIDEO_GEN_TASK_DB_PATH = os.path.join(PROJECT_ROOT, "db", "video_gen_tasks.sqlite3")
# 视频生成任务:生成视频在 COS 上的可访问保留天数(预签名下载 URL 有效期,环境变量覆盖)
VIDEO_GEN_RETENTION_DAYS = max(1, int(os.getenv("VIDEO_GEN_RETENTION_DAYS", "7")))
# 剪映草稿的下载路径
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/")
# 贴纸配置文件路径
STICKER_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config", "sticker.json")
# 花字配置文件路径
HUAZI_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config", "huazi.json")
# 模板目录路径
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "template")
# 剪映草稿保存路径(下载剪映草稿保存位置)-- 云渲染必需配置
#DRAFT_SAVE_PATH = "C:/Users/Administrator/AppData/Local/JianyingPro/User Data/Projects/com.lveditor.draft"
DRAFT_SAVE_PATH = "C:/Users/1/AppData/Local/JianyingPro/User Data/Projects/com.lveditor.draft"
# 腾讯云对象存储配置(优先)
COS_SECRET_ID = os.getenv("COS_SECRET_ID", "")
COS_SECRET_KEY = os.getenv("COS_SECRET_KEY", "")
COS_BUCKET_NAME = os.getenv("COS_BUCKET_NAME", "")
COS_REGION = os.getenv("COS_REGION", "")
# 阿里云对象存储配置(COS 未配置时作为兜底)
OSS_ACCESS_KEY_ID = os.getenv("OSS_ACCESS_KEY_ID", "")
OSS_ACCESS_KEY_SECRET = os.getenv("OSS_ACCESS_KEY_SECRET", "")
OSS_BUCKET_NAME = os.getenv("OSS_BUCKET_NAME", "")
OSS_ENDPOINT = os.getenv("OSS_ENDPOINT", "")
# APIKEY启用配置-默认启用 -- 云渲染必需配置(环境变量 true / false,大小写不敏感)
ENABLE_APIKEY = os.getenv("ENABLE_APIKEY", "true").strip().lower() == "true"
# 文件下载大小限制(字节),默认200MB
DOWNLOAD_FILE_SIZE_LIMIT = int(os.getenv("DOWNLOAD_FILE_SIZE_LIMIT", str(200 * 1024 * 1024)))
================================================
FILE: desktop-client/.gitignore
================================================
/node_modules
/dist
/ui
/logs
app-config.json
download-log.json
/.vscode
.DS_Store
.env
.env.local
.env.*.local
/coverage
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
.vscode-test
.idea
*.sublime-workspace
*.sublime-project
*.log
================================================
FILE: desktop-client/.npmrc
================================================
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/
================================================
FILE: desktop-client/LICENSE
================================================
MIT License
Copyright (c) 2025 gogoshine
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: desktop-client/assets/entitlements.mac.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Enable app sandbox -->
<key>com.apple.security.app-sandbox</key>
<true/>
<!-- File access permissions -->
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<!-- Access to user's Downloads folder -->
<key>com.apple.security.files.downloads.read-write</key>
<true/>
<!-- Access to user's Documents folder -->
<key>com.apple.security.files.documents.read-write</key>
<true/>
<!-- Access to user's Pictures folder -->
<key>com.apple.security.files.pictures.read-write</key>
<true/>
<!-- Access to user's Music folder -->
<key>com.apple.security.files.music.read-write</key>
<true/>
<!-- Access to user's Movies folder -->
<key>com.apple.security.files.movies.read-write</key>
<true/>
<!-- Network access -->
<key>com.apple.security.network.client</key>
<true/>
<!-- Hardware access for media files -->
<key>com.apple.security.device.audio-input</key>
<false/>
<key>com.apple.security.device.camera</key>
<false/>
</dict>
</plist>
================================================
FILE: desktop-client/main.js
================================================
const { app, BrowserWindow, dialog, shell } = require('electron');
const path = require('path');
const logger = require('./nodeapi/logger');
// 引入IPC处理程序模块
const { setupIpcHandlers } = require('./nodeapi/ipcHandlers');
let mainWindow;
let ipcHandlersInitialized = false;
function createWindow() {
// 避免重复创建窗口
if (mainWindow) {
mainWindow.show();
return mainWindow;
}
// 根据平台选择合适的图标格式
let iconPath;
if (process.platform === 'darwin') {
iconPath = path.join(__dirname, './assets/icons/logo.icns');
} else if (process.platform === 'win32') {
iconPath = path.join(__dirname, './assets/icons/logo.ico');
} else {
iconPath = path.join(__dirname, './assets/icons/logo.png');
}
mainWindow = new BrowserWindow({
width: 1366,
height: 868,
icon: iconPath,
show: false, // 创建窗口但先隐藏,等页面加载完成后再显示
webPreferences: {
nodeIntegration: false, // 禁用 Node.js 集成(出于安全考虑,强烈推荐)
contextIsolation: true, // 启用上下文隔离(Electron 12 后默认 true,推荐开启)
preload: path.join(__dirname, 'preload.js'), // 指定预加载脚本的绝对路径
// webSecurity: false, // 禁用web安全策略(可选,根据需求调整)
disableBlinkFeatures: 'OutOfBlinkCors', // 禁用某些Blink特性以提高性能
hardwareAcceleration: true // 启用硬件加速
}
});
// 在 macOS 上设置 Dock 图标
if (process.platform === 'darwin') {
app.dock.setIcon(path.join(__dirname, './assets/icons/logo.png'));
}
// 判断是否为开发模式
const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged;
// 加载React应用
if (isDev) {
// 开发模式下加载本地web服务
mainWindow.loadURL('http://localhost:9000');
// 开发模式下打开开发者工具
mainWindow.webContents.openDevTools();
} else {
// 生产模式下加载构建后的文件
mainWindow.loadFile(path.join(__dirname, 'ui', 'index.html'));
}
// 当页面加载完成后显示窗口
mainWindow.webContents.on('ready-to-show', () => {
mainWindow.show();
});
// 只初始化一次IPC处理程序
if (!ipcHandlersInitialized) {
setupIpcHandlers(mainWindow);
ipcHandlersInitialized = true;
}
mainWindow.on('closed', function () {
mainWindow = null;
});
return mainWindow;
}
// 处理未捕获的异常,特别是与文件权限相关的错误
process.on('uncaughtException', (error) => {
logger.error('未捕获的异常:', error);
// 在 macOS 沙箱环境下,某些权限错误可能在这里捕获
if (process.platform === 'darwin' && error.message &&
(error.message.includes('Operation not permitted') || error.message.includes('EPERM'))) {
dialog.showMessageBoxSync({
type: 'error',
title: '权限错误',
message: '应用缺少必要的文件访问权限,请检查系统偏好设置中的隐私与安全性设置。',
detail: '请在 系统偏好设置 > 安全性与隐私 > 隐私 > 文件夹访问 中允许本应用访问相关文件夹。',
buttons: ['确定']
});
}
});
// 判断是否为需要外跳系统浏览器的外部链接
function isExternalUrl(url) {
return url && (url.startsWith('http://') || url.startsWith('https://'));
}
// 全局拦截所有 webContents 的新窗口打开行为
app.on('web-contents-created', (event, contents) => {
contents.setWindowOpenHandler(({ url }) => {
if (isExternalUrl(url)) {
shell.openExternal(url);
return { action: 'deny' };
}
return { action: 'allow' };
});
});
// 兜底:任何新窗口被创建时直接销毁并甩到系统浏览器
app.on('browser-window-created', (event, window) => {
// 用 getAllWindows 判断:如果当前只有这一个窗口,说明是主窗口,放过
if (BrowserWindow.getAllWindows().length === 1) return;
// 检测不是外部链接则放过
const url = window.webContents.getURL();
if (!isExternalUrl(url)) return;
window.webContents.once('did-finish-load', () => {
shell.openExternal(url);
window.destroy();
});
});
// 当Electron完成初始化并准备创建浏览器窗口时调用此方法
app.whenReady().then(() => {
createWindow();
});
// 当所有窗口都关闭时退出应用
app.on('window-all-closed', () => {
// 在macOS上,应用及其菜单栏通常保持活动状态,直到用户使用Cmd + Q明确退出
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// 在macOS上,当单击dock图标时,如果没有任何窗口打开则创建一个,
// 否则显示已存在的窗口
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
} else {
// 如果已有窗口,确保它被显示和聚焦
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
}
});
================================================
FILE: desktop-client/nodeapi/download.js
================================================
const path = require("path");
const axios = require("axios");
const { app, dialog, shell } = require("electron");
const { createWriteStream } = require("fs");
const fs = require("fs").promises; // 使用 fs.promises 进行异步文件操作
const logger = require("./logger");
const { detectJianyingDraftRoot } = require("./draftPathDetect");
const { v4: uuidv4 } = require('uuid');
const RECORD_MAX = 500;
const LOG_MAX = 2000;
const axiosConfig = {
method: "GET",
timeout: 30000, // 30秒超时
headers: {
// 添加常见的浏览器User-Agent
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
},
};
function isHttpUrl(value) {
if (!value || typeof value !== "string") return false;
try {
const parsed = new URL(value);
return parsed.protocol === "http:" || parsed.protocol === "https:";
} catch {
return false;
}
}
function inferMaterialSubDir(materialType, material) {
if (materialType === "audios") return "audios";
if (materialType === "videos") {
return material?.type === "photo" ? "images" : "videos";
}
return "misc";
}
function getFileExtFromUrl(url, fallbackExt = ".bin") {
try {
const pathname = new URL(url).pathname || "";
const ext = path.extname(pathname);
return ext || fallbackExt;
} catch {
return fallbackExt;
}
}
function sanitizeFilename(value) {
if (!value || typeof value !== "string") return "";
return value.replace(/[\\/:*?"<>|]/g, "_").trim();
}
async function downloadRemoteMaterialFile(fileUrl, localPath) {
const response = await axios({
...axiosConfig,
url: fileUrl,
responseType: "stream",
});
if (response.status !== 200) {
throw new Error(`[error] [material] request failed, status code: ${response.status}`);
}
await fs.mkdir(path.dirname(localPath), { recursive: true });
const writer = response.data.pipe(createWriteStream(localPath, { flags: "w", mode: 0o666 }));
await new Promise((resolve, reject) => {
writer.on("close", resolve);
writer.on("error", (err) => {
fs.unlink(localPath).catch(() => { });
reject(err);
});
response.data.on("error", (err) => {
writer.destroy();
fs.unlink(localPath).catch(() => { });
reject(err);
});
});
}
/**
* Windows 上“权限异常”多与只读属性有关;Node 对文件的 fs.chmod(0o666) 会清除只读位。
* 下载完成后统一处理,避免 copyFile / 外部软件间歇性带上只读导致剪映无法改写素材。
*/
async function ensureWindowsDraftFilesWritable(rootDir) {
if (process.platform !== "win32" || !rootDir) return;
const stack = [rootDir];
while (stack.length) {
const current = stack.pop();
let entries;
try {
entries = await fs.readdir(current, { withFileTypes: true });
} catch {
continue;
}
for (const ent of entries) {
const full = path.join(current, ent.name);
if (ent.isSymbolicLink()) continue;
try {
if (ent.isDirectory()) {
stack.push(full);
} else if (ent.isFile()) {
await fs.chmod(full, 0o666);
}
} catch (e) {
logger.warn(`[perm] 无法调整文件权限(已跳过): ${full} — ${e.message}`);
}
}
}
}
const MAX_DOWNLOAD_ATTEMPTS = 6;
/** 拉取 get_draft:首次请求 + 2 次重试(共 3 次),自开始起硬截止 3000ms 内必须结束 */
const GET_DRAFT_FETCH_MAX_ATTEMPTS = 3;
const GET_DRAFT_FETCH_DEADLINE_MS = 3000;
const GET_DRAFT_FETCH_PER_ATTEMPT_MAX_MS = 800;
const GET_DRAFT_FETCH_BACKOFF_MS = [120, 200];
function isRetryableGetDraftError(error) {
if (!error) return false;
if (error.response) {
const status = error.response.status;
return status === 408 || status === 429 || status >= 500;
}
const code = error.code;
if (code === "ENOTFOUND" || code === "ECONNREFUSED") return false;
return true;
}
async function requestGetDraftOnce(remoteUrl, timeoutMs) {
return axios({
...axiosConfig,
url: remoteUrl,
responseType: "json",
timeout: timeoutMs,
});
}
async function fetchGetDraftWithRetry(remoteUrl) {
const deadline = Date.now() + GET_DRAFT_FETCH_DEADLINE_MS;
const timeLeftMs = () => deadline - Date.now();
let lastError = null;
for (let attempt = 1; attempt <= GET_DRAFT_FETCH_MAX_ATTEMPTS; attempt++) {
if (timeLeftMs() <= 0) break;
if (attempt > 1) {
const planned = GET_DRAFT_FETCH_BACKOFF_MS[attempt - 2] ?? 100;
const wait = Math.min(planned, Math.max(0, timeLeftMs() - 1));
if (wait > 0) {
await new Promise((resolve) => setTimeout(resolve, wait));
}
if (timeLeftMs() <= 0) break;
}
const timeout = Math.min(
GET_DRAFT_FETCH_PER_ATTEMPT_MAX_MS,
Math.max(1, timeLeftMs())
);
try {
return await requestGetDraftOnce(remoteUrl, timeout);
} catch (error) {
lastError = error;
const willRetry =
attempt < GET_DRAFT_FETCH_MAX_ATTEMPTS &&
timeLeftMs() > 0 &&
isRetryableGetDraftError(error);
if (willRetry) {
logger.warn(
`[warn] get draft url attempt ${attempt}/${GET_DRAFT_FETCH_MAX_ATTEMPTS} failed: ${error.message}`
);
continue;
}
throw error;
}
}
throw lastError;
}
async function retryDownloadTask(task, options = {}) {
const {
maxAttempts = MAX_DOWNLOAD_ATTEMPTS,
retryDelayMs = 1000,
onAttempt = null,
onRetry = null,
onExhausted = null,
} = options;
let lastError = null;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
if (typeof onAttempt === "function") {
await onAttempt(attempt, maxAttempts);
}
return await task(attempt, maxAttempts);
} catch (error) {
lastError = error;
const hasNextAttempt = attempt < maxAttempts;
if (hasNextAttempt) {
if (typeof onRetry === "function") {
await onRetry(error, attempt, maxAttempts);
}
if (retryDelayMs > 0) {
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
}
continue;
}
if (typeof onExhausted === "function") {
await onExhausted(error, attempt, maxAttempts);
}
throw error;
}
}
throw lastError || new Error("retryDownloadTask failed without explicit error");
}
async function localizeRemoteMaterialPaths(materials, draftRootDir, parentWindow, sharedCache = null) {
if (!materials || typeof materials !== "object") return;
const supportedTypes = ["videos", "audios"];
const cache = sharedCache instanceof Map ? sharedCache : new Map();
for (const materialType of supportedTypes) {
const list = materials[materialType];
if (!Array.isArray(list)) continue;
for (let i = 0; i < list.length; i++) {
const item = list[i];
if (!item || typeof item !== "object") continue;
if (!isHttpUrl(item.path)) continue;
const subDir = inferMaterialSubDir(materialType, item);
const fallbackExt = materialType === "audios" ? ".mp3" : ".mp4";
const ext = getFileExtFromUrl(item.path, fallbackExt);
const baseName = sanitizeFilename(item.material_name || item.name || item.id || uuidv4());
const fileName = baseName.toLowerCase().endsWith(ext.toLowerCase())
? baseName
: `${baseName}${ext}`;
const localPath = path.join(draftRootDir, "assets", subDir, fileName);
if (!cache.has(item.path)) {
try {
await retryDownloadTask(
async () => {
await downloadRemoteMaterialFile(item.path, localPath);
},
{
onAttempt: async (attempt) => {
const attemptMessage = attempt === 1
? `正在下载 URL 素材到本地:${fileName}`
: `正在下载 URL 素材到本地:${fileName}(第${attempt - 1}次重试)`;
await appendDownloadLog(
{
level: "loading",
message: attemptMessage,
},
parentWindow
);
},
onRetry: async (err, attempt) => {
logger.warn(
`[warn] 下载URL素材失败,准备重试(${attempt}/${MAX_DOWNLOAD_ATTEMPTS}): ${item.path}`,
err?.message || err
);
},
onExhausted: async () => {
await appendDownloadLog(
{
level: "error",
message: `URL 素材下载失败(已重试${MAX_DOWNLOAD_ATTEMPTS - 1}次,共尝试${MAX_DOWNLOAD_ATTEMPTS}次):${fileName}`,
},
parentWindow
);
},
}
);
cache.set(item.path, localPath);
} catch (err) {
// URL 素材失败不影响同一草稿内其他文件下载,保留原 URL 路径。
logger.error(`[error] 下载URL素材失败,已达到重试上限: ${item.path}`, err);
continue;
}
}
item.path = cache.get(item.path);
}
}
}
function getConfigPath() {
return path.join(app.getPath("userData"), "app-config.json");
}
async function readConfig() {
const configPath = getConfigPath();
logger.info("[log] Config path:", configPath);
try {
const data = await fs.readFile(configPath, "utf8");
return JSON.parse(data) || {};
} catch (error) {
return {};
}
}
async function writeConfig(config) {
const configPath = getConfigPath();
try {
await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf8");
return true;
} catch (error) {
logger.error("写入配置文件失败:", error);
return false;
}
}
/**
* 未配置草稿路径时,按平台规则自动探测并写入配置。
*/
async function ensureAutoDetectedDraftPathInConfig() {
let config = await readConfig();
if (config.targetDirectory) {
return config;
}
const detected = await detectJianyingDraftRoot();
if (detected) {
config.targetDirectory = detected;
await writeConfig(config);
logger.info("[draft-detect] 已自动识别剪映草稿目录:", detected);
}
return config;
}
function getDownloadLogPath() {
return path.join(app.getPath("userData"), "download-log.json");
}
async function readDownloadLog() {
const logPath = getDownloadLogPath();
logger.info("[log] Log path:", logPath);
try {
const data = await fs.readFile(logPath, "utf8");
return JSON.parse(data);
} catch (error) {
return [];
}
}
/**
*
* @param {*} entry {time: Date, level: 'error', message: '日志内容' }
*/
async function appendDownloadLog(entry, parentWindow) {
const logPath = getDownloadLogPath();
let logs = [];
try {
logs = await readDownloadLog();
} catch (error) {
// 如果文件不存在或无法读取,初始化为空数组
logs = [];
}
entry.time = new Date();
console.log(`appendDownloadLog: ${JSON.stringify(entry)}`);
await parentWindow.webContents.send("file-operation-log", entry);
logs.push(entry);
if (logs.length > LOG_MAX) {
logs.shift();
}
try {
await fs.writeFile(logPath, JSON.stringify(logs, null, 2), "utf8");
} catch (writeErr) {
logger.error("写入日志文件失败:", writeErr);
}
}
async function clearDownloadLog() {
const logPath = getDownloadLogPath();
try {
await fs.writeFile(logPath, JSON.stringify([], null, 2), "utf8");
return true;
} catch (error) {
logger.error("清空日志文件失败:", error);
return false;
}
}
function getHistoryRecordPath() {
return path.join(app.getPath("userData"), "history-record.json");
}
async function readHistoryRecord() {
const recordPath = getHistoryRecordPath();
console.info("[History] Record path:", recordPath);
try {
const data = await fs.readFile(recordPath, "utf8");
return JSON.parse(data);
} catch (error) {
return [];
}
}
/**
*
* @param {*} entry {id: 'uuid', time: Date, draft_id: 'draft_id' draft_url: 'draft_url' }
*/
async function appendHistoryRecord(entry) {
const recordPath = getHistoryRecordPath();
let records = [];
try {
records = await readHistoryRecord();
} catch (error) {
// 如果文件不存在或无法读取,初始化为空数组
records = [];
}
console.log(`appendHistoryRecord: ${JSON.stringify(entry)}`);
records.push(entry);
if (records.length > RECORD_MAX) {
records.shift();
}
try {
await fs.writeFile(recordPath, JSON.stringify(records, null, 2), "utf8");
} catch (writeErr) {
console.error("写入草稿历史记录文件失败:", writeErr);
}
}
// 更精确的错误处理
function errorHandler(error = {}, url = "") {
if (error.code === "ECONNREFUSED") {
throw new Error(`[error] not connect to server: ${url}`);
} else if (error.code === "ENOTFOUND") {
throw new Error(`[error] domain not found: ${url}`);
} else if (error.response) {
// 服务器返回了错误状态码(如4xx, 5xx)
throw new Error(`[error] server error (${error.response.status}): ${url}`);
} else {
throw error; // 重新抛出其他未知错误
}
}
async function getDraftUrls(remoteUrl, parentWindow) {
logger.info("[info] get draft url");
try {
const response = await fetchGetDraftWithRetry(remoteUrl);
// 检查HTTP状态码
if (response.status !== 200) {
await appendDownloadLog(
{ level: "error", message: `获取草稿地址信息失败` },
parentWindow
);
throw new Error(
`[error] [draft url] request failed, status code: ${response.status}`
);
}
logger.info("[success] get draft url");
return response.data;
} catch (error) {
errorHandler(error, remoteUrl);
}
}
async function updateDraftPath(parentWindow) {
const targetDir = await getTargetDirectory(parentWindow, true);
if (!targetDir) {
return { success: false, error: "用户取消了目录选择" };
}
try {
// 验证目录权限
try {
await fs.access(targetDir, fs.constants.R_OK | fs.constants.W_OK);
} catch (accessError) {
logger.error('所选目录无读写权限:', accessError);
// 尝试使用 dialog 显示错误消息
if (parentWindow) {
const { dialog } = require('electron');
await dialog.showMessageBox(parentWindow, {
type: 'error',
title: '权限不足',
message: '所选目录没有足够的读写权限,请选择其他目录。',
buttons: ['确定']
});
}
return { success: false, error: '所选目录没有足够的读写权限' };
}
const configPath = getConfigPath();
let config = {};
// 尝试读取现有配置
try {
const data = await fs.readFile(configPath, "utf8");
config = JSON.parse(data);
} catch (error) {
// 如果文件不存在,保持config为空对象
}
config.targetDirectory = targetDir;
// 写回配置文件
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf8');
logger.info('默认草稿路径已更新为:', targetDir);
return { success: true, targetDir };
} catch (error) {
logger.error('更新默认草稿路径失败:', error);
return { success: false, error: error.message };
}
}
// 提取出来的函数,可选参数parentWindow用于显示对话框时附加到对话框
async function getTargetDirectory(parentWindow = null, isUpdate = false) {
let config = await readConfig();
if (!isUpdate && config.targetDirectory) {
try {
await fs.access(config.targetDirectory, fs.constants.R_OK | fs.constants.W_OK);
return config.targetDirectory;
} catch (accessErr) {
logger.warn(
"配置的目录已不存在或无访问权限,将清除并尝试自动识别或手动选择。",
accessErr.message
);
delete config.targetDirectory;
await writeConfig(config);
}
}
if (!isUpdate) {
config = await ensureAutoDetectedDraftPathInConfig();
if (config.targetDirectory) {
try {
await fs.access(config.targetDirectory, fs.constants.R_OK | fs.constants.W_OK);
return config.targetDirectory;
} catch (e) {
logger.warn("自动识别的草稿目录不可读写,将打开目录选择:", e.message);
delete config.targetDirectory;
await writeConfig(config);
}
}
}
const dialogOptions = {
properties: ["openDirectory", "createDirectory"], // 允许创建新目录
title: "请选择目标目录",
buttonLabel: "选择此目录",
defaultPath: isUpdate ? config.targetDirectory : undefined
};
// 如果有父窗口,则附加到父窗口
if (parentWindow) {
dialogOptions.window = parentWindow;
}
const result = await dialog.showOpenDialog(dialogOptions);
if (!result.canceled && result.filePaths.length > 0) {
const selectedDir = result.filePaths[0];
// 再次验证目录权限
try {
await fs.access(selectedDir, fs.constants.R_OK | fs.constants.W_OK);
} catch (accessErr) {
logger.error('所选目录无读写权限:', accessErr);
if (parentWindow) {
const { dialog } = require('electron');
await dialog.showMessageBox(parentWindow, {
type: 'error',
title: '权限不足',
message: '所选目录没有足够的读写权限,请重新选择。',
buttons: ['确定']
});
}
return ''; // 返回空字符串表示失败
}
config.targetDirectory = selectedDir;
await writeConfig(config);
return selectedDir;
} else {
return '';
}
}
function updateValue(current, finalKey, targetDir, oldVal, targetId) {
if (oldVal) {
// 找到ID在路径中的位置
const idIndex = oldVal.indexOf(targetId);
if (idIndex === -1) return;
// 提取ID及之后的部分作为将要下载的路径
const relativePath = oldVal.substring(idIndex).replaceAll("/", path.sep); // 替换为系统路径分隔符
// targetDir 已包含 targetId 目录,所以relativePath中的targetId要去重
const newRelativePath = relativePath.replace(`${targetId}${path.sep}`, "");
const newValue = path.join(targetDir, newRelativePath);
current[finalKey] = newValue;
logger.info(`✅ newValue to:`, newValue);
}
}
// 递归遍历对象,更新所有名为path的属性
function recursivelyUpdatePaths(obj, targetDir, targetId) {
// 处理数组
if (Array.isArray(obj)) {
obj.forEach((item) => {
recursivelyUpdatePaths(item, targetDir, targetId);
});
return;
}
// 处理对象
if (obj && typeof obj === "object") {
// 检查是否有path属性
if (obj.path && typeof obj.path === "string") {
updateValue(obj, "path", targetDir, obj.path, targetId);
}
// 递归处理所有属性
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
recursivelyUpdatePaths(obj[key], targetDir, targetId);
}
}
}
}
// 带错误处理的JSON文件下载
async function downloadJsonFile(
{ fileUrl, filePath, targetDir, targetId, materialDownloadCache },
parentWindow
) {
// 1. 使用 Axios 下载 JSON 文件
try {
const response = await axios({
method: "GET",
url: fileUrl,
responseType: "json", // 直接告诉 Axios 解析 JSON
});
// 检查HTTP状态码
if (response.status !== 200) {
await appendDownloadLog(
{ level: "error", message: `下载草稿内容文件失败` },
parentWindow
);
throw new Error(
`[error] [json] request failed, status code: ${response.status}`
);
}
// 2. 解析获取到的数据(Axios 会根据 responseType: 'json' 自动解析)
const jsonData = response.data;
// 3. 修改 JSON 数据中指定键的值
if (jsonData?.materials) {
logger.info(`[log] start modifyJsonValue: materials`);
recursivelyUpdatePaths(jsonData.materials, targetDir, targetId);
// 当素材 path 为 URL 时,下载到本地并回写为本地路径。
await localizeRemoteMaterialPaths(
jsonData.materials,
targetDir,
parentWindow,
materialDownloadCache
);
}
await appendDownloadLog(
{
level: "loading",
message: `正在将草稿内容文件写入本地草稿目录 ${targetDir}`,
},
parentWindow
);
// 4. 将修改后的 JSON 对象转换为格式化的字符串并写入本地文件
const jsonString = JSON.stringify(jsonData, null, 2); // 使用 2 个空格进行缩进,美化输出
await fs.writeFile(filePath, jsonString, { encoding: "utf8", mode: 0o666 });
} catch (error) {
logger.error(`下载JSON文件失败: ${fileUrl}`, error);
throw error;
}
}
async function downloadNotJsonFile(
{ fileUrl, filePath, targetDir },
parentWindow
) {
try {
// 1. 使用 Axios 下载非 JSON 文件
const response = await axios({
...axiosConfig,
url: fileUrl,
responseType: "stream", // 设置响应类型为 'stream' 以处理大文件
});
// 检查HTTP状态码
if (response.status
gitextract_66uhurkx/
├── .github/
│ └── workflows/
│ ├── desktop-client-dev.yml
│ └── dev.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── README.zh.md
├── config/
│ ├── huazi.json
│ └── sticker.json
├── config.py
├── desktop-client/
│ ├── .gitignore
│ ├── .npmrc
│ ├── LICENSE
│ ├── assets/
│ │ ├── entitlements.mac.plist
│ │ └── icons/
│ │ └── logo.icns
│ ├── main.js
│ ├── nodeapi/
│ │ ├── download.js
│ │ ├── draftPathDetect.js
│ │ ├── ipcHandlers.js
│ │ └── logger.js
│ ├── package.json
│ ├── preload.js
│ ├── scripts/
│ │ ├── electron-builder-green.config.js
│ │ ├── electron-builder.config.js
│ │ └── update-version.js
│ └── web/
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── public/
│ │ └── index.html
│ ├── src/
│ │ ├── App.jsx
│ │ ├── components/
│ │ │ ├── DownloadButton.jsx
│ │ │ ├── DownloadControls.jsx
│ │ │ ├── ExternalWebpage.jsx
│ │ │ ├── Header/
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ │ ├── LogModule.jsx
│ │ │ ├── Tabs.jsx
│ │ │ └── Textarea.jsx
│ │ ├── index.jsx
│ │ ├── pages/
│ │ │ ├── ConfigCenter/
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ │ ├── Download/
│ │ │ │ ├── index.jsx
│ │ │ │ └── index.less
│ │ │ └── History/
│ │ │ ├── index.jsx
│ │ │ └── index.less
│ │ ├── services/
│ │ │ └── electronService.js
│ │ ├── styles/
│ │ │ ├── index.less
│ │ │ └── root.less
│ │ └── utils/
│ │ ├── const.tsx
│ │ └── date.ts
│ └── vite.config.js
├── docker-compose.example.yaml
├── docker-compose.yaml
├── docs/
│ ├── add_audios.md
│ ├── add_audios.zh.md
│ ├── add_captions.md
│ ├── add_captions.zh.md
│ ├── add_effects.md
│ ├── add_effects.zh.md
│ ├── add_filters.md
│ ├── add_filters.zh.md
│ ├── add_images.md
│ ├── add_images.zh.md
│ ├── add_keyframes.md
│ ├── add_keyframes.zh.md
│ ├── add_masks.md
│ ├── add_masks.zh.md
│ ├── add_sticker.md
│ ├── add_sticker.zh.md
│ ├── add_text_style.md
│ ├── add_text_style.zh.md
│ ├── add_videos.md
│ ├── add_videos.zh.md
│ ├── audio_infos.md
│ ├── audio_infos.zh.md
│ ├── audio_timelines.md
│ ├── audio_timelines.zh.md
│ ├── caption_infos.md
│ ├── caption_infos.zh.md
│ ├── create_draft.md
│ ├── create_draft.zh.md
│ ├── easy_create_material.md
│ ├── easy_create_material.zh.md
│ ├── effect_infos.md
│ ├── effect_infos.zh.md
│ ├── filter_infos.md
│ ├── filter_infos.zh.md
│ ├── gen_video.md
│ ├── gen_video.zh.md
│ ├── gen_video_status.md
│ ├── gen_video_status.zh.md
│ ├── get_audio_duration.md
│ ├── get_audio_duration.zh.md
│ ├── get_draft.md
│ ├── get_draft.zh.md
│ ├── get_image_animations.md
│ ├── get_image_animations.zh.md
│ ├── get_text_animations.md
│ ├── get_text_animations.zh.md
│ ├── get_text_effects.md
│ ├── get_url.md
│ ├── get_url.zh.md
│ ├── imgs_infos.md
│ ├── imgs_infos.zh.md
│ ├── keyframes_infos.md
│ ├── keyframes_infos.zh.md
│ ├── objs_to_str_list.md
│ ├── objs_to_str_list.zh.md
│ ├── save_draft.md
│ ├── save_draft.zh.md
│ ├── search_sticker.md
│ ├── search_sticker.zh.md
│ ├── str_list_to_objs.md
│ ├── str_list_to_objs.zh.md
│ ├── str_to_list.md
│ ├── str_to_list.zh.md
│ ├── timelines.md
│ ├── timelines.zh.md
│ ├── video_infos.md
│ └── video_infos.zh.md
├── exceptions.py
├── main.py
├── openapi.yaml
├── pyproject.toml
├── src/
│ ├── __init__.py
│ ├── middlewares/
│ │ ├── __init__.py
│ │ ├── prepare.py
│ │ ├── response.py
│ │ └── trace_context.py
│ ├── pyJianYingDraft/
│ │ ├── __init__.py
│ │ ├── animation.py
│ │ ├── assets/
│ │ │ ├── __init__.py
│ │ │ ├── draft_content_template.json
│ │ │ └── draft_meta_info.json
│ │ ├── audio_segment.py
│ │ ├── draft_folder.py
│ │ ├── effect_segment.py
│ │ ├── exceptions.py
│ │ ├── jianying_controller.py
│ │ ├── keyframe.py
│ │ ├── local_materials.py
│ │ ├── metadata/
│ │ │ ├── __init__.py
│ │ │ ├── audio_scene_effect.py
│ │ │ ├── effect_meta.py
│ │ │ ├── filter_meta.py
│ │ │ ├── font_meta.py
│ │ │ ├── mask_meta.py
│ │ │ ├── mix_mode_meta.py
│ │ │ ├── speech_to_song.py
│ │ │ ├── text_intro.py
│ │ │ ├── text_loop.py
│ │ │ ├── text_outro.py
│ │ │ ├── tone_effect.py
│ │ │ ├── transition_meta.py
│ │ │ ├── video_character_effect.py
│ │ │ ├── video_group_animation.py
│ │ │ ├── video_intro.py
│ │ │ ├── video_outro.py
│ │ │ └── video_scene_effect.py
│ │ ├── script_file.py
│ │ ├── segment.py
│ │ ├── template_mode.py
│ │ ├── text_segment.py
│ │ ├── time_util.py
│ │ ├── track.py
│ │ ├── util.py
│ │ └── video_segment.py
│ ├── router/
│ │ ├── __init__.py
│ │ └── v1.py
│ ├── schemas/
│ │ ├── __init__.py
│ │ ├── add_audios.py
│ │ ├── add_captions.py
│ │ ├── add_effects.py
│ │ ├── add_filters.py
│ │ ├── add_images.py
│ │ ├── add_keyframes.py
│ │ ├── add_masks.py
│ │ ├── add_sticker.py
│ │ ├── add_text_style.py
│ │ ├── add_videos.py
│ │ ├── audio_infos.py
│ │ ├── audio_timelines.py
│ │ ├── caption_infos.py
│ │ ├── create_draft.py
│ │ ├── easy_create_material.py
│ │ ├── effect_infos.py
│ │ ├── filter_infos.py
│ │ ├── gen_video.py
│ │ ├── gen_video_active_count.py
│ │ ├── gen_video_status.py
│ │ ├── get_audio_duration.py
│ │ ├── get_draft.py
│ │ ├── get_effects.py
│ │ ├── get_filters.py
│ │ ├── get_image_animations.py
│ │ ├── get_text_animations.py
│ │ ├── get_text_effects.py
│ │ ├── get_url.py
│ │ ├── imgs_infos.py
│ │ ├── keyframes_infos.py
│ │ ├── objs_to_str_list.py
│ │ ├── save_draft.py
│ │ ├── search_sticker.py
│ │ ├── str_list_to_objs.py
│ │ ├── str_to_list.py
│ │ ├── timelines.py
│ │ └── video_infos.py
│ ├── service/
│ │ ├── __init__.py
│ │ ├── add_audios.py
│ │ ├── add_captions.py
│ │ ├── add_effects.py
│ │ ├── add_filters.py
│ │ ├── add_images.py
│ │ ├── add_keyframes.py
│ │ ├── add_masks.py
│ │ ├── add_sticker.py
│ │ ├── add_text_style.py
│ │ ├── add_videos.py
│ │ ├── audio_infos.py
│ │ ├── audio_timelines.py
│ │ ├── caption_infos.py
│ │ ├── create_draft.py
│ │ ├── easy_create_material.py
│ │ ├── effect_infos.py
│ │ ├── filter_infos.py
│ │ ├── gen_video.py
│ │ ├── get_audio_duration.py
│ │ ├── get_draft.py
│ │ ├── get_effects.py
│ │ ├── get_filters.py
│ │ ├── get_image_animations.py
│ │ ├── get_text_animations.py
│ │ ├── get_text_effects.py
│ │ ├── get_url.py
│ │ ├── imgs_infos.py
│ │ ├── keyframes_infos.py
│ │ ├── objs_to_str_list.py
│ │ ├── save_draft.py
│ │ ├── search_sticker.py
│ │ ├── str_list_to_objs.py
│ │ ├── str_to_list.py
│ │ ├── text_effect_map_generated.py
│ │ ├── timelines.py
│ │ └── video_infos.py
│ └── utils/
│ ├── __init__.py
│ ├── cos.py
│ ├── download.py
│ ├── draft_cache.py
│ ├── draft_cleanup.py
│ ├── draft_downloader.py
│ ├── draft_lock_manager.py
│ ├── helper.py
│ ├── keyframe_value.py
│ ├── logger.py
│ ├── media.py
│ ├── oss.py
│ ├── points.py
│ ├── storage_upload_retry.py
│ ├── trace_context.py
│ ├── upload_file.py
│ ├── video_task_manager.py
│ └── video_task_store.py
├── template/
│ ├── default/
│ │ ├── draft_agency_config.json
│ │ ├── draft_info.json
│ │ ├── draft_info.json.bak
│ │ ├── draft_meta_info.json
│ │ ├── draft_settings
│ │ └── template.tmp
│ ├── default2/
│ │ ├── attachment_pc_common.json
│ │ ├── draft_agency_config.json
│ │ ├── draft_content.json
│ │ ├── draft_info.json
│ │ ├── draft_meta_info.json
│ │ └── template.tmp
│ └── readme.md
├── tests/
│ ├── __init__.py
│ ├── manual_test_audio_infos.py
│ ├── manual_test_caption_infos.py
│ ├── manual_test_effect_infos.py
│ ├── manual_test_imgs_infos.py
│ ├── manual_test_keyframes_infos.py
│ ├── manual_test_video_infos.py
│ ├── test_add_audios.py
│ ├── test_add_captions_text_effect.py
│ ├── test_add_images.py
│ ├── test_add_keyframes_normalize.py
│ ├── test_add_keyframes_refactor.py
│ ├── test_add_masks.py
│ ├── test_add_videos_concurrent.py
│ ├── test_add_videos_concurrent_demo.py
│ ├── test_add_videos_duration.py
│ ├── test_add_videos_refactor.py
│ ├── test_all_text_effects.py
│ ├── test_api_version.py
│ ├── test_audio_infos.py
│ ├── test_audio_infos_simple.py
│ ├── test_audio_timelines.py
│ ├── test_caption_keywords.py
│ ├── test_caption_transform.py
│ ├── test_caption_transform_fix.py
│ ├── test_chinese_encoding_fix.py
│ ├── test_ci_dependencies.py
│ ├── test_cross_platform.py
│ ├── test_draft_cleanup.py
│ ├── test_draft_downloader_remote_materials.py
│ ├── test_draft_lock_all_apis.py
│ ├── test_draft_lock_manager.py
│ ├── test_draft_service.py
│ ├── test_export_error_handling.py
│ ├── test_file_operations.py
│ ├── test_float_transform.py
│ ├── test_font_alias_resolution.py
│ ├── test_font_size.py
│ ├── test_font_size_debug.py
│ ├── test_font_size_logic.py
│ ├── test_font_size_not_set.py
│ ├── test_get_audio_duration_api.py
│ ├── test_get_text_effects.py
│ ├── test_imgs_infos_multiple_animations.py
│ ├── test_keyframe_value.py
│ ├── test_keyword_font_size.py
│ ├── test_latest_commit_features.py
│ ├── test_logic_validation.py
│ ├── test_media_utils.py
│ ├── test_middleware.py
│ ├── test_param_pass.py
│ ├── test_parse_video_data.py
│ ├── test_search_sticker.py
│ ├── test_search_sticker_basic.py
│ ├── test_search_sticker_simple.py
│ ├── test_storage_upload_retry.py
│ ├── test_text_segment_add_animation.py
│ ├── test_transform_coordinate_fix.py
│ ├── test_upload_file.py
│ ├── test_video_duration_extension.py
│ ├── test_video_task_draft_duration.py
│ ├── test_video_transform.py
│ ├── test_video_transform_fix.py
│ └── verify_get_text_effects_api.py
└── tools/
├── extract_text_effects.py
├── ffprobe
└── query_sticker.py
SYMBOL INDEX (1154 symbols across 211 files)
FILE: desktop-client/main.js
function createWindow (line 11) | function createWindow() {
function isExternalUrl (line 98) | function isExternalUrl(url) {
FILE: desktop-client/nodeapi/download.js
constant RECORD_MAX (line 10) | const RECORD_MAX = 500;
constant LOG_MAX (line 12) | const LOG_MAX = 2000;
function isHttpUrl (line 24) | function isHttpUrl(value) {
function inferMaterialSubDir (line 34) | function inferMaterialSubDir(materialType, material) {
function getFileExtFromUrl (line 42) | function getFileExtFromUrl(url, fallbackExt = ".bin") {
function sanitizeFilename (line 52) | function sanitizeFilename(value) {
function downloadRemoteMaterialFile (line 57) | async function downloadRemoteMaterialFile(fileUrl, localPath) {
function ensureWindowsDraftFilesWritable (line 86) | async function ensureWindowsDraftFilesWritable(rootDir) {
constant MAX_DOWNLOAD_ATTEMPTS (line 113) | const MAX_DOWNLOAD_ATTEMPTS = 6;
constant GET_DRAFT_FETCH_MAX_ATTEMPTS (line 116) | const GET_DRAFT_FETCH_MAX_ATTEMPTS = 3;
constant GET_DRAFT_FETCH_DEADLINE_MS (line 117) | const GET_DRAFT_FETCH_DEADLINE_MS = 3000;
constant GET_DRAFT_FETCH_PER_ATTEMPT_MAX_MS (line 118) | const GET_DRAFT_FETCH_PER_ATTEMPT_MAX_MS = 800;
constant GET_DRAFT_FETCH_BACKOFF_MS (line 119) | const GET_DRAFT_FETCH_BACKOFF_MS = [120, 200];
function isRetryableGetDraftError (line 121) | function isRetryableGetDraftError(error) {
function requestGetDraftOnce (line 132) | async function requestGetDraftOnce(remoteUrl, timeoutMs) {
function fetchGetDraftWithRetry (line 141) | async function fetchGetDraftWithRetry(remoteUrl) {
function retryDownloadTask (line 184) | async function retryDownloadTask(task, options = {}) {
function localizeRemoteMaterialPaths (line 222) | async function localizeRemoteMaterialPaths(materials, draftRootDir, pare...
function getConfigPath (line 292) | function getConfigPath() {
function readConfig (line 296) | async function readConfig() {
function writeConfig (line 307) | async function writeConfig(config) {
function ensureAutoDetectedDraftPathInConfig (line 321) | async function ensureAutoDetectedDraftPathInConfig() {
function getDownloadLogPath (line 335) | function getDownloadLogPath() {
function readDownloadLog (line 339) | async function readDownloadLog() {
function appendDownloadLog (line 354) | async function appendDownloadLog(entry, parentWindow) {
function clearDownloadLog (line 378) | async function clearDownloadLog() {
function getHistoryRecordPath (line 389) | function getHistoryRecordPath() {
function readHistoryRecord (line 393) | async function readHistoryRecord() {
function appendHistoryRecord (line 408) | async function appendHistoryRecord(entry) {
function errorHandler (line 431) | function errorHandler(error = {}, url = "") {
function getDraftUrls (line 444) | async function getDraftUrls(remoteUrl, parentWindow) {
function updateDraftPath (line 466) | async function updateDraftPath(parentWindow) {
function getTargetDirectory (line 514) | async function getTargetDirectory(parentWindow = null, isUpdate = false) {
function updateValue (line 586) | function updateValue(current, finalKey, targetDir, oldVal, targetId) {
function recursivelyUpdatePaths (line 604) | function recursivelyUpdatePaths(obj, targetDir, targetId) {
function downloadJsonFile (line 630) | async function downloadJsonFile(
function downloadNotJsonFile (line 686) | async function downloadNotJsonFile(
function downloadSingleFile (line 748) | async function downloadSingleFile(config, parentWindow) {
function triggerDirectoryScan (line 782) | async function triggerDirectoryScan(targetDir) {
function openDraftDirectory (line 846) | async function openDraftDirectory(dirPath) {
function getTargetFilePath (line 862) | async function getTargetFilePath(fileUrl, baseTargetDir, targetId) {
function downloadFileWithRetry (line 891) | async function downloadFileWithRetry(config, parentWindow, fileIndex) {
function downloadFiles (line 949) | async function downloadFiles(
function checkUrlAccessRight (line 1069) | async function checkUrlAccessRight(url) {
FILE: desktop-client/nodeapi/draftPathDetect.js
constant DRAFT_REL_WIN (line 7) | const DRAFT_REL_WIN = path.join(
function isConfirmedJianyingDraftDir (line 19) | async function isConfirmedJianyingDraftDir(dir) {
function detectWindowsDraftPath (line 41) | async function detectWindowsDraftPath() {
function detectMacDraftPath (line 78) | async function detectMacDraftPath() {
function detectJianyingDraftRoot (line 94) | async function detectJianyingDraftRoot() {
FILE: desktop-client/nodeapi/ipcHandlers.js
function setupIpcHandlers (line 25) | function setupIpcHandlers(mainWindow) {
FILE: desktop-client/web/src/App.jsx
function App (line 22) | function App() {
FILE: desktop-client/web/src/components/DownloadButton.jsx
function DownloadButton (line 2) | function DownloadButton({ onClick, isLoading, setIsLoading, textValue }) {
FILE: desktop-client/web/src/components/DownloadControls.jsx
function DownloadControls (line 1) | function DownloadControls({ isOpen, onToggle, isLoading }) {
FILE: desktop-client/web/src/components/ExternalWebpage.jsx
function ExternalWebpage (line 7) | function ExternalWebpage() {
FILE: desktop-client/web/src/components/Header/index.jsx
function TopHeader (line 6) | function TopHeader({ onTabChange, selectedTab }) {
FILE: desktop-client/web/src/components/LogModule.jsx
function LogModule (line 4) | function LogModule({ logs, onClear }) {
FILE: desktop-client/web/src/components/Tabs.jsx
function Tabs (line 3) | function Tabs({ onTabChange, initialContent }) {
FILE: desktop-client/web/src/components/Textarea.jsx
function Textarea (line 3) | function Textarea({ value, onChange }) {
FILE: desktop-client/web/src/pages/Download/index.jsx
function MainPage (line 13) | function MainPage() {
FILE: desktop-client/web/src/pages/History/index.jsx
function HistoryPage (line 23) | function HistoryPage() {
FILE: desktop-client/web/src/utils/const.tsx
constant THEME_COLOR (line 5) | const THEME_COLOR = "#5c89ff";
FILE: desktop-client/web/src/utils/date.ts
constant DATE_TIME_FORMAT (line 9) | const DATE_TIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
constant DATE_TIME_MIN_FORMAT (line 10) | const DATE_TIME_MIN_FORMAT = "YYYY-MM-DD HH:mm";
constant DATE_FORMAT (line 11) | const DATE_FORMAT = "YYYY-MM-DD";
constant TIME_FORMAT (line 12) | const TIME_FORMAT = "HH:mm:ss";
function formatToDateTime (line 14) | function formatToDateTime(
function formatToDateTimeMin (line 21) | function formatToDateTimeMin(
function formatToDate (line 28) | function formatToDate(
function formatToTime (line 35) | function formatToTime(
function formatToUTCDate (line 42) | function formatToUTCDate(date: ConfigType = null): string {
function toDate (line 47) | function toDate(date?: ConfigType) {
function toTimeStamp (line 52) | function toTimeStamp(date?: ConfigType) {
FILE: exceptions.py
class CustomError (line 4) | class CustomError(Enum):
method __init__ (line 62) | def __init__(self, code: int, cn_message: str, en_message: str) -> None:
method as_dict (line 67) | def as_dict(self, detail: str = "", lang: str = 'zh') -> dict:
class CustomException (line 76) | class CustomException(Exception):
method __init__ (line 78) | def __init__(self, err: CustomError, detail: str = "") -> None:
FILE: main.py
function lifespan (line 12) | async def lifespan(app: FastAPI):
FILE: src/middlewares/prepare.py
class PrepareMiddleware (line 8) | class PrepareMiddleware(BaseHTTPMiddleware):
method dispatch (line 15) | async def dispatch(self, request: Request, call_next):
FILE: src/middlewares/response.py
class ResponseMiddleware (line 9) | class ResponseMiddleware(BaseHTTPMiddleware):
method dispatch (line 16) | async def dispatch(self, request: Request, call_next):
method _get_language_from_request (line 39) | def _get_language_from_request(self, request: Request) -> str:
method _handle_422_error (line 64) | def _handle_422_error(self, body_str: str, lang: str) -> JSONResponse:
method _handle_non_200_response (line 91) | async def _handle_non_200_response(self, response, lang: str) -> JSONR...
method _is_json_response (line 113) | def _is_json_response(self, response) -> bool:
method _process_json_response (line 117) | async def _process_json_response(self, response, lang: str):
method _handle_custom_exception (line 148) | def _handle_custom_exception(self, e: CustomException, lang: str) -> J...
method _handle_generic_exception (line 157) | def _handle_generic_exception(self, e: Exception, lang: str) -> JSONRe...
FILE: src/middlewares/trace_context.py
class TraceContextMiddleware (line 11) | class TraceContextMiddleware(BaseHTTPMiddleware):
method dispatch (line 17) | async def dispatch(self, request: Request, call_next) -> Response:
FILE: src/pyJianYingDraft/__init__.py
function _deprecated_class_warning (line 41) | def _deprecated_class_warning(old_name: str, new_name: str):
class Script_file (line 50) | class Script_file:
method __new__ (line 52) | def __new__(cls, *args, **kwargs):
class Draft_folder (line 56) | class Draft_folder:
method __new__ (line 58) | def __new__(cls, *args, **kwargs):
class Shrink_mode (line 62) | class Shrink_mode:
method __new__ (line 64) | def __new__(cls, *args, **kwargs):
class Extend_mode (line 68) | class Extend_mode:
method __new__ (line 70) | def __new__(cls, *args, **kwargs):
class Clip_settings (line 74) | class Clip_settings:
method __new__ (line 76) | def __new__(cls, *args, **kwargs):
class Text_style (line 80) | class Text_style:
method __new__ (line 82) | def __new__(cls, *args, **kwargs):
class Text_border (line 86) | class Text_border:
method __new__ (line 88) | def __new__(cls, *args, **kwargs):
class Text_background (line 92) | class Text_background:
method __new__ (line 94) | def __new__(cls, *args, **kwargs):
class Text_segment (line 98) | class Text_segment:
method __new__ (line 100) | def __new__(cls, *args, **kwargs):
class Audio_segment (line 104) | class Audio_segment:
method __new__ (line 106) | def __new__(cls, *args, **kwargs):
class Video_segment (line 110) | class Video_segment:
method __new__ (line 112) | def __new__(cls, *args, **kwargs):
class Sticker_segment (line 116) | class Sticker_segment:
method __new__ (line 118) | def __new__(cls, *args, **kwargs):
class Effect_segment (line 122) | class Effect_segment:
method __new__ (line 124) | def __new__(cls, *args, **kwargs):
class Filter_segment (line 128) | class Filter_segment:
method __new__ (line 130) | def __new__(cls, *args, **kwargs):
class Video_material (line 134) | class Video_material:
method __new__ (line 136) | def __new__(cls, *args, **kwargs):
class Audio_material (line 140) | class Audio_material:
method __new__ (line 142) | def __new__(cls, *args, **kwargs):
class Crop_settings (line 146) | class Crop_settings:
method __new__ (line 148) | def __new__(cls, *args, **kwargs):
class _DeprecatedEnum (line 153) | class _DeprecatedEnum:
method __init__ (line 155) | def __init__(self, original_enum, old_name, new_name):
method __getattr__ (line 160) | def __getattr__(self, name):
method __getitem__ (line 165) | def __getitem__(self, name):
method __repr__ (line 170) | def __repr__(self):
class Jianying_controller (line 191) | class Jianying_controller:
method __new__ (line 193) | def __new__(cls, *args, **kwargs):
FILE: src/pyJianYingDraft/animation.py
class Animation (line 14) | class Animation:
method __init__ (line 34) | def __init__(self, animation_meta: AnimationMeta, start: int, duration...
method export_json (line 42) | def export_json(self) -> Dict[str, Any]:
class VideoAnimation (line 59) | class VideoAnimation(Animation):
method __init__ (line 64) | def __init__(self, animation_type: Union[IntroType, OutroType, GroupAn...
class Text_animation (line 77) | class Text_animation(Animation):
method __init__ (line 82) | def __init__(self, animation_type: Union[TextIntro, TextOutro, TextLoo...
class SegmentAnimations (line 95) | class SegmentAnimations:
method __init__ (line 106) | def __init__(self):
method get_animation_trange (line 110) | def get_animation_trange(self, animation_type: Literal["in", "out", "g...
method add_animation (line 117) | def add_animation(self, animation: Union[VideoAnimation, Text_animatio...
method export_json (line 134) | def export_json(self) -> Dict[str, Any]:
FILE: src/pyJianYingDraft/assets/__init__.py
function get_asset_path (line 17) | def get_asset_path(asset_name: str) -> Path:
FILE: src/pyJianYingDraft/audio_segment.py
class AudioFade (line 20) | class AudioFade:
method __init__ (line 31) | def __init__(self, in_duration: int, out_duration: int):
method export_json (line 38) | def export_json(self) -> Dict[str, Any]:
class AudioEffect (line 47) | class AudioEffect:
method __init__ (line 63) | def __init__(self, effect_meta: Union[AudioSceneEffectType, ToneEffect...
method export_json (line 89) | def export_json(self) -> Dict[str, Any]:
class AudioSegment (line 106) | class AudioSegment(MediaSegment):
method __init__ (line 124) | def __init__(self, material: Union[AudioMaterial, str], target_timeran...
method add_effect (line 160) | def add_effect(self, effect_type: Union[AudioSceneEffectType, ToneEffe...
method add_fade (line 183) | def add_fade(self, in_duration: Union[str, int], out_duration: Union[s...
method add_keyframe (line 204) | def add_keyframe(self, time_offset: int, volume: float) -> "AudioSegme...
method export_json (line 221) | def export_json(self) -> Dict[str, Any]:
FILE: src/pyJianYingDraft/draft_folder.py
class DraftFolder (line 11) | class DraftFolder:
method __init__ (line 17) | def __init__(self, folder_path: str):
method list_drafts (line 31) | def list_drafts(self) -> List[str]:
method has_draft (line 38) | def has_draft(self, draft_name: str) -> bool:
method remove (line 48) | def remove(self, draft_name: str) -> None:
method create_draft (line 63) | def create_draft(self, draft_name: str, width: int, height: int, fps: ...
method inspect_material (line 104) | def inspect_material(self, draft_name: str) -> None:
method load_template (line 120) | def load_template(self, draft_name: str) -> ScriptFile:
method duplicate_as_template (line 141) | def duplicate_as_template(self, template_name: str, new_draft_name: st...
FILE: src/pyJianYingDraft/effect_segment.py
class EffectSegment (line 11) | class EffectSegment(BaseSegment):
method __init__ (line 20) | def __init__(self, effect_type: Union[VideoSceneEffectType, VideoChara...
class FilterSegment (line 25) | class FilterSegment(BaseSegment):
method __init__ (line 34) | def __init__(self, meta: FilterType, target_timerange: Timerange, inte...
FILE: src/pyJianYingDraft/exceptions.py
class TrackNotFound (line 3) | class TrackNotFound(NameError):
class AmbiguousTrack (line 5) | class AmbiguousTrack(ValueError):
class SegmentOverlap (line 7) | class SegmentOverlap(ValueError):
class MaterialNotFound (line 10) | class MaterialNotFound(NameError):
class AmbiguousMaterial (line 12) | class AmbiguousMaterial(ValueError):
class ExtensionFailed (line 15) | class ExtensionFailed(ValueError):
class DraftNotFound (line 18) | class DraftNotFound(NameError):
class AutomationError (line 20) | class AutomationError(Exception):
class ExportTimeout (line 22) | class ExportTimeout(Exception):
FILE: src/pyJianYingDraft/jianying_controller.py
class ExportResolution (line 30) | class ExportResolution(Enum):
class ExportFramerate (line 39) | class ExportFramerate(Enum):
class ControlFinder (line 47) | class ControlFinder:
method desc_matcher (line 51) | def desc_matcher(target_desc: str, depth: int = 2, exact: bool = False...
method class_name_matcher (line 62) | def class_name_matcher(class_name: str, depth: int = 1, exact: bool = ...
class JianyingController (line 72) | class JianyingController:
method __init__ (line 85) | def __init__(self):
method find_and_click_draft (line 89) | def find_and_click_draft(self, draft_name: str, max_retries: int = 5, ...
method click_export_button (line 130) | def click_export_button(self) -> None:
method get_original_export_path (line 143) | def get_original_export_path(self) -> str:
method set_export_resolution (line 161) | def set_export_resolution(self, resolution: Optional[ExportResolution]...
method set_export_framerate (line 188) | def set_export_framerate(self, framerate: Optional[ExportFramerate]) -...
method click_final_export_button (line 215) | def click_final_export_button(self) -> None:
method __ensure_window_focus (line 227) | def __ensure_window_focus(self) -> None:
method wait_for_export_completion (line 244) | def wait_for_export_completion(self, timeout: float) -> None:
method return_to_home (line 278) | def return_to_home(self) -> None:
method move_exported_file (line 284) | def move_exported_file(self, original_path: str, output_path: Optional...
method export_draft (line 295) | def export_draft(self, draft_name: str, output_path: Optional[str] = N...
method switch_to_home (line 362) | def switch_to_home(self) -> None:
method get_window (line 384) | def get_window(
method init_export_sub_status (line 438) | def init_export_sub_status(self) -> None:
method __jianying_window_cmp (line 457) | def __jianying_window_cmp(self, control: uia.WindowControl, depth: int...
FILE: src/pyJianYingDraft/keyframe.py
class Keyframe (line 6) | class Keyframe:
method __init__ (line 16) | def __init__(self, time_offset: int, value: float):
method export_json (line 23) | def export_json(self) -> Dict[str, Any]:
class KeyframeProperty (line 36) | class KeyframeProperty(Enum):
class KeyframeList (line 65) | class KeyframeList:
method __init__ (line 75) | def __init__(self, keyframe_property: KeyframeProperty):
method add_keyframe (line 82) | def add_keyframe(self, time_offset: int, value: float):
method export_json (line 88) | def export_json(self) -> Dict[str, Any]:
FILE: src/pyJianYingDraft/local_materials.py
class CropSettings (line 8) | class CropSettings:
method __init__ (line 20) | def __init__(self, *, upper_left_x: float = 0.0, upper_left_y: float =...
method export_json (line 34) | def export_json(self) -> Dict[str, Any]:
class VideoMaterial (line 46) | class VideoMaterial:
method __init__ (line 68) | def __init__(self, path: str, material_name: Optional[str] = None, cro...
method export_json (line 117) | def export_json(self) -> Dict[str, Any]:
class AudioMaterial (line 139) | class AudioMaterial:
method __init__ (line 152) | def __init__(self, path: str, material_name: Optional[str] = None):
method export_json (line 180) | def export_json(self) -> Dict[str, Any]:
FILE: src/pyJianYingDraft/metadata/audio_scene_effect.py
class AudioSceneEffectType (line 6) | class AudioSceneEffectType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/effect_meta.py
class EffectParam (line 8) | class EffectParam:
method __init__ (line 20) | def __init__(self, name: str, default_value: float, min_value: float, ...
class EffectParamInstance (line 26) | class EffectParamInstance(EffectParam):
method __init__ (line 34) | def __init__(self, meta: EffectParam, index: int, value: float):
method export_json (line 39) | def export_json(self) -> Dict[str, Any]:
class EffectMeta (line 51) | class EffectMeta:
method __init__ (line 68) | def __init__(self, name: str, is_vip: bool, resource_id: str, effect_i...
method parse_params (line 76) | def parse_params(self, params: Optional[List[Optional[float]]]) -> Lis...
class EffectEnum (line 95) | class EffectEnum(Enum):
method from_name (line 99) | def from_name(cls: "type[EffectEnumSubclass]", name: str) -> EffectEnu...
class AnimationMeta (line 115) | class AnimationMeta:
method __init__ (line 127) | def __init__(self, title: str, is_vip: bool, duration: float, resource...
class MaskMeta (line 136) | class MaskMeta:
method __init__ (line 154) | def __init__(self, name: str, resource_type: str, resource_id: str, ef...
class TransitionMeta (line 164) | class TransitionMeta:
method __init__ (line 183) | def __init__(self, name: str, is_vip: bool, resource_id: str, effect_i...
FILE: src/pyJianYingDraft/metadata/filter_meta.py
class FilterType (line 6) | class FilterType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/font_meta.py
class FontType (line 6) | class FontType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/mask_meta.py
class MaskType (line 5) | class MaskType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/mix_mode_meta.py
class MixModeType (line 5) | class MixModeType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/speech_to_song.py
class SpeechToSongType (line 4) | class SpeechToSongType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/text_intro.py
class TextIntro (line 5) | class TextIntro(EffectEnum):
FILE: src/pyJianYingDraft/metadata/text_loop.py
class TextLoopAnim (line 5) | class TextLoopAnim(EffectEnum):
FILE: src/pyJianYingDraft/metadata/text_outro.py
class TextOutro (line 5) | class TextOutro(EffectEnum):
FILE: src/pyJianYingDraft/metadata/tone_effect.py
class ToneEffectType (line 4) | class ToneEffectType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/transition_meta.py
class TransitionType (line 5) | class TransitionType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/video_character_effect.py
class VideoCharacterEffectType (line 6) | class VideoCharacterEffectType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/video_group_animation.py
class GroupAnimationType (line 5) | class GroupAnimationType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/video_intro.py
class IntroType (line 5) | class IntroType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/video_outro.py
class OutroType (line 5) | class OutroType(EffectEnum):
FILE: src/pyJianYingDraft/metadata/video_scene_effect.py
class VideoSceneEffectType (line 6) | class VideoSceneEffectType(EffectEnum):
FILE: src/pyJianYingDraft/script_file.py
class ScriptMaterial (line 24) | class ScriptMaterial:
method __init__ (line 58) | def __init__(self):
method __contains__ (line 77) | def __contains__(self, item: Union[VideoMaterial, AudioMaterial]) -> b...
method __contains__ (line 79) | def __contains__(self, item: Union[AudioFade, AudioEffect]) -> bool: ...
method __contains__ (line 81) | def __contains__(self, item: Union[SegmentAnimations, VideoEffect, Tra...
method __contains__ (line 83) | def __contains__(self, item) -> bool:
method export_json (line 105) | def export_json(self) -> Dict[str, List[Any]]:
class ScriptFile (line 154) | class ScriptFile:
method __init__ (line 187) | def __init__(self, width: int, height: int, fps: int, maintrack_adsorb...
method load_template (line 216) | def load_template(json_path: str) -> "ScriptFile":
method add_material (line 241) | def add_material(self, material: Union[VideoMaterial, AudioMaterial]) ...
method next_track_render_index (line 253) | def next_track_render_index(self) -> int:
method add_track_ordered (line 259) | def add_track_ordered(self, track_type: TrackType, track_name: Optiona...
method add_track (line 264) | def add_track(self, track_type: TrackType, track_name: Optional[str] =...
method _get_track (line 299) | def _get_track(self, segment_type: Type[BaseSegment], track_name: Opti...
method add_segment (line 312) | def add_segment(self, segment: Union[VideoSegment, StickerSegment, Aud...
method add_effect (line 400) | def add_effect(self, effect: Union[VideoSceneEffectType, VideoCharacte...
method add_filter (line 429) | def add_filter(self, filter_meta: FilterType, t_range: Timerange,
method import_srt (line 455) | def import_srt(self, srt_path: str, track_name: str, *,
method get_imported_track (line 534) | def get_imported_track(self, track_type: Literal[TrackType.video, Trac...
method import_track (line 570) | def import_track(self, source_file: "ScriptFile", track: EditableTrack...
method replace_material_by_name (line 627) | def replace_material_by_name(self, material_name: str, material: Union...
method replace_material_by_seg (line 665) | def replace_material_by_seg(self, track: EditableTrack, segment_index:...
method replace_text (line 711) | def replace_text(self, track: EditableTrack, segment_index: int, text:...
method inspect_material (line 799) | def inspect_material(self) -> None:
method dumps (line 816) | def dumps(self) -> str:
method dump (line 838) | def dump(self, file_path: str) -> None:
method save (line 843) | def save(self) -> None:
FILE: src/pyJianYingDraft/segment.py
class BaseSegment (line 10) | class BaseSegment:
method __init__ (line 23) | def __init__(self, material_id: str, target_timerange: Timerange):
method start (line 31) | def start(self) -> int:
method start (line 35) | def start(self, value: int):
method duration (line 39) | def duration(self) -> int:
method duration (line 43) | def duration(self, value: int):
method end (line 47) | def end(self) -> int:
method overlaps (line 51) | def overlaps(self, other: "BaseSegment") -> bool:
method export_json (line 55) | def export_json(self) -> Dict[str, Any]:
class Speed (line 79) | class Speed:
method __init__ (line 87) | def __init__(self, speed: float):
method export_json (line 91) | def export_json(self) -> Dict[str, Any]:
class AudioFade (line 100) | class AudioFade:
method __init__ (line 111) | def __init__(self, in_duration: int, out_duration: int):
method export_json (line 118) | def export_json(self) -> Dict[str, Any]:
class ClipSettings (line 127) | class ClipSettings:
method __init__ (line 147) | def __init__(self, *, alpha: float = 1.0,
method export_json (line 171) | def export_json(self) -> Dict[str, Any]:
class MediaSegment (line 181) | class MediaSegment(BaseSegment):
method __init__ (line 196) | def __init__(self, material_id: str, source_timerange: Optional[Timera...
method export_json (line 207) | def export_json(self) -> Dict[str, Any]:
class VisualSegment (line 219) | class VisualSegment(MediaSegment):
method __init__ (line 234) | def __init__(self, material_id: str, source_timerange: Optional[Timera...
method add_keyframe (line 253) | def add_keyframe(self, _property: KeyframeProperty, time_offset: Union...
method export_json (line 282) | def export_json(self) -> Dict[str, Any]:
FILE: src/pyJianYingDraft/template_mode.py
class ShrinkMode (line 15) | class ShrinkMode(Enum):
class ExtendMode (line 29) | class ExtendMode(Enum):
class ImportedSegment (line 43) | class ImportedSegment(BaseSegment):
method __init__ (line 50) | def __init__(self, json_data: Dict[str, Any]):
method export_json (line 55) | def export_json(self) -> Dict[str, Any]:
class ImportedMediaSegment (line 60) | class ImportedMediaSegment(ImportedSegment):
method __init__ (line 67) | def __init__(self, json_data: Dict[str, Any]):
method export_json (line 72) | def export_json(self) -> Dict[str, Any]:
class ImportedTrack (line 78) | class ImportedTrack(BaseTrack):
method __init__ (line 84) | def __init__(self, json_data: Dict[str, Any]):
method export_json (line 92) | def export_json(self) -> Dict[str, Any]:
class EditableTrack (line 100) | class EditableTrack(ImportedTrack):
method __len__ (line 106) | def __len__(self):
method start_time (line 110) | def start_time(self) -> int:
method end_time (line 117) | def end_time(self) -> int:
method export_json (line 123) | def export_json(self) -> Dict[str, Any]:
class ImportedTextTrack (line 132) | class ImportedTextTrack(EditableTrack):
method __init__ (line 135) | def __init__(self, json_data: Dict[str, Any]):
class ImportedMediaTrack (line 139) | class ImportedMediaTrack(EditableTrack):
method __init__ (line 145) | def __init__(self, json_data: Dict[str, Any]):
method check_material_type (line 149) | def check_material_type(self, material: object) -> bool:
method process_timerange (line 157) | def process_timerange(self, seg_index: int, src_timerange: Timerange,
function import_track (line 214) | def import_track(json_data: Dict[str, Any]) -> ImportedTrack:
FILE: src/pyJianYingDraft/text_segment.py
class TextStyle (line 17) | class TextStyle:
method __init__ (line 50) | def __init__(self, *, size: float = 8.0, bold: bool = False, italic: b...
class TextBorder (line 87) | class TextBorder:
method __init__ (line 97) | def __init__(self, *, alpha: float = 1.0, color: Tuple[float, float, f...
method export_json (line 108) | def export_json(self) -> Dict[str, Any]:
class TextBackground (line 120) | class TextBackground:
method __init__ (line 141) | def __init__(self, *, color: str, style: Literal[1, 2] = 1, alpha: flo...
method export_json (line 165) | def export_json(self) -> Dict[str, Any]:
class TextBubble (line 178) | class TextBubble:
method __init__ (line 187) | def __init__(self, effect_id: str, resource_id: str):
method export_json (line 192) | def export_json(self) -> Dict[str, Any]:
class TextEffect (line 203) | class TextEffect(TextBubble):
method export_json (line 206) | def export_json(self) -> Dict[str, Any]:
class TextShadow (line 212) | class TextShadow:
method __init__ (line 226) | def __init__(self, *, alpha: float = 1.0, color: Tuple[float, float, f...
method export_json (line 242) | def export_json(self) -> Dict[str, Any]:
class TextSegment (line 255) | class TextSegment(VisualSegment):
method __init__ (line 279) | def __init__(self, text: str, timerange: Timerange, *,
method create_from_template (line 312) | def create_from_template(cls, text: str, timerange: Timerange, templat...
method add_animation (line 331) | def add_animation(self, animation_type: Union[TextIntro, TextOutro, Te...
method add_bubble (line 374) | def add_bubble(self, effect_id: str, resource_id: str) -> "TextSegment":
method add_effect (line 385) | def add_effect(self, effect_id: str) -> "TextSegment":
method export_material (line 395) | def export_material(self) -> Dict[str, Any]:
FILE: src/pyJianYingDraft/time_util.py
function tim (line 9) | def tim(inp: Union[str, float]) -> int:
class Timerange (line 34) | class Timerange:
method __init__ (line 41) | def __init__(self, start: int, duration: int):
method import_json (line 53) | def import_json(cls, json_obj: Dict[str, str]) -> "Timerange":
method end (line 58) | def end(self) -> int:
method __eq__ (line 62) | def __eq__(self, other: object) -> bool:
method overlaps (line 67) | def overlaps(self, other: "Timerange") -> bool:
method __repr__ (line 71) | def __repr__(self) -> str:
method __str__ (line 74) | def __str__(self) -> str:
method export_json (line 77) | def export_json(self) -> Dict[str, int]:
function trange (line 80) | def trange(start: Union[str, float], duration: Union[str, float]) -> Tim...
function srt_tstamp (line 91) | def srt_tstamp(srt_tstamp: str) -> int:
FILE: src/pyJianYingDraft/track.py
class Track_meta (line 19) | class Track_meta:
class TrackType (line 31) | class TrackType(Enum):
method from_name (line 48) | def from_name(name: str) -> "TrackType":
class BaseTrack (line 56) | class BaseTrack(ABC):
method export_json (line 69) | def export_json(self) -> Dict[str, Any]: ...
class Track (line 72) | class Track(BaseTrack, Generic[Seg_type]):
method __init__ (line 81) | def __init__(self, track_type: TrackType, name: str, render_index: int...
method end_time (line 91) | def end_time(self) -> int:
method accept_segment_type (line 98) | def accept_segment_type(self) -> Type[Seg_type]:
method add_segment (line 102) | def add_segment(self, segment: Seg_type) -> "Track[Seg_type]":
method export_json (line 124) | def export_json(self) -> Dict[str, Any]:
FILE: src/pyJianYingDraft/util.py
function provide_ctor_defaults (line 10) | def provide_ctor_defaults(cls: Type) -> Dict[str, Any]:
function assign_attr_with_json (line 31) | def assign_attr_with_json(obj: object, attrs: List[str], json_data: Dict...
function export_attr_to_json (line 47) | def export_attr_to_json(obj: object, attrs: List[str]) -> Dict[str, Json...
FILE: src/pyJianYingDraft/video_segment.py
class Mask (line 23) | class Mask:
method __init__ (line 46) | def __init__(self, mask_meta: MaskMeta,
method export_json (line 61) | def export_json(self) -> Dict[str, Any]:
class VideoEffect (line 84) | class VideoEffect:
method __init__ (line 102) | def __init__(self, effect_meta: Union[VideoSceneEffectType, VideoChara...
method export_json (line 123) | def export_json(self) -> Dict[str, Any]:
class Filter (line 148) | class Filter:
method __init__ (line 162) | def __init__(self, meta: EffectMeta, intensity: float, *,
method export_json (line 171) | def export_json(self) -> Dict[str, Any]:
class Transition (line 205) | class Transition:
method __init__ (line 222) | def __init__(self, effect_meta: TransitionType, duration: Optional[int...
method export_json (line 232) | def export_json(self) -> Dict[str, Any]:
class BackgroundFilling (line 247) | class BackgroundFilling:
method __init__ (line 259) | def __init__(self, fill_type: Literal["canvas_blur", "canvas_color"], ...
method export_json (line 265) | def export_json(self) -> Dict[str, Any]:
class MixMode (line 274) | class MixMode:
method __init__ (line 289) | def __init__(self, meta: EffectMeta, *,
method export_json (line 297) | def export_json(self) -> Dict[str, Any]:
class VideoSegment (line 315) | class VideoSegment(VisualSegment):
method __init__ (line 360) | def __init__(self, material: Union[VideoMaterial, str], target_timeran...
method add_animation (line 404) | def add_animation(self, animation_type: Union[IntroType, OutroType, Gr...
method add_effect (line 435) | def add_effect(self, effect_type: Union[VideoSceneEffectType, VideoCha...
method add_fade (line 456) | def add_fade(self, in_duration: Union[str, int], out_duration: Union[s...
method add_filter (line 477) | def add_filter(self, filter_type: FilterType, intensity: float = 100.0...
method set_mix_mode (line 490) | def set_mix_mode(self, mode: MixModeType) -> "VideoSegment":
method add_mask (line 502) | def add_mask(self, mask_type: MaskType, *, center_x: float = 0.0, cent...
method add_transition (line 538) | def add_transition(self, transition_type: TransitionType, *, duration:...
method add_background_filling (line 556) | def add_background_filling(self, fill_type: Literal["blur", "color"], ...
method export_json (line 582) | def export_json(self) -> Dict[str, Any]:
class StickerSegment (line 589) | class StickerSegment(VisualSegment):
method __init__ (line 595) | def __init__(self, resource_id: str, target_timerange: Timerange, *, c...
method export_material (line 608) | def export_material(self) -> Dict[str, Any]:
FILE: src/router/v1.py
function create_draft (line 67) | def create_draft(cdr: CreateDraftRequest) -> CreateDraftResponse:
function save_draft (line 81) | async def save_draft(sdr: SaveDraftRequest) -> SaveDraftResponse:
function add_videos (line 96) | async def add_videos(avr: AddVideosRequest) -> AddVideosResponse:
function add_audios (line 124) | async def add_audios(aar: AddAudiosRequest) -> AddAudiosResponse:
function add_images (line 140) | async def add_images(air: AddImagesRequest) -> AddImagesResponse:
function add_sticker (line 167) | async def add_sticker(asr: AddStickerRequest) -> AddStickerResponse:
function add_keyframes (line 194) | async def add_keyframes(akr: AddKeyframesRequest) -> AddKeyframesResponse:
function add_captions (line 214) | async def add_captions(acr: AddCaptionsRequest) -> AddCaptionsResponse:
function add_effects (line 258) | async def add_effects(aer: AddEffectsRequest) -> AddEffectsResponse:
function add_filters (line 279) | async def add_filters(afr: AddFiltersRequest) -> AddFiltersResponse:
function add_masks (line 300) | async def add_masks(amr: AddMasksRequest) -> AddMasksResponse:
function add_text_style (line 330) | def add_text_style(atsr: AddTextStyleRequest) -> AddTextStyleResponse:
function easy_create_material (line 349) | async def easy_create_material(ecmr: EasyCreateMaterialRequest) -> EasyC...
function get_text_animations (line 373) | def get_text_animations(gtar: GetTextAnimationsRequest) -> GetTextAnimat...
function get_image_animations (line 390) | def get_image_animations(giar: GetImageAnimationsRequest) -> GetImageAni...
function get_filters (line 407) | def get_filters(gfr: GetFiltersRequest) -> GetFiltersResponse:
function get_text_effects (line 423) | def get_text_effects(gter: GetTextEffectsRequest) -> GetTextEffectsRespo...
function get_effects (line 441) | def get_effects(ger: GetEffectsRequest) -> GetEffectsResponse:
function get_draft (line 457) | def get_draft(params: Annotated[GetDraftRequest, Depends()]) -> GetDraft...
function gen_video (line 471) | def gen_video(request: Request, gvr: GenVideoRequest) -> GenVideoResponse:
function gen_video_status (line 486) | def gen_video_status(gvsr: GenVideoStatusRequest) -> GenVideoStatusRespo...
function gen_video_active_count (line 500) | def gen_video_active_count() -> GenVideoActiveCountResponse:
function get_audio_duration (line 509) | def get_audio_duration(gadr: GetAudioDurationRequest) -> GetAudioDuratio...
function timelines (line 523) | def timelines(request: TimelinesRequest) -> TimelinesResponse:
function audio_timelines (line 541) | def audio_timelines(request: AudioTimelinesRequest) -> AudioTimelinesRes...
function audio_infos (line 556) | def audio_infos(request: AudioInfosRequest) -> AudioInfosResponse:
function imgs_infos (line 574) | def imgs_infos(request: ImgsInfosRequest) -> ImgsInfosResponse:
function caption_infos (line 600) | def caption_infos(request: CaptionInfosRequest) -> CaptionInfosResponse:
function effect_infos (line 629) | def effect_infos(request: EffectInfosRequest) -> EffectInfosResponse:
function filter_infos (line 645) | def filter_infos(request: FilterInfosRequest) -> FilterInfosResponse:
function keyframes_infos (line 662) | def keyframes_infos(request: KeyframesInfosRequest) -> KeyframesInfosRes...
function video_infos (line 682) | def video_infos(request: VideoInfosRequest) -> VideoInfosResponse:
function search_sticker (line 704) | def search_sticker(ssr: SearchStickerRequest) -> SearchStickerResponse:
function get_url (line 718) | def get_url(gur: GetUrlRequest) -> GetUrlResponse:
function str_list_to_objs (line 732) | def str_list_to_objs(slto: StrListToObjsRequest) -> StrListToObjsResponse:
function str_to_list (line 746) | def str_to_list(stl: StrToListRequest) -> StrToListResponse:
function objs_to_str_list (line 760) | def objs_to_str_list(otl: ObjsToStrListRequest) -> ObjsToStrListResponse:
FILE: src/schemas/add_audios.py
class AddAudiosRequest (line 6) | class AddAudiosRequest(BaseModel):
method validate_audio_infos_http_urls (line 13) | def validate_audio_infos_http_urls(cls, value: str) -> str:
class AddAudiosResponse (line 32) | class AddAudiosResponse(BaseModel):
FILE: src/schemas/add_captions.py
class ShadowInfo (line 5) | class ShadowInfo(BaseModel):
class AddCaptionsRequest (line 14) | class AddCaptionsRequest(BaseModel):
class CaptionItem (line 39) | class CaptionItem(BaseModel):
class SegmentInfo (line 61) | class SegmentInfo(BaseModel):
class AddCaptionsResponse (line 68) | class AddCaptionsResponse(BaseModel):
FILE: src/schemas/add_effects.py
class AddEffectsRequest (line 5) | class AddEffectsRequest(BaseModel):
class EffectItem (line 11) | class EffectItem(BaseModel):
class AddEffectsResponse (line 18) | class AddEffectsResponse(BaseModel):
FILE: src/schemas/add_filters.py
class AddFiltersRequest (line 5) | class AddFiltersRequest(BaseModel):
class FilterItem (line 11) | class FilterItem(BaseModel):
class AddFiltersResponse (line 19) | class AddFiltersResponse(BaseModel):
FILE: src/schemas/add_images.py
class AddImagesRequest (line 6) | class AddImagesRequest(BaseModel):
method validate_image_infos_http_urls (line 18) | def validate_image_infos_http_urls(cls, value: str) -> str:
class SegmentInfo (line 37) | class SegmentInfo(BaseModel):
class AddImagesResponse (line 44) | class AddImagesResponse(BaseModel):
FILE: src/schemas/add_keyframes.py
class AddKeyframesRequest (line 5) | class AddKeyframesRequest(BaseModel):
class KeyframeItem (line 11) | class KeyframeItem(BaseModel):
class AddKeyframesResponse (line 19) | class AddKeyframesResponse(BaseModel):
FILE: src/schemas/add_masks.py
class AddMasksRequest (line 5) | class AddMasksRequest(BaseModel):
class AddMasksResponse (line 20) | class AddMasksResponse(BaseModel):
FILE: src/schemas/add_sticker.py
class AddStickerRequest (line 4) | class AddStickerRequest(BaseModel):
class AddStickerResponse (line 14) | class AddStickerResponse(BaseModel):
FILE: src/schemas/add_text_style.py
class AddTextStyleRequest (line 4) | class AddTextStyleRequest(BaseModel):
class AddTextStyleResponse (line 13) | class AddTextStyleResponse(BaseModel):
FILE: src/schemas/add_videos.py
class SceneTimelineItem (line 6) | class SceneTimelineItem(BaseModel):
class AddVideosRequest (line 12) | class AddVideosRequest(BaseModel):
method validate_video_infos_http_urls (line 25) | def validate_video_infos_http_urls(cls, value: str) -> str:
class SegmentInfo (line 44) | class SegmentInfo(BaseModel):
class AddVideosResponse (line 51) | class AddVideosResponse(BaseModel):
FILE: src/schemas/audio_infos.py
class AudioInfosRequest (line 6) | class AudioInfosRequest(BaseModel):
class AudioInfosResponse (line 14) | class AudioInfosResponse(BaseModel):
FILE: src/schemas/audio_timelines.py
class AudioTimelinesRequest (line 5) | class AudioTimelinesRequest(BaseModel):
class TimelineItem (line 10) | class TimelineItem(BaseModel):
class AudioTimelinesResponse (line 16) | class AudioTimelinesResponse(BaseModel):
FILE: src/schemas/caption_infos.py
class CaptionInfosRequest (line 6) | class CaptionInfosRequest(BaseModel):
class CaptionInfosResponse (line 27) | class CaptionInfosResponse(BaseModel):
FILE: src/schemas/create_draft.py
class CreateDraftRequest (line 4) | class CreateDraftRequest(BaseModel):
class CreateDraftResponse (line 10) | class CreateDraftResponse(BaseModel):
FILE: src/schemas/easy_create_material.py
class EasyCreateMaterialRequest (line 5) | class EasyCreateMaterialRequest(BaseModel):
method _is_http_url (line 17) | def _is_http_url(url: str) -> bool:
method validate_audio_url (line 22) | def validate_audio_url(cls, value: str) -> str:
method validate_optional_media_url (line 30) | def validate_optional_media_url(cls, value: Optional[str]) -> Optional...
class EasyCreateMaterialResponse (line 39) | class EasyCreateMaterialResponse(BaseModel):
FILE: src/schemas/effect_infos.py
class EffectInfosRequest (line 6) | class EffectInfosRequest(BaseModel):
class EffectInfosResponse (line 12) | class EffectInfosResponse(BaseModel):
FILE: src/schemas/filter_infos.py
class FilterInfosRequest (line 6) | class FilterInfosRequest(BaseModel):
method validate_intensities (line 14) | def validate_intensities(cls, v):
class FilterInfosResponse (line 21) | class FilterInfosResponse(BaseModel):
FILE: src/schemas/gen_video.py
class GenVideoRequest (line 7) | class GenVideoRequest(BaseModel):
method validate_api_key (line 14) | def validate_api_key(cls, v):
class GenVideoResponse (line 24) | class GenVideoResponse(BaseModel):
FILE: src/schemas/gen_video_active_count.py
class GenVideoActiveCountResponse (line 5) | class GenVideoActiveCountResponse(BaseModel):
FILE: src/schemas/gen_video_status.py
class GenVideoStatusRequest (line 8) | class GenVideoStatusRequest(BaseModel):
class GenVideoStatusResponse (line 13) | class GenVideoStatusResponse(BaseModel):
FILE: src/schemas/get_audio_duration.py
class GetAudioDurationRequest (line 4) | class GetAudioDurationRequest(BaseModel):
class Config (line 11) | class Config:
class GetAudioDurationResponse (line 19) | class GetAudioDurationResponse(BaseModel):
class Config (line 27) | class Config:
FILE: src/schemas/get_draft.py
class GetDraftRequest (line 5) | class GetDraftRequest(BaseModel):
class GetDraftResponse (line 10) | class GetDraftResponse(BaseModel):
FILE: src/schemas/get_effects.py
class GetEffectsRequest (line 5) | class GetEffectsRequest(BaseModel):
class EffectItem (line 10) | class EffectItem(BaseModel):
class GetEffectsResponse (line 20) | class GetEffectsResponse(BaseModel):
FILE: src/schemas/get_filters.py
class GetFiltersRequest (line 5) | class GetFiltersRequest(BaseModel):
class FilterItem (line 10) | class FilterItem(BaseModel):
class GetFiltersResponse (line 19) | class GetFiltersResponse(BaseModel):
FILE: src/schemas/get_image_animations.py
class GetImageAnimationsRequest (line 8) | class GetImageAnimationsRequest(BaseModel):
class ImageAnimationItem (line 14) | class ImageAnimationItem(BaseModel):
class GetImageAnimationsResponse (line 32) | class GetImageAnimationsResponse(BaseModel):
FILE: src/schemas/get_text_animations.py
class GetTextAnimationsRequest (line 8) | class GetTextAnimationsRequest(BaseModel):
class TextAnimationItem (line 14) | class TextAnimationItem(BaseModel):
class GetTextAnimationsResponse (line 32) | class GetTextAnimationsResponse(BaseModel):
FILE: src/schemas/get_text_effects.py
class GetTextEffectsRequest (line 5) | class GetTextEffectsRequest(BaseModel):
class TextEffectItem (line 10) | class TextEffectItem(BaseModel):
class GetTextEffectsResponse (line 17) | class GetTextEffectsResponse(BaseModel):
FILE: src/schemas/get_url.py
class GetUrlRequest (line 4) | class GetUrlRequest(BaseModel):
class GetUrlResponse (line 9) | class GetUrlResponse(BaseModel):
FILE: src/schemas/imgs_infos.py
class ImgsInfosRequest (line 6) | class ImgsInfosRequest(BaseModel):
class ImgsInfosResponse (line 22) | class ImgsInfosResponse(BaseModel):
FILE: src/schemas/keyframes_infos.py
class SegmentInfoItem (line 5) | class SegmentInfoItem(BaseModel):
class KeyframesInfosRequest (line 12) | class KeyframesInfosRequest(BaseModel):
class KeyframesInfosResponse (line 22) | class KeyframesInfosResponse(BaseModel):
FILE: src/schemas/objs_to_str_list.py
class ObjItem (line 5) | class ObjItem(BaseModel):
class ObjsToStrListRequest (line 10) | class ObjsToStrListRequest(BaseModel):
class ObjsToStrListResponse (line 15) | class ObjsToStrListResponse(BaseModel):
FILE: src/schemas/save_draft.py
class SaveDraftRequest (line 4) | class SaveDraftRequest(BaseModel):
class SaveDraftResponse (line 9) | class SaveDraftResponse(BaseModel):
FILE: src/schemas/search_sticker.py
class StickerPackage (line 5) | class StickerPackage(BaseModel):
class LargeImage (line 12) | class LargeImage(BaseModel):
class StickerInfo (line 17) | class StickerInfo(BaseModel):
class StickerItem (line 26) | class StickerItem(BaseModel):
class SearchStickerRequest (line 33) | class SearchStickerRequest(BaseModel):
class SearchStickerResponse (line 38) | class SearchStickerResponse(BaseModel):
FILE: src/schemas/str_list_to_objs.py
class StrListToObjsItem (line 5) | class StrListToObjsItem(BaseModel):
class StrListToObjsRequest (line 10) | class StrListToObjsRequest(BaseModel):
class StrListToObjsResponse (line 15) | class StrListToObjsResponse(BaseModel):
FILE: src/schemas/str_to_list.py
class StrToListRequest (line 5) | class StrToListRequest(BaseModel):
class StrToListResponse (line 10) | class StrToListResponse(BaseModel):
FILE: src/schemas/timelines.py
class TimelineItem (line 5) | class TimelineItem(BaseModel):
class TimelinesRequest (line 11) | class TimelinesRequest(BaseModel):
class TimelinesResponse (line 19) | class TimelinesResponse(BaseModel):
FILE: src/schemas/video_infos.py
class VideoInfosRequest (line 6) | class VideoInfosRequest(BaseModel):
class VideoInfosResponse (line 18) | class VideoInfosResponse(BaseModel):
FILE: src/service/add_audios.py
function add_audios (line 18) | def add_audios(
function _prepare_audios_local_files (line 40) | def _prepare_audios_local_files(draft_url: str, audio_infos: str) -> Lis...
function _add_audios_internal (line 54) | def _add_audios_internal(
function add_audios_async (line 85) | async def add_audios_async(
function validate_and_get_draft_id (line 157) | def validate_and_get_draft_id(draft_url: str) -> str:
function create_audio_directory (line 166) | def create_audio_directory(draft_id: str) -> str:
function validate_audio_data (line 175) | def validate_audio_data(audios: List[Dict[str, Any]], draft_id: str):
function add_audio_track (line 183) | def add_audio_track(script: ScriptFile) -> str:
function add_audio_segments (line 192) | def add_audio_segments(script: ScriptFile, track_name: str, draft_audio_...
function get_track_id (line 206) | def get_track_id(script: ScriptFile, track_name: str) -> str:
function find_audio_effect_type (line 216) | def find_audio_effect_type(audio_effect: str):
function convert_params_to_range (line 251) | def convert_params_to_range(effect_type) -> list:
function add_audio_effect (line 275) | def add_audio_effect(audio_segment, audio_effect: str):
function add_audio_to_draft (line 299) | def add_audio_to_draft(
function download_audio_file (line 371) | def download_audio_file(audio: dict, draft_audio_dir: str) -> str:
function get_audio_actual_duration (line 378) | def get_audio_actual_duration(audio_path: str) -> int:
function process_audio_duration (line 386) | def process_audio_duration(audio: dict, actual_duration: int):
function calculate_adjusted_time_range (line 393) | def calculate_adjusted_time_range(audio: dict, actual_duration: int):
function update_audio_time_params (line 429) | def update_audio_time_params(audio: dict, start_time: int, end_time: int):
function create_audio_segment (line 435) | def create_audio_segment(audio_path: str, start_time: int, segment_durat...
function add_segment_with_overlap_handling (line 445) | def add_segment_with_overlap_handling(script: ScriptFile, track_name: st...
function parse_audio_data (line 492) | def parse_audio_data(json_str: str) -> List[Dict[str, Any]]:
function parse_json_string (line 520) | def parse_json_string(json_str: str) -> List[Dict[str, Any]]:
function validate_input_format (line 531) | def validate_input_format(data: Any):
function process_single_audio_item (line 538) | def process_single_audio_item(item: Any, index: int) -> Dict[str, Any]:
function validate_item_type (line 556) | def validate_item_type(item: Any, index: int):
function validate_required_fields (line 563) | def validate_required_fields(item: Dict[str, Any], index: int):
function create_processed_item (line 573) | def create_processed_item(item: Dict[str, Any]) -> Dict[str, Any]:
function validate_numeric_ranges (line 585) | def validate_numeric_ranges(processed_item: Dict[str, Any], index: int):
FILE: src/service/add_captions.py
function resolve_font_type (line 23) | def resolve_font_type(font_name: str) -> Optional[FontType]:
function add_captions (line 94) | def add_captions(
function add_captions_async (line 265) | async def add_captions_async(
function add_caption_to_draft (line 384) | def add_caption_to_draft(
function apply_keyword_highlight (line 663) | def apply_keyword_highlight(text_segment: TextSegment, keywords: str, ke...
function parse_captions_data (line 736) | def parse_captions_data(json_str: str) -> List[Dict[str, Any]]:
function map_animation_name_to_enum (line 839) | def map_animation_name_to_enum(animation_name: str, animation_type: str):
function hex_to_rgb (line 881) | def hex_to_rgb(hex_color: str) -> tuple:
FILE: src/service/add_effects.py
function add_effects (line 14) | def add_effects(
function add_effects_async (line 99) | async def add_effects_async(
function add_effect_to_draft (line 161) | def add_effect_to_draft(
function find_effect_type_by_name (line 217) | def find_effect_type_by_name(effect_title: str) -> Optional[Union[VideoS...
function parse_effects_data (line 245) | def parse_effects_data(json_str: str) -> List[Dict[str, Any]]:
FILE: src/service/add_filters.py
function add_filters (line 14) | def add_filters(
function add_filters_async (line 100) | async def add_filters_async(
function add_filter_to_draft (line 162) | def add_filter_to_draft(
function find_filter_type_by_name (line 223) | def find_filter_type_by_name(filter_title: str) -> Optional[FilterType]:
function parse_filters_data (line 245) | def parse_filters_data(json_str: str) -> List[Dict[str, Any]]:
FILE: src/service/add_images.py
function add_images (line 20) | def add_images(
function _prepare_images_local_files (line 80) | def _prepare_images_local_files(draft_url: str, image_infos: str) -> Lis...
function _add_images_internal (line 106) | def _add_images_internal(
function add_images_async (line 185) | async def add_images_async(
function add_image_to_draft (line 272) | def add_image_to_draft(
function map_video_animation_name_to_enum (line 454) | def map_video_animation_name_to_enum(animation_name: str, animation_type...
function parse_image_data (line 496) | def parse_image_data(json_str: str) -> List[Dict[str, Any]]:
FILE: src/service/add_keyframes.py
function add_keyframes (line 16) | def add_keyframes(
function add_keyframes_async (line 150) | async def add_keyframes_async(
function find_segment_by_id (line 212) | def find_segment_by_id(script: ScriptFile, segment_id: str) -> Optional[...
function parse_keyframes_data (line 239) | def parse_keyframes_data(json_str: str) -> List[Dict[str, Any]]:
FILE: src/service/add_masks.py
function add_masks (line 14) | def add_masks(
function add_masks_async (line 118) | async def add_masks_async(
function add_mask_to_segment (line 208) | def add_mask_to_segment(
function find_segment_by_id (line 330) | def find_segment_by_id(script: ScriptFile, segment_id: str) -> Optional[...
function calculate_mask_size_params (line 357) | def calculate_mask_size_params(
function find_mask_type_by_name (line 391) | def find_mask_type_by_name(mask_name: str) -> Optional[MaskType]:
FILE: src/service/add_sticker.py
function add_sticker (line 14) | def add_sticker(
function add_sticker_async (line 140) | async def add_sticker_async(
FILE: src/service/add_text_style.py
function add_text_style (line 7) | def add_text_style(
function parse_keywords (line 79) | def parse_keywords(keyword_str: str) -> List[str]:
function find_keyword_positions (line 102) | def find_keyword_positions(text: str, keywords: List[str]) -> List[Tuple...
function hex_to_rgb (line 137) | def hex_to_rgb(hex_color: str) -> List[float]:
function generate_text_styles (line 167) | def generate_text_styles(
function create_text_style_segment (line 233) | def create_text_style_segment(
function create_simple_text_style (line 275) | def create_simple_text_style(text: str, font_size: int) -> str:
FILE: src/service/add_videos.py
function add_videos (line 20) | def add_videos(
function _prepare_videos_local_files (line 88) | def _prepare_videos_local_files(draft_url: str, video_infos: str) -> Lis...
function add_videos_async (line 114) | async def add_videos_async(
function _add_videos_internal (line 206) | def _add_videos_internal(
function _is_valid_scene_timeline (line 321) | def _is_valid_scene_timeline(scene_timeline: Any) -> bool:
function _has_valid_scene_timelines (line 333) | def _has_valid_scene_timelines(
function add_video_to_draft (line 347) | def add_video_to_draft(
function find_transition_type_by_name (line 480) | def find_transition_type_by_name(transition_name: str) -> Optional[draft...
function parse_video_data (line 500) | def parse_video_data(json_str: str) -> List[Dict[str, Any]]:
FILE: src/service/audio_infos.py
function audio_infos (line 6) | def audio_infos(
FILE: src/service/audio_timelines.py
function audio_timelines (line 10) | def audio_timelines(links: List[str]) -> Tuple[List[dict], List[dict]]:
function _calculate_timelines (line 67) | def _calculate_timelines(durations: List[int]) -> Tuple[List[dict], List...
function _cleanup_temp_files (line 94) | def _cleanup_temp_files(temp_files: List[str]) -> None:
FILE: src/service/caption_infos.py
function caption_infos (line 6) | def caption_infos(
function _build_caption_info (line 77) | def _build_caption_info(text, timeline, index, keywords,
FILE: src/service/create_draft.py
function create_draft (line 12) | def create_draft(width: int, height: int) -> str:
FILE: src/service/easy_create_material.py
function easy_create_material (line 17) | def easy_create_material(
function easy_create_material_async (line 96) | async def easy_create_material_async(
function add_video_material (line 177) | def add_video_material(script: ScriptFile, draft_id: str, video_url: str...
function add_image_material (line 235) | def add_image_material(script: ScriptFile, draft_id: str, img_url: str) ...
function add_audio_material (line 291) | def add_audio_material(script: ScriptFile, draft_id: str, audio_url: str...
function add_text_material (line 346) | def add_text_material(
function hex_to_rgb (line 409) | def hex_to_rgb(hex_color: str) -> list:
function validate_url (line 439) | def validate_url(url: str) -> bool:
FILE: src/service/effect_infos.py
function effect_infos (line 6) | def effect_infos(
FILE: src/service/filter_infos.py
function filter_infos (line 6) | def filter_infos(
FILE: src/service/gen_video.py
function gen_video (line 8) | def gen_video(draft_url: str, apiKey: str = None) -> str:
function validate_draft_url (line 58) | def validate_draft_url(draft_url: str) -> None:
function extract_draft_id_from_url (line 76) | def extract_draft_id_from_url(draft_url: str) -> str:
function gen_video_status (line 90) | def gen_video_status(draft_url: str) -> dict:
function get_task_status_info (line 116) | def get_task_status_info(draft_url: str) -> dict:
function get_gen_video_active_count (line 138) | def get_gen_video_active_count() -> int:
FILE: src/service/get_audio_duration.py
function get_audio_duration (line 10) | def get_audio_duration(mp3_url: str) -> int:
function _cleanup_temp_file (line 54) | def _cleanup_temp_file(temp_file_path: Optional[str]) -> None:
FILE: src/service/get_draft.py
function gen_download_url (line 8) | def gen_download_url(file_path: str) -> str:
function batch_gen_download_url (line 32) | def batch_gen_download_url(file_paths: List[str]) -> List[str]:
function get_draft (line 48) | def get_draft(draft_id: str) -> List[str]:
FILE: src/service/get_effects.py
function get_effects (line 10) | def get_effects(mode: int = 0) -> List[Dict[str, Any]]:
function _get_effects_by_mode (line 48) | def _get_effects_by_mode(mode: int) -> List[Dict[str, Any]]:
FILE: src/service/get_filters.py
function get_filters (line 10) | def get_filters(mode: int = 0) -> List[Dict[str, Any]]:
function _get_filters_by_mode (line 48) | def _get_filters_by_mode(mode: int) -> List[Dict[str, Any]]:
FILE: src/service/get_image_animations.py
function get_image_animations (line 10) | def get_image_animations(mode: int = 0, type: str = "in") -> List[Dict[s...
function _get_animations_by_type_and_mode (line 53) | def _get_animations_by_type_and_mode(type: str, mode: int) -> List[Dict[...
function _get_mock_image_animation_data (line 87) | def _get_mock_image_animation_data() -> List[Dict[str, Any]]:
FILE: src/service/get_text_animations.py
function get_text_animations (line 10) | def get_text_animations(mode: int = 0, type: str = "in") -> List[Dict[st...
function _get_animations_by_type_and_mode (line 53) | def _get_animations_by_type_and_mode(type: str, mode: int) -> List[Dict[...
function _get_mock_animation_data (line 87) | def _get_mock_animation_data() -> List[Dict[str, Any]]:
FILE: src/service/get_text_effects.py
function _load_huazi_data (line 17) | def _load_huazi_data() -> None:
function resolve_text_effect (line 55) | def resolve_text_effect(effect_identifier: str) -> Optional[Dict[str, An...
function get_text_effects (line 95) | def get_text_effects(mode: int = 0) -> List[Dict[str, Any]]:
function _get_text_effects_by_mode (line 133) | def _get_text_effects_by_mode(mode: int) -> List[Dict[str, Any]]:
FILE: src/service/get_url.py
function get_url (line 6) | def get_url(output: str) -> str:
FILE: src/service/imgs_infos.py
function imgs_infos (line 6) | def imgs_infos(
function _parse_animation_params (line 73) | def _parse_animation_params(in_animation, out_animation, loop_animation,...
function _build_image_info (line 88) | def _build_image_info(img_url, timeline, height, width, i,
function _add_animation_with_extension_logic (line 114) | def _add_animation_with_extension_logic(info, animation_key, animations,...
FILE: src/service/keyframes_infos.py
function calculate_relative_time_offset (line 7) | def calculate_relative_time_offset(offset_percent: int, duration: int) -...
function keyframes_infos (line 21) | def keyframes_infos(
FILE: src/service/objs_to_str_list.py
function objs_to_str_list (line 6) | def objs_to_str_list(outputs: List[Dict[str, Any]]) -> List[str]:
FILE: src/service/save_draft.py
function save_draft (line 12) | def save_draft(draft_url: str) -> str:
function save_draft_async (line 40) | async def save_draft_async(draft_url: str, lock_timeout: float = 30.0) -...
FILE: src/service/search_sticker.py
function search_sticker (line 9) | def search_sticker(keyword: str) -> List[Dict[str, Any]]:
FILE: src/service/str_list_to_objs.py
function str_list_to_objs (line 6) | def str_list_to_objs(infos: List[str]) -> List[Dict[str, Any]]:
FILE: src/service/str_to_list.py
function str_to_list (line 7) | def str_to_list(obj: str) -> List[str]:
FILE: src/service/timelines.py
function timelines (line 5) | def timelines(duration: int, num: int, start: int, type: int) -> Tuple[L...
FILE: src/service/video_infos.py
function video_infos (line 6) | def video_infos(
FILE: src/utils/cos.py
function cos_upload_file (line 14) | def cos_upload_file(file_path: str, expire_days: Optional[int] = None) -...
FILE: src/utils/download.py
function download (line 45) | def download(url: str, save_dir: str, limit: int = DEFAULT_FILE_SIZE_LIMIT,
function cleanup_temp_file (line 71) | def cleanup_temp_file(temp_file_path: Optional[str]) -> None:
function _prepare_download_context (line 85) | def _prepare_download_context(url: str, save_dir: str, timeout: int) -> ...
function _execute_download_with_retry (line 119) | def _execute_download_with_retry(context: dict, limit: int, retry: int) ...
function _check_resume_conditions (line 198) | def _check_resume_conditions(save_path: str, supports_range: bool,
function _execute_single_download (line 231) | def _execute_single_download(url: str, resume_info: dict, timeouts: dict...
function _handle_download_exception (line 251) | def _handle_download_exception(exception: Exception, attempt: int, retry...
function _execute_retry_wait (line 301) | def _execute_retry_wait(attempt: int, error_category: str, consecutive_f...
function _handle_final_failure (line 325) | def _handle_final_failure(last_exception: Optional[Exception], url: str)...
function _determine_file_path_with_extension (line 344) | def _determine_file_path_with_extension(response: requests.Response, sav...
function _parse_api_response (line 362) | def _parse_api_response(response: requests.Response) -> Dict[str, Any]:
function _validate_download_integrity_with_resume (line 381) | def _validate_download_integrity_with_resume(
function _safe_remove_file (line 435) | def _safe_remove_file(file_path: str) -> None:
function _assess_network_quality (line 450) | def _assess_network_quality(url: str) -> str:
function _check_range_support_with_retry (line 500) | def _check_range_support_with_retry(url: str, max_retries: int = 2) -> b...
function _calculate_adaptive_timeouts (line 591) | def _calculate_adaptive_timeouts(network_quality: str, base_timeout: int...
function _create_optimized_session (line 626) | def _create_optimized_session() -> requests.Session:
function _download_with_resume_enhanced (line 662) | def _download_with_resume_enhanced(url: str, resume_pos: int, timeouts: ...
function _download_fresh_enhanced (line 718) | def _download_fresh_enhanced(url: str, timeouts: dict) -> requests.Respo...
function _download_file_with_enhanced_stability (line 764) | def _download_file_with_enhanced_stability(
function _classify_download_error (line 864) | def _classify_download_error(error: Exception) -> str:
function _should_cleanup_on_error (line 899) | def _should_cleanup_on_error(error_category: str, supports_range: bool, ...
function _calculate_retry_delay (line 927) | def _calculate_retry_delay(attempt: int, error_category: str, consecutiv...
FILE: src/utils/draft_cache.py
function update_cache (line 9) | def update_cache(key: str, value: draft.ScriptFile) -> None:
FILE: src/utils/draft_cleanup.py
function is_draft_directory_name (line 32) | def is_draft_directory_name(name: str) -> bool:
function _draft_sort_key (line 36) | def _draft_sort_key(draft_id: str) -> tuple[datetime.datetime, str]:
function list_sorted_draft_ids (line 42) | def list_sorted_draft_ids(draft_dir: str) -> list[str]:
function select_drafts_for_deletion (line 54) | def select_drafts_for_deletion(
function delete_draft_folders (line 71) | def delete_draft_folders(draft_dir: str, draft_ids: Iterable[str]) -> li...
function run_one_draft_cleanup (line 98) | def run_one_draft_cleanup(
function draft_cleanup_background_loop (line 143) | async def draft_cleanup_background_loop() -> None:
FILE: src/utils/draft_downloader.py
function _sleep_gateway_backoff (line 25) | def _sleep_gateway_backoff(retry_no: int) -> None:
function safe_write_file (line 31) | def safe_write_file(file_path: str, file_content: bytes, is_binary: bool...
function extract_draft_id_from_url (line 79) | def extract_draft_id_from_url(url: str) -> Optional[str]:
function download_draft (line 99) | def download_draft(draft_url: str, save_path: Optional[str] = None) -> b...
function get_draft_files_list (line 135) | def get_draft_files_list(draft_url: str) -> list:
function download_all_files (line 209) | def download_all_files(files: list, target_dir: str, draft_id: str) -> b...
function download_single_file (line 239) | def download_single_file(file_url: str, target_dir: str) -> bool:
function update_json_file_paths (line 345) | def update_json_file_paths(json_file_path: str, target_dir: str, draft_i...
function update_material_paths (line 381) | def update_material_paths(data, remote_prefix: str, local_prefix: str):
function update_single_path (line 439) | def update_single_path(path: str, remote_prefix: str, local_prefix: str)...
function _is_http_url (line 462) | def _is_http_url(value: Any) -> bool:
function _safe_name (line 469) | def _safe_name(name: str) -> str:
function _infer_local_subdir (line 473) | def _infer_local_subdir(material_type: str, material: Dict[str, Any]) ->...
function _infer_ext_from_url (line 481) | def _infer_ext_from_url(url: str, fallback: str) -> str:
function _download_remote_file (line 489) | def _download_remote_file(file_url: str, local_path: str) -> bool:
function localize_remote_material_paths (line 542) | def localize_remote_material_paths(data: Dict[str, Any], target_dir: str...
function trigger_directory_scan_with_robocopy (line 595) | def trigger_directory_scan_with_robocopy(target_dir: str):
function copy_with_robocopy (line 614) | def copy_with_robocopy(src: str, dst: str, verbose: bool = False) -> bool:
function prepare_target_directory (line 749) | def prepare_target_directory(save_path: str, draft_id: str) -> str:
function execute_download (line 765) | def execute_download(draft_url: str, target_dir: str, draft_id: str) -> ...
function get_file_path (line 814) | def get_file_path(response: requests.Response, target_dir: str, draft_id...
function extract_filename_from_response (line 831) | def extract_filename_from_response(response: requests.Response, draft_id...
function sanitize_filename (line 854) | def sanitize_filename(filename: str) -> str:
function batch_download_drafts (line 876) | def batch_download_drafts(draft_urls: list, save_path: Optional[str] = N...
function initialize_batch_results (line 896) | def initialize_batch_results() -> dict:
function process_single_draft (line 910) | def process_single_draft(url: str, save_path: Optional[str], results: di...
function finalize_batch_results (line 928) | def finalize_batch_results(results: dict, draft_urls: list) -> None:
FILE: src/utils/draft_lock_manager.py
class DraftLockManager (line 11) | class DraftLockManager:
method __new__ (line 30) | def __new__(cls):
method __init__ (line 36) | def __init__(self):
method acquire_lock (line 56) | async def acquire_lock(self, draft_id: str, timeout: Optional[float] =...
method release_lock (line 132) | async def release_lock(self, draft_id: str) -> None:
method is_locked (line 190) | def is_locked(self, draft_id: str) -> bool:
method get_lock_count (line 212) | def get_lock_count(self, draft_id: str) -> int:
method get_all_locked_drafts (line 229) | def get_all_locked_drafts(self) -> list:
method clear_all_locks (line 247) | async def clear_all_locks(self) -> None:
method get_stats (line 267) | def get_stats(self) -> dict:
function get_draft_lock_manager (line 291) | def get_draft_lock_manager() -> DraftLockManager:
FILE: src/utils/helper.py
function get_url_param (line 13) | def get_url_param(url: str, key: str, default=None):
function gen_unique_id (line 21) | def gen_unique_id() -> str:
function get_all_files (line 30) | def get_all_files(dir: str) -> list:
FILE: src/utils/keyframe_value.py
function normalize_keyframe_value (line 10) | def normalize_keyframe_value(
FILE: src/utils/logger.py
class SkipGenVideoStatusAccessLogFilter (line 16) | class SkipGenVideoStatusAccessLogFilter(logging.Filter):
method filter (line 21) | def filter(self, record: logging.LogRecord) -> bool:
class RelativePathFormatter (line 25) | class RelativePathFormatter(logging.Formatter):
method __init__ (line 26) | def __init__(self, *args, project_root: Optional[str] = None, **kwargs):
method format (line 31) | def format(self, record: logging.LogRecord) -> str:
function _install_trace_context_filters (line 71) | def _install_trace_context_filters() -> None:
FILE: src/utils/media.py
function get_media_duration (line 7) | def get_media_duration(file_path: str) -> Optional[int]:
function get_media_duration_formatted (line 77) | def get_media_duration_formatted(file_path: str) -> Optional[str]:
FILE: src/utils/oss.py
function oss_upload_file (line 18) | def oss_upload_file(file_path: str, expire_days: Optional[int] = None) -...
FILE: src/utils/points.py
function get_user_points (line 19) | def get_user_points(api_key: str) -> float:
function deduct_user_points (line 58) | def deduct_user_points(api_key: str, points: float, desc: str) -> bool:
function _extract_points_from_response (line 100) | def _extract_points_from_response(result: Dict[str, Any]) -> float:
function _parse_api_response (line 121) | def _parse_api_response(response: requests.Response) -> Dict[str, Any]:
function _call_user_api (line 140) | def _call_user_api(method: str, endpoint: str, params: Optional[dict] = ...
FILE: src/utils/storage_upload_retry.py
function _iter_exception_chain (line 40) | def _iter_exception_chain(exc: BaseException) -> Iterator[BaseException]:
function is_retryable_storage_error (line 50) | def is_retryable_storage_error(exc: BaseException) -> bool:
function run_with_storage_retry (line 95) | def run_with_storage_retry(operation: Callable[[], T], *, context: str =...
FILE: src/utils/trace_context.py
function get_trace_id (line 30) | def get_trace_id() -> Optional[str]:
function get_span_id (line 34) | def get_span_id() -> Optional[str]:
function _gen_trace_id (line 38) | def _gen_trace_id() -> str:
function _gen_span_id (line 42) | def _gen_span_id() -> str:
function parse_traceparent (line 46) | def parse_traceparent(value: str) -> Optional[Tuple[str, str]]:
function build_traceparent (line 66) | def build_traceparent(trace_id: str, span_id: str, sampled: bool = True)...
function _normalize_custom_request_id (line 72) | def _normalize_custom_request_id(raw: str) -> str:
function resolve_trace_from_headers (line 84) | def resolve_trace_from_headers(header_getter) -> Tuple[str, str]:
class TraceContextFilter (line 104) | class TraceContextFilter(logging.Filter):
method filter (line 107) | def filter(self, record: logging.LogRecord) -> bool:
FILE: src/utils/upload_file.py
function _is_valid_storage_config (line 11) | def _is_valid_storage_config(value: str) -> bool:
function _is_cos_configured (line 17) | def _is_cos_configured() -> bool:
function _is_oss_configured (line 25) | def _is_oss_configured() -> bool:
function upload_file (line 38) | def upload_file(file_path: str, expire_days: Optional[int] = None) -> str:
FILE: src/utils/video_task_manager.py
class UIAutomationInitializerInThread (line 42) | class UIAutomationInitializerInThread: # type: ignore
method __enter__ (line 43) | def __enter__(self):
method __exit__ (line 45) | def __exit__(self, *args):
class TaskStatus (line 49) | class TaskStatus(Enum):
class VideoGenTask (line 58) | class VideoGenTask:
class VideoGenTaskManager (line 73) | class VideoGenTaskManager:
method __new__ (line 85) | def __new__(cls):
method __init__ (line 92) | def __init__(self):
method submit_task (line 134) | def submit_task(self, draft_url: str, api_key: str = None) -> None:
method _add_task_to_queue_sync (line 173) | def _add_task_to_queue_sync(self, task: VideoGenTask) -> None:
method get_task_status (line 178) | def get_task_status(self, draft_url: str) -> Optional[Dict[str, Any]]:
method get_active_render_count (line 206) | def get_active_render_count(self) -> int:
method _ensure_worker_running (line 214) | def _ensure_worker_running(self):
method _worker_loop (line 222) | def _worker_loop(self):
method _async_worker_loop (line 235) | async def _async_worker_loop(self):
method _log_async_task_done (line 249) | def _log_async_task_done(self, fut: asyncio.Task) -> None:
method _persist_terminal_task (line 257) | def _persist_terminal_task(self, task: VideoGenTask) -> None:
method _run_upload_and_finalize (line 279) | async def _run_upload_and_finalize(self, task: VideoGenTask) -> None:
method _process_task (line 307) | async def _process_task(self, task: VideoGenTask):
method _check_draft_duration (line 360) | def _check_draft_duration(self, task: VideoGenTask) -> bool:
method _phase_download_and_prepare (line 427) | def _phase_download_and_prepare(self, task: VideoGenTask) -> str:
method _phase_export_only (line 462) | def _phase_export_only(self, task: VideoGenTask) -> str:
method _phase_cos_upload_finalize (line 498) | def _phase_cos_upload_finalize(self, task: VideoGenTask) -> Tuple[str,...
method _download_draft (line 516) | def _download_draft(self, task: VideoGenTask) -> bool:
method _export_video (line 537) | def _export_video(self, task: VideoGenTask, outfile: str) -> bool:
method _upload_video_to_cos (line 597) | def _upload_video_to_cos(self, outfile: str) -> Tuple[str, bool]:
method _calculate_and_charge (line 621) | def _calculate_and_charge(self, task: VideoGenTask, outfile: str) -> N...
method _cleanup_files (line 666) | def _cleanup_files(self, outfile: str, draft_id: str) -> None:
method _handle_result (line 688) | def _handle_result(self, upload_url: str, upload_failed: bool) -> Tupl...
method stop (line 706) | def stop(self):
FILE: src/utils/video_task_store.py
function _connect (line 26) | def _connect() -> sqlite3.Connection:
function _init_schema (line 34) | def _init_schema(conn: sqlite3.Connection) -> None:
function _ensure_schema (line 59) | def _ensure_schema() -> None:
function prune_if_needed (line 71) | def prune_if_needed() -> None:
function save_completed_result (line 112) | def save_completed_result(
function get_completed_by_draft_id (line 152) | def get_completed_by_draft_id(draft_id: str) -> Optional[Dict[str, Any]]:
FILE: tests/manual_test_audio_infos.py
function audio_infos (line 3) | def audio_infos(
function test_audio_infos (line 40) | def test_audio_infos():
FILE: tests/manual_test_caption_infos.py
function caption_infos (line 3) | def caption_infos(
function test_caption_infos (line 85) | def test_caption_infos():
FILE: tests/manual_test_effect_infos.py
function effect_infos (line 4) | def effect_infos(
function test_effect_infos (line 32) | def test_effect_infos():
FILE: tests/manual_test_imgs_infos.py
function imgs_infos (line 3) | def imgs_infos(
function test_imgs_infos (line 72) | def test_imgs_infos():
FILE: tests/manual_test_keyframes_infos.py
function keyframes_infos (line 4) | def keyframes_infos(
function test_keyframes_infos (line 60) | def test_keyframes_infos():
FILE: tests/manual_test_video_infos.py
function video_infos (line 4) | def video_infos(
function test_video_infos (line 62) | def test_video_infos():
FILE: tests/test_add_audios.py
function test_add_audios (line 5) | def test_add_audios():
FILE: tests/test_add_captions_text_effect.py
function test_resolve_text_effect (line 9) | def test_resolve_text_effect():
function test_text_effect_map (line 46) | def test_text_effect_map():
function test_add_captions_with_text_effect (line 57) | def test_add_captions_with_text_effect():
FILE: tests/test_add_images.py
function test_add_images (line 5) | def test_add_images():
FILE: tests/test_add_keyframes_normalize.py
function visual_segment (line 17) | def visual_segment():
function test_add_keyframes_normalizes_pixel_position_x (line 24) | def test_add_keyframes_normalizes_pixel_position_x(visual_segment):
function test_add_keyframes_rotation_value_unchanged (line 60) | def test_add_keyframes_rotation_value_unchanged(visual_segment):
function test_add_keyframes_uniform_scale_and_alpha_unchanged (line 77) | def test_add_keyframes_uniform_scale_and_alpha_unchanged(visual_segment):
function test_keyframes_infos_normalizes_pixels_for_position (line 104) | def test_keyframes_infos_normalizes_pixels_for_position():
FILE: tests/test_add_keyframes_refactor.py
function test_parse_keyframes_data (line 9) | def test_parse_keyframes_data():
function test_parse_invalid_keyframes_data (line 48) | def test_parse_invalid_keyframes_data():
FILE: tests/test_add_masks.py
class TestCalculateMaskSizeParams (line 29) | class TestCalculateMaskSizeParams(unittest.TestCase):
method test_circle_mask_size_calculation (line 32) | def test_circle_mask_size_calculation(self):
method test_rectangle_mask_size_calculation (line 55) | def test_rectangle_mask_size_calculation(self):
method test_heart_mask_size_calculation (line 79) | def test_heart_mask_size_calculation(self):
method test_star_mask_size_calculation (line 99) | def test_star_mask_size_calculation(self):
method test_linear_mask_size_calculation (line 119) | def test_linear_mask_size_calculation(self):
method test_mirror_mask_size_calculation (line 139) | def test_mirror_mask_size_calculation(self):
method test_zero_dimensions (line 159) | def test_zero_dimensions(self):
method test_large_dimensions (line 178) | def test_large_dimensions(self):
class TestFindMaskTypeByName (line 200) | class TestFindMaskTypeByName(unittest.TestCase):
method test_find_circle_mask (line 203) | def test_find_circle_mask(self):
method test_find_rectangle_mask (line 208) | def test_find_rectangle_mask(self):
method test_find_linear_mask (line 213) | def test_find_linear_mask(self):
method test_find_mirror_mask (line 218) | def test_find_mirror_mask(self):
method test_find_heart_mask (line 223) | def test_find_heart_mask(self):
method test_find_star_mask (line 228) | def test_find_star_mask(self):
method test_find_invalid_mask (line 233) | def test_find_invalid_mask(self):
method test_case_sensitive_search (line 238) | def test_case_sensitive_search(self):
class TestAddMaskToSegment (line 248) | class TestAddMaskToSegment(unittest.TestCase):
method setUp (line 251) | def setUp(self):
method test_add_circle_mask_success (line 269) | def test_add_circle_mask_success(self):
method test_add_rectangle_mask_with_all_params (line 310) | def test_add_rectangle_mask_with_all_params(self):
method test_segment_not_found (line 344) | def test_segment_not_found(self):
method test_non_video_segment (line 358) | def test_non_video_segment(self):
method test_segment_already_has_mask (line 375) | def test_segment_already_has_mask(self, mock_find_segment):
class TestAddMasksIntegration (line 394) | class TestAddMasksIntegration(unittest.TestCase):
method test_add_single_circle_mask (line 401) | def test_add_single_circle_mask(self, mock_add_mask, mock_find_mask_ty...
method test_add_multiple_masks (line 447) | def test_add_multiple_masks(self, mock_add_mask, mock_find_mask_type, ...
method test_invalid_draft_url (line 476) | def test_invalid_draft_url(self, mock_cache, mock_get_param):
method test_empty_segment_ids (line 490) | def test_empty_segment_ids(self, mock_get_param, mock_cache):
method test_invalid_mask_type (line 507) | def test_invalid_mask_type(self, mock_find_mask_type, mock_get_param, ...
method test_partial_failure_handling (line 526) | def test_partial_failure_handling(self, mock_add_mask, mock_find_mask_...
FILE: tests/test_add_videos_concurrent.py
class TestAddVideosAsync (line 25) | class TestAddVideosAsync:
method mock_draft_data (line 29) | def mock_draft_data(self):
method test_add_videos_with_lock_success (line 46) | async def test_add_videos_with_lock_success(self, mock_draft_data):
method test_add_videos_invalid_draft_url (line 95) | async def test_add_videos_invalid_draft_url(self):
method test_add_videos_lock_timeout (line 106) | async def test_add_videos_lock_timeout(self):
method test_concurrent_add_videos_same_draft (line 140) | async def test_concurrent_add_videos_same_draft(self):
method test_concurrent_add_videos_different_drafts (line 215) | async def test_concurrent_add_videos_different_drafts(self):
class TestAddVideosInternal (line 275) | class TestAddVideosInternal:
method test_internal_function_requires_lock (line 279) | async def test_internal_function_requires_lock(self):
class TestLockManagerIntegration (line 300) | class TestLockManagerIntegration:
method test_lock_cleanup_after_exception (line 304) | async def test_lock_cleanup_after_exception(self):
method test_lock_stats_accuracy (line 325) | async def test_lock_stats_accuracy(self):
FILE: tests/test_add_videos_concurrent_demo.py
class TestConcurrentProtectionDemo (line 16) | class TestConcurrentProtectionDemo:
method test_same_draft_serialized_access (line 20) | async def test_same_draft_serialized_access(self):
method test_different_drafts_parallel_access (line 64) | async def test_different_drafts_parallel_access(self):
method test_lock_prevents_concurrent_writes (line 102) | async def test_lock_prevents_concurrent_writes(self):
function main (line 154) | async def main():
FILE: tests/test_add_videos_duration.py
function test_add_videos_with_duration (line 5) | def test_add_videos_with_duration():
FILE: tests/test_add_videos_refactor.py
function test_parse_video_data_with_duration (line 8) | def test_parse_video_data_with_duration():
FILE: tests/test_all_text_effects.py
function test_total_count (line 8) | def test_total_count():
function test_resolve_by_name (line 22) | def test_resolve_by_name():
function test_resolve_by_id (line 47) | def test_resolve_by_id():
function test_random_effects (line 65) | def test_random_effects():
function test_filter_by_mode (line 85) | def test_filter_by_mode():
function test_special_characters (line 110) | def test_special_characters():
function test_export_capability (line 137) | def test_export_capability():
function main (line 159) | def main():
FILE: tests/test_api_version.py
function test_v1_create_draft (line 8) | def test_v1_create_draft():
function test_version_not_found (line 17) | def test_version_not_found():
FILE: tests/test_audio_infos.py
function test_audio_infos (line 9) | def test_audio_infos():
FILE: tests/test_audio_infos_simple.py
function test_audio_infos (line 10) | def test_audio_infos():
FILE: tests/test_audio_timelines.py
function test_audio_timelines (line 8) | def test_audio_timelines():
FILE: tests/test_caption_keywords.py
function test_caption_keywords (line 5) | def test_caption_keywords():
FILE: tests/test_caption_transform.py
function test_caption_transform (line 5) | def test_caption_transform():
FILE: tests/test_caption_transform_fix.py
function test_caption_transform_fix (line 5) | def test_caption_transform_fix():
FILE: tests/test_chinese_encoding_fix.py
function test_chinese_metadata_audio (line 7) | def test_chinese_metadata_audio():
FILE: tests/test_ci_dependencies.py
function test_platform_info (line 13) | def test_platform_info():
function test_basic_sync (line 22) | def test_basic_sync():
function test_windows_extras (line 36) | def test_windows_extras():
function test_import_functionality (line 54) | def test_import_functionality():
function main (line 81) | def main():
FILE: tests/test_cross_platform.py
function test_cross_platform_compatibility (line 10) | def test_cross_platform_compatibility():
FILE: tests/test_draft_cleanup.py
function _mkdir (line 9) | def _mkdir(p: str, name: str) -> str:
function test_is_draft_directory_name_accepts_standard_id (line 15) | def test_is_draft_directory_name_accepts_standard_id() -> None:
function test_is_draft_directory_name_rejects_invalid (line 20) | def test_is_draft_directory_name_rejects_invalid() -> None:
function test_list_sorted_draft_ids_ignores_files_and_bad_names (line 27) | def test_list_sorted_draft_ids_ignores_files_and_bad_names(tmp_path) -> ...
function test_select_drafts_for_deletion_oldest_first_until_quota (line 37) | def test_select_drafts_for_deletion_oldest_first_until_quota(tmp_path) -...
function test_select_drafts_for_deletion_skips_protected_uses_next_oldest (line 54) | def test_select_drafts_for_deletion_skips_protected_uses_next_oldest() -...
function test_run_one_draft_cleanup_deletes_oldest_unskipped_only (line 67) | def test_run_one_draft_cleanup_deletes_oldest_unskipped_only(tmp_path) -...
function test_run_one_draft_cleanup_never_removes_protected_ids (line 87) | def test_run_one_draft_cleanup_never_removes_protected_ids(tmp_path) -> ...
function test_run_one_draft_cleanup_skips_locked_ids (line 106) | def test_run_one_draft_cleanup_skips_locked_ids(tmp_path) -> None:
function test_run_one_draft_cleanup_skips_cached_ids (line 127) | def test_run_one_draft_cleanup_skips_cached_ids(tmp_path) -> None:
function test_list_sorted_draft_ids_missing_dir_returns_empty (line 143) | def test_list_sorted_draft_ids_missing_dir_returns_empty(tmp_path) -> None:
FILE: tests/test_draft_downloader_remote_materials.py
function no_sleep (line 16) | def no_sleep():
class TestDownloadRemoteFile (line 22) | class TestDownloadRemoteFile:
method _ok_response (line 23) | def _ok_response(self, content: bytes = b"data") -> MagicMock:
method test_succeeds_first_request (line 29) | def test_succeeds_first_request(self, no_sleep) -> None:
method test_retries_then_success_on_timeout (line 43) | def test_retries_then_success_on_timeout(self, no_sleep) -> None:
method test_returns_false_after_exhausting_retries (line 63) | def test_returns_false_after_exhausting_retries(self, no_sleep) -> None:
method test_non200_retries_then_success (line 72) | def test_non200_retries_then_success(self, no_sleep) -> None:
class TestLocalizeRemoteMaterialPaths (line 88) | class TestLocalizeRemoteMaterialPaths:
method test_no_materials_returns_true (line 89) | def test_no_materials_returns_true(self) -> None:
method test_no_urls_returns_true (line 92) | def test_no_urls_returns_true(self) -> None:
method test_rewrites_path_on_success (line 97) | def test_rewrites_path_on_success(self, m_dl) -> None:
method test_returns_false_when_download_fails (line 119) | def test_returns_false_when_download_fails(self, m_dl) -> None:
method test_same_url_shared_across_items (line 132) | def test_same_url_shared_across_items(self, m_dl) -> None:
class TestUpdateJsonFilePaths (line 152) | class TestUpdateJsonFilePaths:
method test_skips_write_when_localize_fails (line 153) | def test_skips_write_when_localize_fails(self) -> None:
method test_writes_when_localize_ok (line 175) | def test_writes_when_localize_ok(self, m_config, m_loc) -> None:
class TestDownloadSingleFile (line 193) | class TestDownloadSingleFile:
method _stream_response (line 202) | def _stream_response(
method test_success_writes_concatenated_chunks_and_relative_path (line 213) | def test_success_writes_concatenated_chunks_and_relative_path(self, no...
method test_fallback_relative_path_without_draft_segment (line 237) | def test_fallback_relative_path_without_draft_segment(self, no_sleep) ...
method test_non200_returns_false_and_closes (line 252) | def test_non200_returns_false_and_closes(self, no_sleep) -> None:
method test_gateway_503_retries_until_exhausted (line 263) | def test_gateway_503_retries_until_exhausted(self, no_sleep) -> None:
method test_retries_then_success_on_read_timeout (line 275) | def test_retries_then_success_on_read_timeout(self, no_sleep) -> None:
method test_returns_false_after_exhausting_retries (line 297) | def test_returns_false_after_exhausting_retries(self, no_sleep) -> None:
method test_plain_file_does_not_touch_json_paths (line 310) | def test_plain_file_does_not_touch_json_paths(self, m_upd, no_sleep) -...
method test_json_files_invoke_path_update (line 322) | def test_json_files_invoke_path_update(self, m_upd, no_sleep) -> None:
method test_json_update_failure_returns_false (line 338) | def test_json_update_failure_returns_false(self, m_upd, no_sleep) -> N...
class TestExecuteDownload (line 350) | class TestExecuteDownload:
method test_streams_body_to_default_filename_and_closes (line 358) | def test_streams_body_to_default_filename_and_closes(self, no_sleep) -...
method test_non200_returns_false (line 384) | def test_non200_returns_false(self, no_sleep) -> None:
method test_request_exception_returns_false (line 395) | def test_request_exception_returns_false(self, no_sleep) -> None:
FILE: tests/test_draft_lock_all_apis.py
class TestAllAsyncLockAPIs (line 46) | class TestAllAsyncLockAPIs:
method mock_draft_data (line 50) | def mock_draft_data(self):
method test_save_draft_async_normal (line 58) | async def test_save_draft_async_normal(self, mock_draft_data):
method test_add_audios_async_normal (line 76) | async def test_add_audios_async_normal(self, mock_draft_data):
method test_add_images_async_normal (line 121) | async def test_add_images_async_normal(self, mock_draft_data):
method test_add_captions_async_normal (line 167) | async def test_add_captions_async_normal(self, mock_draft_data):
method test_add_effects_async_normal (line 199) | async def test_add_effects_async_normal(self, mock_draft_data):
method test_add_keyframes_async_normal (line 229) | async def test_add_keyframes_async_normal(self, mock_draft_data):
method test_add_sticker_async_normal (line 265) | async def test_add_sticker_async_normal(self, mock_draft_data):
method test_add_filters_async_normal (line 291) | async def test_add_filters_async_normal(self, mock_draft_data):
method test_add_masks_async_normal (line 321) | async def test_add_masks_async_normal(self, mock_draft_data):
method test_easy_create_material_async_normal (line 349) | async def test_easy_create_material_async_normal(self, mock_draft_data):
method test_concurrent_access_same_draft_serialized (line 376) | async def test_concurrent_access_same_draft_serialized(self, mock_draf...
method test_invalid_draft_id_raises_error (line 413) | async def test_invalid_draft_id_raises_error(self):
method test_lock_timeout_raises_error (line 422) | async def test_lock_timeout_raises_error(self, mock_draft_data):
FILE: tests/test_draft_lock_manager.py
class TestDraftLockManager (line 21) | class TestDraftLockManager:
method lock_manager (line 25) | def lock_manager(self):
method test_acquire_and_release_lock (line 30) | async def test_acquire_and_release_lock(self, lock_manager):
method test_acquire_lock_with_timeout (line 46) | async def test_acquire_lock_with_timeout(self, lock_manager):
method test_acquire_lock_timeout_exception (line 63) | async def test_acquire_lock_timeout_exception(self, lock_manager):
method test_release_nonexistent_lock (line 78) | async def test_release_nonexistent_lock(self, lock_manager):
method test_is_locked_method (line 86) | async def test_is_locked_method(self, lock_manager):
method test_get_lock_count (line 102) | async def test_get_lock_count(self, lock_manager):
method test_get_all_locked_drafts (line 118) | async def test_get_all_locked_drafts(self, lock_manager):
method test_clear_all_locks (line 144) | async def test_clear_all_locks(self, lock_manager):
method test_get_stats (line 164) | async def test_get_stats(self, lock_manager):
method test_concurrent_access_different_drafts (line 187) | async def test_concurrent_access_different_drafts(self, lock_manager):
method test_serial_access_same_draft (line 213) | async def test_serial_access_same_draft(self, lock_manager):
method test_singleton_pattern (line 247) | async def test_singleton_pattern(self):
method test_get_draft_lock_manager_function (line 256) | async def test_get_draft_lock_manager_function(self):
class TestDraftLockManagerEdgeCases (line 265) | class TestDraftLockManagerEdgeCases:
method test_empty_draft_id (line 269) | async def test_empty_draft_id(self):
method test_special_characters_in_draft_id (line 281) | async def test_special_characters_in_draft_id(self):
method test_very_long_draft_id (line 300) | async def test_very_long_draft_id(self):
method test_rapid_acquire_release_cycle (line 312) | async def test_rapid_acquire_release_cycle(self):
method test_multiple_workers_same_draft_stress (line 326) | async def test_multiple_workers_same_draft_stress(self):
FILE: tests/test_draft_service.py
function test_create_draft_service (line 10) | def test_create_draft_service(mocker):
function test_create_draft_api (line 32) | def test_create_draft_api():
FILE: tests/test_export_error_handling.py
function test_export_error_handling (line 15) | def test_export_error_handling():
FILE: tests/test_file_operations.py
function test_file_move_improvements (line 17) | def test_file_move_improvements():
function test_directory_creation (line 51) | def test_directory_creation():
FILE: tests/test_float_transform.py
function test_float_transform (line 5) | def test_float_transform():
FILE: tests/test_font_alias_resolution.py
function test_resolve_font_type_by_alias_zhixianghei (line 10) | def test_resolve_font_type_by_alias_zhixianghei():
function test_resolve_font_type_by_display_name (line 15) | def test_resolve_font_type_by_display_name():
function test_resolve_font_type_by_enum_name (line 20) | def test_resolve_font_type_by_enum_name():
function test_resolve_font_type_with_unknown_name (line 25) | def test_resolve_font_type_with_unknown_name():
FILE: tests/test_font_size.py
function test_font_size (line 8) | def test_font_size():
FILE: tests/test_font_size_debug.py
function test_font_size_logic (line 1) | def test_font_size_logic():
FILE: tests/test_font_size_logic.py
function test_font_size_logic (line 5) | def test_font_size_logic():
FILE: tests/test_font_size_not_set.py
function test_font_size_not_set (line 8) | def test_font_size_not_set():
FILE: tests/test_get_audio_duration_api.py
function test_get_audio_duration_api (line 7) | def test_get_audio_duration_api():
FILE: tests/test_get_text_effects.py
function test_get_all_text_effects (line 13) | def test_get_all_text_effects():
function test_get_vip_text_effects (line 44) | def test_get_vip_text_effects():
function test_get_free_text_effects (line 65) | def test_get_free_text_effects():
function test_invalid_mode (line 86) | def test_invalid_mode():
FILE: tests/test_imgs_infos_multiple_animations.py
function test_multiple_animations_basic (line 11) | def test_multiple_animations_basic():
function test_animation_extension_logic (line 53) | def test_animation_extension_logic():
function test_excess_animations (line 95) | def test_excess_animations():
function test_multiple_animation_types (line 132) | def test_multiple_animation_types():
function test_backward_compatibility (line 192) | def test_backward_compatibility():
function test_empty_and_none_animations (line 230) | def test_empty_and_none_animations():
function run_all_tests (line 269) | def run_all_tests():
FILE: tests/test_keyframe_value.py
function test_normalize_pixel_position_x (line 10) | def test_normalize_pixel_position_x():
function test_normalize_already_normalized_position_x (line 15) | def test_normalize_already_normalized_position_x():
function test_normalize_pixel_position_y (line 20) | def test_normalize_pixel_position_y():
function test_keyframes_infos_assume_pixel_normalizes_small_values (line 24) | def test_keyframes_infos_assume_pixel_normalizes_small_values():
function test_rotation_scale_alpha_unchanged (line 30) | def test_rotation_scale_alpha_unchanged():
function test_rotation_scale_alpha_unchanged_with_assume_pixel (line 37) | def test_rotation_scale_alpha_unchanged_with_assume_pixel():
FILE: tests/test_keyword_font_size.py
function test_keyword_font_size_parsing (line 10) | def test_keyword_font_size_parsing():
function test_keyword_font_size_application (line 45) | def test_keyword_font_size_application():
function test_keyword_font_size_default (line 67) | def test_keyword_font_size_default():
FILE: tests/test_latest_commit_features.py
class TestMaintrackAdsorb (line 26) | class TestMaintrackAdsorb(unittest.TestCase):
method test_maintrack_adsorb_default_true (line 29) | def test_maintrack_adsorb_default_true(self):
method test_maintrack_adsorb_false (line 34) | def test_maintrack_adsorb_false(self):
method test_maintrack_adsorb_in_export (line 39) | def test_maintrack_adsorb_in_export(self):
class TestMixMode (line 46) | class TestMixMode(unittest.TestCase):
method test_mix_mode_creation (line 49) | def test_mix_mode_creation(self):
method test_mix_mode_export_json (line 56) | def test_mix_mode_export_json(self):
method test_video_segment_set_mix_mode (line 70) | def test_video_segment_set_mix_mode(self):
class TestVideoSegmentAudioFade (line 80) | class TestVideoSegmentAudioFade(unittest.TestCase):
method test_audio_fade_creation (line 83) | def test_audio_fade_creation(self):
method test_audio_fade_export_json (line 90) | def test_audio_fade_export_json(self):
class TestNewFilters (line 102) | class TestNewFilters(unittest.TestCase):
method test_filter_has_resource_id (line 105) | def test_filter_has_resource_id(self):
method test_filter_with_params (line 111) | def test_filter_with_params(self):
class TestNewFonts (line 120) | class TestNewFonts(unittest.TestCase):
method test_new_fonts_exist (line 123) | def test_new_fonts_exist(self):
class TestScriptMaterial (line 136) | class TestScriptMaterial(unittest.TestCase):
method test_mix_modes_list_exists (line 139) | def test_mix_modes_list_exists(self):
method test_mix_mode_in_check (line 146) | def test_mix_mode_in_check(self):
class TestIntegration (line 160) | class TestIntegration(unittest.TestCase):
method test_script_file_creation_with_maintrack_adsorb (line 163) | def test_script_file_creation_with_maintrack_adsorb(self):
method test_export_json_structure (line 172) | def test_export_json_structure(self):
class TestBackwardCompatibility (line 184) | class TestBackwardCompatibility(unittest.TestCase):
method test_script_file_init_requires_maintrack_adsorb (line 187) | def test_script_file_init_requires_maintrack_adsorb(self):
method test_mix_mode_types_available (line 193) | def test_mix_mode_types_available(self):
FILE: tests/test_logic_validation.py
function test_duration_handling_logic (line 5) | def test_duration_handling_logic():
FILE: tests/test_media_utils.py
function test_media_duration (line 8) | def test_media_duration():
FILE: tests/test_middleware.py
function test (line 15) | async def test(request: Request):
FILE: tests/test_param_pass.py
function test_create_draft_with_custom_params (line 4) | def test_create_draft_with_custom_params():
FILE: tests/test_parse_video_data.py
function parse_video_data (line 3) | def parse_video_data(json_str: str) -> list:
function test_parse_video_data_with_duration (line 61) | def test_parse_video_data_with_duration():
FILE: tests/test_search_sticker.py
function test_search_sticker (line 17) | def test_search_sticker():
FILE: tests/test_search_sticker_basic.py
function search_sticker (line 13) | def search_sticker(keyword: str, sticker_config_path: str) -> list:
function test_search_sticker (line 63) | def test_search_sticker():
FILE: tests/test_search_sticker_simple.py
function search_sticker (line 18) | def search_sticker(keyword: str) -> list:
function test_search_sticker (line 67) | def test_search_sticker():
FILE: tests/test_storage_upload_retry.py
function no_sleep_no_random_delay (line 17) | def no_sleep_no_random_delay():
class TestIterExceptionChain (line 28) | class TestIterExceptionChain:
method test_yields_self_then_cause (line 29) | def test_yields_self_then_cause(self) -> None:
method test_stops_on_cycle (line 37) | def test_stops_on_cycle(self) -> None:
class TestIsRetryableStorageError (line 46) | class TestIsRetryableStorageError:
method test_requests_transient (line 55) | def test_requests_transient(self, exc: Exception) -> None:
method test_urllib3_new_connection (line 58) | def test_urllib3_new_connection(self) -> None:
method test_urllib3_read_timeout (line 64) | def test_urllib3_read_timeout(self) -> None:
method test_urllib3_connect_timeout (line 69) | def test_urllib3_connect_timeout(self) -> None:
method test_urllib3_protocol (line 72) | def test_urllib3_protocol(self) -> None:
method test_oserror_errno (line 76) | def test_oserror_errno(self, code: int) -> None:
method test_oserror_not_retryable (line 79) | def test_oserror_not_retryable(self) -> None:
method test_cos_client_error (line 82) | def test_cos_client_error(self) -> None:
method test_cos_service_error (line 86) | def test_cos_service_error(self, status: int, expected: bool) -> None:
method test_exception_chain_finds_cause (line 90) | def test_exception_chain_finds_cause(self) -> None:
method test_exception_chain_valueerror_first_in_chain_still_finds_cause (line 96) | def test_exception_chain_valueerror_first_in_chain_still_finds_cause(s...
method test_oss_request_error (line 103) | def test_oss_request_error(self) -> None:
method test_oss_oss_error_status (line 110) | def test_oss_oss_error_status(self, status: int, expected: bool) -> None:
class TestRunWithStorageRetry (line 117) | class TestRunWithStorageRetry:
method test_success_first_call (line 118) | def test_success_first_call(self, no_sleep_no_random_delay) -> None:
method test_retries_then_success (line 123) | def test_retries_then_success(self, no_sleep_no_random_delay) -> None:
method test_non_retryable_raises_immediately (line 130) | def test_non_retryable_raises_immediately(self, no_sleep_no_random_del...
method test_exhausts_attempts (line 138) | def test_exhausts_attempts(self, no_sleep_no_random_delay) -> None:
method test_context_passed_to_warning_logger (line 148) | def test_context_passed_to_warning_logger(self, no_sleep_no_random_del...
FILE: tests/test_text_segment_add_animation.py
function _anim (line 20) | def _anim(seg: TextSegment, animation_type: str):
function test_intro_only_start_zero_and_respects_duration (line 28) | def test_intro_only_start_zero_and_respects_duration():
function test_outro_only_start_is_segment_end_minus_duration (line 36) | def test_outro_only_start_is_segment_end_minus_duration():
function test_intro_then_outro_both_unchanged (line 44) | def test_intro_then_outro_both_unchanged():
function test_intro_duration_still_capped_by_segment_length (line 53) | def test_intro_duration_still_capped_by_segment_length():
function test_outro_duration_still_capped_by_segment_length (line 60) | def test_outro_duration_still_capped_by_segment_length():
function test_loop_only_start_zero_uses_explicit_cycle (line 71) | def test_loop_only_start_zero_uses_explicit_cycle():
function test_loop_only_cycle_limited_by_segment_before_loop_branch (line 79) | def test_loop_only_cycle_limited_by_segment_before_loop_branch():
function test_loop_none_duration_uses_enum_default_microseconds (line 88) | def test_loop_none_duration_uses_enum_default_microseconds():
function test_loop_after_intro_outro_starts_at_intro_end (line 97) | def test_loop_after_intro_outro_starts_at_intro_end():
function test_loop_cycle_capped_by_available_between_in_and_out (line 109) | def test_loop_cycle_capped_by_available_between_in_and_out():
function test_loop_accepts_int_duration_microseconds (line 120) | def test_loop_accepts_int_duration_microseconds():
function test_add_in_out_loop_order_required_by_contract (line 126) | def test_add_in_out_loop_order_required_by_contract():
function test_add_loop_before_in_raises (line 135) | def test_add_loop_before_in_raises():
FILE: tests/test_transform_coordinate_fix.py
function test_transform_coordinate_fix (line 5) | def test_transform_coordinate_fix():
function test_transform_with_different_draft_sizes (line 68) | def test_transform_with_different_draft_sizes():
FILE: tests/test_upload_file.py
function upload_mocks (line 10) | def upload_mocks():
function test_upload_file_prefers_cos_when_configured (line 20) | def test_upload_file_prefers_cos_when_configured(upload_mocks) -> None:
function test_upload_file_fallback_oss_when_cos_not_configured (line 32) | def test_upload_file_fallback_oss_when_cos_not_configured(upload_mocks) ...
function test_upload_file_neither_storage_raises (line 44) | def test_upload_file_neither_storage_raises(upload_mocks) -> None:
function test_upload_file_passes_expire_days (line 57) | def test_upload_file_passes_expire_days(upload_mocks) -> None:
FILE: tests/test_video_duration_extension.py
class MockMediaInfo (line 6) | class MockMediaInfo:
method __init__ (line 7) | def __init__(self, duration=2000000, width=576, height=1024):
method parse (line 12) | def parse(self, path, **kwargs):
method can_parse (line 27) | def can_parse():
function test_video_duration_extension (line 39) | def test_video_duration_extension():
FILE: tests/test_video_task_draft_duration.py
function _task (line 18) | def _task(draft_id: str = "d_test") -> VideoGenTask:
function draft_home (line 28) | def draft_home():
class TestCheckDraftDuration (line 33) | class TestCheckDraftDuration:
method test_below_three_seconds_returns_false (line 34) | def test_below_three_seconds_returns_false(self, draft_home) -> None:
method test_exactly_three_seconds_returns_true (line 46) | def test_exactly_three_seconds_returns_true(self, draft_home) -> None:
method test_zero_duration_returns_false (line 58) | def test_zero_duration_returns_false(self, draft_home) -> None:
class TestPhaseDownloadPrepareMessage (line 71) | class TestPhaseDownloadPrepareMessage:
method test_phase_returns_duration_too_short_message (line 76) | def test_phase_returns_duration_too_short_message(
FILE: tests/test_video_transform.py
function test_video_transform (line 9) | def test_video_transform():
FILE: tests/test_video_transform_fix.py
function test_video_transform_coordinate_fix (line 5) | def test_video_transform_coordinate_fix():
function test_video_transform_with_different_draft_sizes (line 68) | def test_video_transform_with_different_draft_sizes():
function test_video_transform_vs_image_transform_consistency (line 123) | def test_video_transform_vs_image_transform_consistency():
FILE: tests/verify_get_text_effects_api.py
function test_imports (line 10) | def test_imports():
function test_schema_validation (line 50) | def test_schema_validation():
function test_service_logic (line 86) | def test_service_logic():
function main (line 124) | def main():
FILE: tools/extract_text_effects.py
function extract_text_effects_from_data_ts (line 8) | def extract_text_effects_from_data_ts(file_path: str) -> dict:
function generate_python_mapping (line 63) | def generate_python_mapping(text_effects: dict) -> str:
function main (line 98) | def main():
FILE: tools/query_sticker.py
function query_stickers (line 24) | def query_stickers(keyword, workflow_id=None, auth_token=None):
function save_result (line 78) | def save_result(result, output_file=None):
function query_multiple_keywords (line 126) | def query_multiple_keywords(keywords, output_file=None):
function get_common_chinese_characters (line 203) | def get_common_chinese_characters():
function main (line 421) | def main():
Condensed preview — 342 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,094K chars).
[
{
"path": ".github/workflows/desktop-client-dev.yml",
"chars": 3421,
"preview": "name: Build\n\non:\n push:\n branches: [ main, dev ]\n tags: [ 'v*' ]\n pull_request:\n branches: [ main, dev ]\n\njob"
},
{
"path": ".github/workflows/dev.yml",
"chars": 2494,
"preview": "name: Docker Image CI Dev\n\non:\n push:\n branches: [ \"main\", \"dev\" ]\n tags:\n - 'v*' # 当推送v开头的tag时触发\n pull_re"
},
{
"path": ".gitignore",
"chars": 51,
"preview": "*.pyc\n.venv\n./dist\n/.qoder\n/output\n/temp\n/logs\n/db\n"
},
{
"path": "Dockerfile",
"chars": 577,
"preview": "FROM python:3.11-slim\n\n# 使用pip安装uv\nRUN pip install --no-cache-dir uv\n\n# 验证uv安装\nRUN uv --version\n\n# 设置工作目录\nWORKDIR /app\n\n"
},
{
"path": "LICENSE",
"chars": 1066,
"preview": "MIT License\n\nCopyright (c) 2025 gogoshine\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
},
{
"path": "README.md",
"chars": 12186,
"preview": "# CapCut Mate API\n\n<div align=\"center\">\n\n### 🌐 Language Switch\n\n[中文版](README.zh.md) | [English](README.md)\n\n</div>\n\n---\n"
},
{
"path": "README.zh.md",
"chars": 7151,
"preview": "# CapCut Mate API\n\n<div align=\"center\">\n\n### 🌐 语言切换\n\n[中文版](README.zh.md) | [English](README.md)\n\n</div>\n\n---\n\n## 项目简介\nCa"
},
{
"path": "config/huazi.json",
"chars": 142745,
"preview": "[\n {\n \"id\": \"7539407429763796249\",\n \"title\": \"红黄火焰综艺花字\",\n \"is_vip\": true\n },\n {\n \"id\": \"73513165037713687"
},
{
"path": "config.py",
"chars": 2048,
"preview": "# 项目常量定义\nimport os\n\n\n# 项目根目录\nPROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))\n\n# 保存剪映草稿的目录\nDRAFT_DIR = os.path."
},
{
"path": "desktop-client/.gitignore",
"chars": 265,
"preview": "/node_modules\n/dist\n/ui\n/logs\napp-config.json\ndownload-log.json\n/.vscode\n.DS_Store\n.env\n.env.local\n.env.*.local\n/coverag"
},
{
"path": "desktop-client/.npmrc",
"chars": 146,
"preview": "ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/\nELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/e"
},
{
"path": "desktop-client/LICENSE",
"chars": 1066,
"preview": "MIT License\n\nCopyright (c) 2025 gogoshine\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
},
{
"path": "desktop-client/assets/entitlements.mac.plist",
"chars": 1280,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "desktop-client/main.js",
"chars": 3944,
"preview": "const { app, BrowserWindow, dialog, shell } = require('electron');\nconst path = require('path');\nconst logger = require("
},
{
"path": "desktop-client/nodeapi/download.js",
"chars": 30775,
"preview": "const path = require(\"path\");\nconst axios = require(\"axios\");\nconst { app, dialog, shell } = require(\"electron\");\nconst "
},
{
"path": "desktop-client/nodeapi/draftPathDetect.js",
"chars": 2483,
"preview": "const path = require(\"path\");\nconst fs = require(\"fs\").promises;\nconst os = require(\"os\");\nconst logger = require(\"./log"
},
{
"path": "desktop-client/nodeapi/ipcHandlers.js",
"chars": 2419,
"preview": "const { ipcMain, dialog, app } = require('electron');\n\n// 引入logger模块\nconst logger = require('./logger');\n\n// 引入axios\ncon"
},
{
"path": "desktop-client/nodeapi/logger.js",
"chars": 760,
"preview": "// logger.js\nconst log4js = require('log4js');\nconst path = require('path');\nconst { app } = require('electron');\n\nlog4j"
},
{
"path": "desktop-client/package.json",
"chars": 2097,
"preview": "{\n \"name\": \"capcut-mate\",\n \"version\": \"0.0.100\",\n \"description\": \"剪映小助手,用于下载剪映草稿\",\n \"main\": \"main.js\",\n \"scripts\": "
},
{
"path": "desktop-client/preload.js",
"chars": 1551,
"preview": "const { contextBridge, ipcRenderer } = require('electron');\n\nconsole.log('Preload script is loaded!');\n\n// 通过 contextBri"
},
{
"path": "desktop-client/scripts/electron-builder-green.config.js",
"chars": 935,
"preview": "module.exports = {\n appId: \"com.gogoshine.capcutmate\",\n productName: \"CapCut-Mate\",\n directories: {\n output: \"dist"
},
{
"path": "desktop-client/scripts/electron-builder.config.js",
"chars": 1369,
"preview": "/**\n * Electron Builder Configuration\n */\nmodule.exports = {\n appId: \"com.gogoshine.capcut-mate\",\n productName: \"剪映小助手"
},
{
"path": "desktop-client/scripts/update-version.js",
"chars": 1136,
"preview": "/**\n * 更新 package.json 中的 version 字段为 GitHub tag 版本号\n */\nconst fs = require('fs');\nconst path = require('path');\n\n// 获取 "
},
{
"path": "desktop-client/web/.gitignore",
"chars": 225,
"preview": "/node_modules\n/dist\n/ui\n/.vscode\n.DS_Store\n.env\n.env.local\n.env.*.local\n/coverage\nnpm-debug.log*\nyarn-debug.log*\nyarn-er"
},
{
"path": "desktop-client/web/index.html",
"chars": 389,
"preview": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-wid"
},
{
"path": "desktop-client/web/package.json",
"chars": 873,
"preview": "{\n \"name\": \"@sd/web\",\n \"version\": \"0.0.100\",\n \"description\": \"剪映小助手,用于下载剪映草稿\",\n \"scripts\": {\n \"dev\": \"vite\",\n "
},
{
"path": "desktop-client/web/public/index.html",
"chars": 332,
"preview": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-wid"
},
{
"path": "desktop-client/web/src/App.jsx",
"chars": 1609,
"preview": "// import {\n// BrowserRouter as Router,\n// Routes,\n// Route,\n// Navigate,\n// } from \"react-router-dom\";\n\nimport "
},
{
"path": "desktop-client/web/src/components/DownloadButton.jsx",
"chars": 590,
"preview": "\nfunction DownloadButton({ onClick, isLoading, setIsLoading, textValue }) {\n const handleClick = async () => {\n setI"
},
{
"path": "desktop-client/web/src/components/DownloadControls.jsx",
"chars": 543,
"preview": "function DownloadControls({ isOpen, onToggle, isLoading }) {\n return (\n <section className=\"module flex justify-betw"
},
{
"path": "desktop-client/web/src/components/ExternalWebpage.jsx",
"chars": 2932,
"preview": "import { useEffect, useRef, useState } from \"react\";\nimport { fetchAppVersion } from \"../utils/const\";\nimport electronSe"
},
{
"path": "desktop-client/web/src/components/Header/index.jsx",
"chars": 1201,
"preview": "import electronService from \"@/services/electronService\";\n\nimport \"./index.less\";\n\n// 顶部导航组件\nfunction TopHeader({ onTabC"
},
{
"path": "desktop-client/web/src/components/Header/index.less",
"chars": 837,
"preview": ".top-header {\n background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%);\n color: #ff"
},
{
"path": "desktop-client/web/src/components/LogModule.jsx",
"chars": 1464,
"preview": "import { formatToTime } from '../utils/date';\nimport { useEffect, useRef } from 'react';\n\nfunction LogModule({ logs, onC"
},
{
"path": "desktop-client/web/src/components/Tabs.jsx",
"chars": 1140,
"preview": "import React, { useState } from 'react';\n\nfunction Tabs({ onTabChange, initialContent }) {\n const templates = {\n tem"
},
{
"path": "desktop-client/web/src/components/Textarea.jsx",
"chars": 1032,
"preview": "import React, { useState, useEffect } from 'react';\n\nfunction Textarea({ value, onChange }) {\n const [textareaHeight, s"
},
{
"path": "desktop-client/web/src/index.jsx",
"chars": 233,
"preview": "import React from 'react';\nimport ReactDOM from 'react-dom/client';\n\nimport App from './App';\n\nconst root = ReactDOM.cre"
},
{
"path": "desktop-client/web/src/pages/ConfigCenter/index.jsx",
"chars": 1943,
"preview": "import { useEffect, useState } from \"react\";\nimport electronService from \"../../services/electronService\";\n\nimport \"./in"
},
{
"path": "desktop-client/web/src/pages/ConfigCenter/index.less",
"chars": 370,
"preview": "\n.setting-path-input-group {\n gap: 10px;\n margin-bottom: 5px;\n}\n.setting-path-label {\n font-size: 14px;\n wid"
},
{
"path": "desktop-client/web/src/pages/Download/index.jsx",
"chars": 3564,
"preview": "import { useState, useEffect, useRef } from \"react\";\nimport { toast } from \"react-toastify\";\nimport electronService from"
},
{
"path": "desktop-client/web/src/pages/Download/index.less",
"chars": 3716,
"preview": ".download-page {\n height: 100%;\n overflow-y: auto;\n}\n\n/* 外部网页样式 */\n.external-webpage-container {\n position: rel"
},
{
"path": "desktop-client/web/src/pages/History/index.jsx",
"chars": 10617,
"preview": "import { useState, useEffect, useMemo } from \"react\";\nimport { toast } from \"react-toastify\";\n\nimport {\n ListGroup,\n P"
},
{
"path": "desktop-client/web/src/pages/History/index.less",
"chars": 2214,
"preview": ".history-page {\n padding: 20px 0;\n height: 100%;\n overflow-y: auto;\n}\n\n.history-page h2 {\n margin-bottom: 20px;\n fo"
},
{
"path": "desktop-client/web/src/services/electronService.js",
"chars": 3849,
"preview": "/**\n * Electron API服务层\n * 封装Electron API调用,实现浏览器和Electron环境的兼容\n */\n\nimport axios from 'axios';\n\n// 检查是否在Electron环境中\ncons"
},
{
"path": "desktop-client/web/src/styles/index.less",
"chars": 3721,
"preview": "@charset \"UTF-8\";\n\n@import \"./root.less\";\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n font-family: \"Sego"
},
{
"path": "desktop-client/web/src/styles/root.less",
"chars": 454,
"preview": "@charset \"UTF-8\";\n\n:root {\n /* 基础蓝色系 */\n --primary-color: #356bfd;\n --primary-light: #5c89ff;\n --primary-dark: #1a50"
},
{
"path": "desktop-client/web/src/utils/const.tsx",
"chars": 482,
"preview": "import electronService from \"../services/electronService\";\n\nimport { version } from \"../../package.json\";\n\nexport const "
},
{
"path": "desktop-client/web/src/utils/date.ts",
"chars": 1265,
"preview": "/**\n * 时间格式化工具函数\n */\n\nimport type { ConfigType } from \"dayjs\";\nimport dayjs from \"dayjs\";\nimport { G_EmptyStr } from \"./"
},
{
"path": "desktop-client/web/vite.config.js",
"chars": 534,
"preview": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\nimport electron from 'vite-plugin-electron'"
},
{
"path": "docker-compose.example.yaml",
"chars": 1103,
"preview": "services:\n capcut-mate:\n image: gogoshine/capcut-mate:latest\n #image: gogoshine/capcut-mate:sha-190a61f\n ports"
},
{
"path": "docker-compose.yaml",
"chars": 1660,
"preview": "services:\n capcut-mate:\n image: gogoshine/capcut-mate:latest\n #image: gogoshine/capcut-mate:sha-190a61f\n platf"
},
{
"path": "docs/add_audios.md",
"chars": 6881,
"preview": "# ADD_AUDIOS API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## Interfac"
},
{
"path": "docs/add_audios.zh.md",
"chars": 4637,
"preview": "# ADD_AUDIOS API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openapi/capc"
},
{
"path": "docs/add_captions.md",
"chars": 8423,
"preview": "# ADD_CAPTIONS API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_captions.zh.md) | [English](./add_captions.md)\n\n## In"
},
{
"path": "docs/add_captions.zh.md",
"chars": 8189,
"preview": "# ADD_CAPTIONS API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openapi/ca"
},
{
"path": "docs/add_effects.md",
"chars": 6696,
"preview": "# ADD_EFFECTS API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_effects.zh.md) | [English](./add_effects.md)\n\n## Inter"
},
{
"path": "docs/add_effects.zh.md",
"chars": 3886,
"preview": "# ADD_EFFECTS API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```bash\nPOST /openapi"
},
{
"path": "docs/add_filters.md",
"chars": 6917,
"preview": "# ADD_FILTERS API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_filters.zh.md) | [English](./add_filters.md)\n\n## Inter"
},
{
"path": "docs/add_filters.zh.md",
"chars": 4559,
"preview": "# ADD_FILTERS API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_filters.zh.md) | [English](./add_filters.md)\n\n## 接口信息\n\n```bash\nPOST /opena"
},
{
"path": "docs/add_images.md",
"chars": 8335,
"preview": "# ADD_IMAGES API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_images.zh.md) | [English](./add_images.md)\n\n## Interfac"
},
{
"path": "docs/add_images.zh.md",
"chars": 5509,
"preview": "# ADD_IMAGES API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_images.zh.md) | [English](./add_images.md)\n\n## 接口信息\n\n```\nPOST /openapi/capc"
},
{
"path": "docs/add_keyframes.md",
"chars": 5261,
"preview": "# ADD_KEYFRAMES API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_keyframes.zh.md) | [English](./add_keyframes.md)\n\n##"
},
{
"path": "docs/add_keyframes.zh.md",
"chars": 4868,
"preview": "# ADD_KEYFRAMES API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n``` \nPOST /openapi/"
},
{
"path": "docs/add_masks.md",
"chars": 5362,
"preview": "# ADD_MASKS API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_masks.zh.md) | [English](./add_masks.md)\n\n## Interface I"
},
{
"path": "docs/add_masks.zh.md",
"chars": 5097,
"preview": "# ADD_MASKS API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openapi/capcu"
},
{
"path": "docs/add_sticker.md",
"chars": 7117,
"preview": "# ADD_STICKER API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_sticker.zh.md) | [English](./add_sticker.md)\n\n## Inter"
},
{
"path": "docs/add_sticker.zh.md",
"chars": 4502,
"preview": "# ADD_STICKER API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openapi/cap"
},
{
"path": "docs/add_text_style.md",
"chars": 5439,
"preview": "# ADD_TEXT_STYLE API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_text_style.zh.md) | [English](./add_text_style.md)\n"
},
{
"path": "docs/add_text_style.zh.md",
"chars": 3736,
"preview": "# ADD_TEXT_STYLE API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```bash\nPOST /open"
},
{
"path": "docs/add_videos.md",
"chars": 11972,
"preview": "# ADD_VIDEOS API Documentation\n\n## 🌐 Language Switch\n[中文版](./add_videos.zh.md) | [English](./add_videos.md)\n\n## Interfac"
},
{
"path": "docs/add_videos.zh.md",
"chars": 8308,
"preview": "# ADD_VIDEOS API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_videos.zh.md) | [English](./add_videos.md)\n\n## 接口信息\n\n```\nPOST /openapi/capc"
},
{
"path": "docs/audio_infos.md",
"chars": 5394,
"preview": "# AUDIO_INFOS API Documentation\n\n## 🌐 Language Switch\n[中文版](./audio_infos.zh.md) | [English](./audio_infos.md)\n\n## Inter"
},
{
"path": "docs/audio_infos.zh.md",
"chars": 3712,
"preview": "# AUDIO_INFOS API 接口文档\n\n## 🌐 语言切换\n[中文版](./audio_infos.zh.md) | [English](./audio_infos.md)\n\n## 接口信息\n\n```\nPOST /openapi/c"
},
{
"path": "docs/audio_timelines.md",
"chars": 5548,
"preview": "# AUDIO_TIMELINES API Documentation\n\n## 🌐 Language Switch\n[中文版](./audio_timelines.zh.md) | [English](./audio_timelines.m"
},
{
"path": "docs/audio_timelines.zh.md",
"chars": 3627,
"preview": "# AUDIO_TIMELINES API 接口文档\n\n## 🌐 语言切换\n[中文版](./audio_timelines.zh.md) | [English](./audio_timelines.md)\n\n## 接口信息\n\n```\nPOS"
},
{
"path": "docs/caption_infos.md",
"chars": 6269,
"preview": "# CAPTION_INFOS API Documentation\n\n## 🌐 Language Switch\n[中文版](./caption_infos.zh.md) | [English](./caption_infos.md)\n\n##"
},
{
"path": "docs/caption_infos.zh.md",
"chars": 4450,
"preview": "# CAPTION_INFOS API 接口文档\n\n## 🌐 语言切换\n[中文版](./caption_infos.zh.md) | [English](./caption_infos.md)\n\n## 接口信息\n\n```\nPOST /ope"
},
{
"path": "docs/create_draft.md",
"chars": 4693,
"preview": "# CREATE_DRAFT API Documentation\n\n## 🌐 Language Switch\n[中文版](./create_draft.zh.md) | [English](./create_draft.md)\n\n## In"
},
{
"path": "docs/create_draft.zh.md",
"chars": 2927,
"preview": "# CREATE_DRAFT API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openapi/ca"
},
{
"path": "docs/easy_create_material.md",
"chars": 7778,
"preview": "# EASY_CREATE_MATERIAL API Documentation\n\n## 🌐 Language Switch\n[中文版](./easy_create_material.zh.md) | [English](./easy_cr"
},
{
"path": "docs/easy_create_material.zh.md",
"chars": 4935,
"preview": "# EASY_CREATE_MATERIAL API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /op"
},
{
"path": "docs/effect_infos.md",
"chars": 3748,
"preview": "# EFFECT_INFOS API Documentation\n\n## 🌐 Language Switch\n[中文版](./effect_infos.zh.md) | [English](./effect_infos.md)\n\n## In"
},
{
"path": "docs/effect_infos.zh.md",
"chars": 2499,
"preview": "# EFFECT_INFOS API 接口文档\n\n## 🌐 语言切换\n[中文版](./effect_infos.zh.md) | [English](./effect_infos.md)\n\n## 接口信息\n\n```\nPOST /openap"
},
{
"path": "docs/filter_infos.md",
"chars": 4489,
"preview": "# FILTER_INFOS API Documentation\n\n## 🌐 Language Switch\n[中文版](./filter_infos.zh.md) | [English](./filter_infos.md)\n\n## In"
},
{
"path": "docs/filter_infos.zh.md",
"chars": 3040,
"preview": "# FILTER_INFOS API 接口文档\n\n## 🌐 语言切换\n[中文版](./filter_infos.zh.md) | [English](./filter_infos.md)\n\n## 接口信息\n\n```\nPOST /openap"
},
{
"path": "docs/gen_video.md",
"chars": 4856,
"preview": "# GEN_VIDEO API Documentation\n\n## 🌐 Language Switch\n[中文版](./gen_video.zh.md) | [English](./gen_video.md)\n\n## Interface I"
},
{
"path": "docs/gen_video.zh.md",
"chars": 2772,
"preview": "# GEN_VIDEO API 接口文档\n\n## 🌐 语言切换\n[中文版](./gen_video.zh.md) | [English](./gen_video.md)\n\n## 接口信息\n\n```\nPOST /openapi/capcut-"
},
{
"path": "docs/gen_video_status.md",
"chars": 5968,
"preview": "# GEN_VIDEO_STATUS API Documentation\n\n## 🌐 Language Switch\n[中文版](./gen_video_status.zh.md) | [English](./gen_video_statu"
},
{
"path": "docs/gen_video_status.zh.md",
"chars": 4229,
"preview": "# GEN_VIDEO_STATUS API 接口文档\n\n## 🌐 语言切换\n[中文版](./gen_video_status.zh.md) | [English](./gen_video_status.md)\n\n## 接口信息\n\n```b"
},
{
"path": "docs/get_audio_duration.md",
"chars": 3301,
"preview": "# GET_AUDIO_DURATION API Documentation\n\n## 🌐 Language Switch\n[中文版](./get_audio_duration.zh.md) | [English](./get_audio_d"
},
{
"path": "docs/get_audio_duration.zh.md",
"chars": 2248,
"preview": "# GET_AUDIO_DURATION API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /open"
},
{
"path": "docs/get_draft.md",
"chars": 4032,
"preview": "# GET_DRAFT API Documentation\n\n## 🌐 Language Switch\n[中文版](./get_draft.zh.md) | [English](./get_draft.md)\n\n## Interface I"
},
{
"path": "docs/get_draft.zh.md",
"chars": 2569,
"preview": "# GET_DRAFT API 接口文档\n\n## 🌐 语言切换\n[中文版](./get_draft.zh.md) | [English](./get_draft.md)\n\n## 接口信息\n\n```\nGET /openapi/capcut-m"
},
{
"path": "docs/get_image_animations.md",
"chars": 5871,
"preview": "# GET_IMAGE_ANIMATIONS API Documentation\n\n## 🌐 Language Switch\n[中文版](./get_image_animations.zh.md) | [English](./get_ima"
},
{
"path": "docs/get_image_animations.zh.md",
"chars": 3802,
"preview": "# GET_IMAGE_ANIMATIONS API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /op"
},
{
"path": "docs/get_text_animations.md",
"chars": 6442,
"preview": "# GET_TEXT_ANIMATIONS API Documentation\n\n## 🌐 Language Switch\n[中文版](./get_text_animations.zh.md) | [English](./get_text_"
},
{
"path": "docs/get_text_animations.zh.md",
"chars": 4325,
"preview": "# GET_TEXT_ANIMATIONS API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```bash\nPOST "
},
{
"path": "docs/get_text_effects.md",
"chars": 4365,
"preview": "# 获取花字效果列表 API 文档\n\n## 📖 接口说明\n\n获取所有支持的花字效果列表,支持按 VIP/免费进行筛选。\n\n本接口参考 `get_filters` 的实现模式,提供 RESTful 风格的 POST 请求方式。\n\n## 🔗 接"
},
{
"path": "docs/get_url.md",
"chars": 2509,
"preview": "# GET_URL API Documentation\n\n## 🌐 Language Switch\n[中文版](./get_url.zh.md) | [English](./get_url.md)\n\n## Interface Informa"
},
{
"path": "docs/get_url.zh.md",
"chars": 1662,
"preview": "# GET_URL API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openapi/capcut-"
},
{
"path": "docs/imgs_infos.md",
"chars": 6004,
"preview": "# IMGS_INFOS API Documentation\n\n## 🌐 Language Switch\n[中文版](./imgs_infos.zh.md) | [English](./imgs_infos.md)\n\n## Interfac"
},
{
"path": "docs/imgs_infos.zh.md",
"chars": 4298,
"preview": "# IMGS_INFOS API 接口文档\n\n## 🌐 语言切换\n[中文版](./imgs_infos.zh.md) | [English](./imgs_infos.md)\n\n## 接口信息\n\n```\nPOST /openapi/capc"
},
{
"path": "docs/keyframes_infos.md",
"chars": 4639,
"preview": "# KEYFRAMES_INFOS API Documentation\n\n## 🌐 Language Switch\n[中文版](./keyframes_infos.zh.md) | [English](./keyframes_infos.m"
},
{
"path": "docs/keyframes_infos.zh.md",
"chars": 3210,
"preview": "# KEYFRAMES_INFOS API 接口文档\n\n## 🌐 语言切换\n[中文版](./keyframes_infos.zh.md) | [English](./keyframes_infos.md)\n\n## 接口信息\n\n```\nPOS"
},
{
"path": "docs/objs_to_str_list.md",
"chars": 2786,
"preview": "# OBJS_TO_STR_LIST API Documentation\n\n## 🌐 Language Switch\n[中文版](./objs_to_str_list.zh.md) | [English](./objs_to_str_lis"
},
{
"path": "docs/objs_to_str_list.zh.md",
"chars": 1993,
"preview": "# OBJS_TO_STR_LIST API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openap"
},
{
"path": "docs/save_draft.md",
"chars": 3540,
"preview": "# SAVE_DRAFT API Documentation\n\n## 🌐 Language Switch\n[中文版](./save_draft.zh.md) | [English](./save_draft.md)\n\n## Interfac"
},
{
"path": "docs/save_draft.zh.md",
"chars": 2334,
"preview": "# SAVE_DRAFT API 接口文档\n\n## 🌐 语言切换\n[中文版](./save_draft.zh.md) | [English](./save_draft.md)\n\n## 接口信息\n\n```\nPOST /openapi/capc"
},
{
"path": "docs/search_sticker.md",
"chars": 4181,
"preview": "# SEARCH_STICKER API Documentation\n\n## 🌐 Language Switch\n[中文版](./search_sticker.zh.md) | [English](./search_sticker.md)\n"
},
{
"path": "docs/search_sticker.zh.md",
"chars": 2966,
"preview": "# SEARCH_STICKER API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openapi/"
},
{
"path": "docs/str_list_to_objs.md",
"chars": 2722,
"preview": "# STR_LIST_TO_OBJS API Documentation\n\n## 🌐 Language Switch\n[中文版](./str_list_to_objs.zh.md) | [English](./str_list_to_obj"
},
{
"path": "docs/str_list_to_objs.zh.md",
"chars": 1922,
"preview": "# STR_LIST_TO_OBJS API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openap"
},
{
"path": "docs/str_to_list.md",
"chars": 2664,
"preview": "# STR_TO_LIST API Documentation\n\n## 🌐 Language Switch\n[中文版](./str_to_list.zh.md) | [English](./str_to_list.md)\n\n## Inter"
},
{
"path": "docs/str_to_list.zh.md",
"chars": 1888,
"preview": "# STR_TO_LIST API 接口文档\n\n## 🌐 语言切换\n[中文版](./add_audios.zh.md) | [English](./add_audios.md)\n\n## 接口信息\n\n```\nPOST /openapi/cap"
},
{
"path": "docs/timelines.md",
"chars": 4981,
"preview": "# TIMELINES API Documentation\n\n## 🌐 Language Switch\n[中文版](./timelines.zh.md) | [English](./timelines.md)\n\n## Interface I"
},
{
"path": "docs/timelines.zh.md",
"chars": 3131,
"preview": "# TIMELINES API 接口文档\n\n## 🌐 语言切换\n[中文版](./timelines.zh.md) | [English](./timelines.md)\n\n## 接口信息\n\n```\nPOST /openapi/capcut-"
},
{
"path": "docs/video_infos.md",
"chars": 5197,
"preview": "# VIDEO_INFOS API Documentation\n\n## 🌐 Language Switch\n[中文版](./video_infos.zh.md) | [English](./video_infos.md)\n\n## Inter"
},
{
"path": "docs/video_infos.zh.md",
"chars": 3656,
"preview": "# VIDEO_INFOS API 接口文档\n\n## 🌐 语言切换\n[中文版](./video_infos.zh.md) | [English](./video_infos.md)\n\n## 接口信息\n\n```\nPOST /openapi/c"
},
{
"path": "exceptions.py",
"chars": 5588,
"preview": "from enum import Enum\n\n# 自定义错误码\nclass CustomError(Enum):\n \"\"\"错误码枚举类(支持中英文)\"\"\"\n \n # ===== 基础错误码 (1000-1999) ===="
},
{
"path": "main.py",
"chars": 1589,
"preview": "import asyncio\nfrom contextlib import asynccontextmanager, suppress\n\nfrom fastapi import FastAPI\nfrom src.router import "
},
{
"path": "openapi.yaml",
"chars": 646972,
"preview": "components:\n examples:\n add_audios:\n value:\n ReqExample:\n audio_i"
},
{
"path": "pyproject.toml",
"chars": 721,
"preview": "[project]\nname = \"capcut-mate\"\nversion = \"1.0.0\"\ndescription = \"CapCut Mate API Service\"\nauthors = [\n { name = \"Hommy"
},
{
"path": "src/__init__.py",
"chars": 21,
"preview": "\n# 空文件,标识src为Python包\n"
},
{
"path": "src/middlewares/__init__.py",
"chars": 219,
"preview": "# 中间件实现\nfrom .prepare import PrepareMiddleware\nfrom .response import ResponseMiddleware\nfrom .trace_context import Trace"
},
{
"path": "src/middlewares/prepare.py",
"chars": 512,
"preview": "# 环境初始化中间件\nfrom fastapi import Request\nfrom starlette.middleware.base import BaseHTTPMiddleware\nimport config\nimport os\n"
},
{
"path": "src/middlewares/response.py",
"chars": 6019,
"preview": "from fastapi import Request\nfrom fastapi.responses import JSONResponse\nfrom exceptions import CustomError, CustomExcepti"
},
{
"path": "src/middlewares/trace_context.py",
"chars": 1155,
"preview": "\"\"\"为每个 HTTP 请求注入 W3C trace 上下文并写入 contextvars。\"\"\"\nfrom __future__ import annotations\n\nfrom starlette.middleware.base imp"
},
{
"path": "src/pyJianYingDraft/__init__.py",
"chars": 9489,
"preview": "import warnings\nimport sys\n\nfrom .local_materials import CropSettings, VideoMaterial, AudioMaterial\nfrom .keyframe impor"
},
{
"path": "src/pyJianYingDraft/animation.py",
"chars": 4551,
"preview": "\"\"\"定义视频/文本动画相关类\"\"\"\n\nimport uuid\n\nfrom typing import Union, Optional\nfrom typing import Literal, Dict, List, Any\n\nfrom .t"
},
{
"path": "src/pyJianYingDraft/assets/__init__.py",
"chars": 932,
"preview": "\"\"\"\npyJianYingDraft 的资源管理模块,提供集中管理资源文件的方式,避免硬编码路径\n\"\"\"\n\nfrom pathlib import Path\n\n# 获取当前模块所在目录\nASSETS_DIR = Path(__file__"
},
{
"path": "src/pyJianYingDraft/assets/draft_content_template.json",
"chars": 3316,
"preview": "{\n \"canvas_config\": {\n \"height\": 1080,\n \"ratio\": \"original\",\n \"width\": 1920\n },\n \"color_sp"
},
{
"path": "src/pyJianYingDraft/assets/draft_meta_info.json",
"chars": 1374,
"preview": "{\n\t\"cloud_package_completed_time\": \"\",\n\t\"draft_cloud_capcut_purchase_info\": \"\",\n\t\"draft_cloud_last_action_download\": fal"
},
{
"path": "src/pyJianYingDraft/audio_segment.py",
"chars": 8007,
"preview": "\"\"\"定义音频片段及其相关类\n\n包含淡入淡出效果、音频特效等相关类\n\"\"\"\n\nimport uuid\nfrom copy import deepcopy\n\nfrom typing import Optional, Literal, Unio"
},
{
"path": "src/pyJianYingDraft/draft_folder.py",
"chars": 5273,
"preview": "\"\"\"草稿文件夹管理器\"\"\"\n\nimport os\nimport shutil\n\nfrom typing import List\n\nfrom . import assets\nfrom .script_file import ScriptFi"
},
{
"path": "src/pyJianYingDraft/effect_segment.py",
"chars": 1080,
"preview": "\"\"\"定义特效/滤镜片段类\"\"\"\n\nfrom typing import Union, Optional, List\n\nfrom .time_util import Timerange\nfrom .segment import BaseSe"
},
{
"path": "src/pyJianYingDraft/exceptions.py",
"chars": 503,
"preview": "\"\"\"自定义异常类\"\"\"\n\nclass TrackNotFound(NameError):\n \"\"\"未找到满足条件的轨道\"\"\"\nclass AmbiguousTrack(ValueError):\n \"\"\"找到多个满足条件的轨道\""
},
{
"path": "src/pyJianYingDraft/jianying_controller.py",
"chars": 17468,
"preview": "\"\"\"剪映自动化控制,主要与自动导出有关\"\"\"\n\nimport time\nimport shutil\nimport sys\n\n# 平台检查和依赖导入\nif sys.platform != \"win32\":\n raise ImportE"
},
{
"path": "src/pyJianYingDraft/keyframe.py",
"chars": 2751,
"preview": "import uuid\n\nfrom enum import Enum\nfrom typing import Dict, List, Any\n\nclass Keyframe:\n \"\"\"一个关键帧(关键点), 目前只支持线性插值\"\"\"\n\n"
},
{
"path": "src/pyJianYingDraft/local_materials.py",
"chars": 6841,
"preview": "import os\nimport uuid\nimport pymediainfo\n\nfrom typing import Optional, Literal\nfrom typing import Dict, Any\n\nclass CropS"
},
{
"path": "src/pyJianYingDraft/metadata/__init__.py",
"chars": 1302,
"preview": "\"\"\"记录各种特效/音效/滤镜等的元数据\n\n音频相关元数据更新时间:2024\n其余元数据更新时间:2026-03\n\"\"\"\nfrom .effect_meta import EffectMeta, EffectParamInstance\nfr"
},
{
"path": "src/pyJianYingDraft/metadata/audio_scene_effect.py",
"chars": 22498,
"preview": "\"\"\"音频场景特效元数据\"\"\"\n\nfrom .effect_meta import EffectEnum\nfrom .effect_meta import EffectMeta, EffectParam\n\nclass AudioSceneE"
},
{
"path": "src/pyJianYingDraft/metadata/effect_meta.py",
"chars": 5000,
"preview": "\"\"\"元数据类型定义\"\"\"\n\nfrom enum import Enum\n\nfrom typing import List, Dict, Any\nfrom typing import TypeVar, Optional\n\nclass Eff"
},
{
"path": "src/pyJianYingDraft/metadata/filter_meta.py",
"chars": 226889,
"preview": "\"\"\"滤镜效果元数据\"\"\"\n\nfrom .effect_meta import EffectEnum\nfrom .effect_meta import EffectMeta, EffectParam\n\nclass FilterType(Ef"
},
{
"path": "src/pyJianYingDraft/metadata/font_meta.py",
"chars": 102579,
"preview": "\"\"\"字体资源元数据\"\"\"\n\nfrom .effect_meta import EffectEnum\nfrom .effect_meta import EffectMeta\n\nclass FontType(EffectEnum):\n "
},
{
"path": "src/pyJianYingDraft/metadata/mask_meta.py",
"chars": 816,
"preview": "\"\"\"视频蒙版元数据\"\"\"\n\nfrom .effect_meta import EffectEnum, MaskMeta\n\nclass MaskType(EffectEnum):\n \"\"\"蒙版类型\"\"\"\n\n 线性 = MaskM"
},
{
"path": "src/pyJianYingDraft/metadata/mix_mode_meta.py",
"chars": 1189,
"preview": "\"\"\"混合模式元数据\"\"\"\n\nfrom .effect_meta import EffectEnum, EffectMeta\n\nclass MixModeType(EffectEnum):\n \"\"\"混合模式类型\"\"\"\n\n 正片叠"
},
{
"path": "src/pyJianYingDraft/metadata/speech_to_song.py",
"chars": 846,
"preview": "from .effect_meta import EffectEnum\nfrom .effect_meta import EffectMeta\n\nclass SpeechToSongType(EffectEnum):\n \"\"\"剪映自带"
},
{
"path": "src/pyJianYingDraft/metadata/text_intro.py",
"chars": 18883,
"preview": "\"\"\"文字入场动画元数据\"\"\"\n\nfrom .effect_meta import EffectEnum, AnimationMeta\n\nclass TextIntro(EffectEnum):\n \"\"\"文字入场动画, 默认时长为0."
},
{
"path": "src/pyJianYingDraft/metadata/text_loop.py",
"chars": 12172,
"preview": "\"\"\"文字循环动画元数据\"\"\"\n\nfrom .effect_meta import EffectEnum, AnimationMeta\n\nclass TextLoopAnim(EffectEnum):\n \"\"\"文字循环动画\"\"\"\n\n "
},
{
"path": "src/pyJianYingDraft/metadata/text_outro.py",
"chars": 12676,
"preview": "\"\"\"文字出场动画元数据\"\"\"\n\nfrom .effect_meta import EffectEnum, AnimationMeta\n\nclass TextOutro(EffectEnum):\n \"\"\"文字出场动画, 默认时长为0."
},
{
"path": "src/pyJianYingDraft/metadata/tone_effect.py",
"chars": 8231,
"preview": "from .effect_meta import EffectEnum\nfrom .effect_meta import EffectMeta, EffectParam\n\nclass ToneEffectType(EffectEnum):\n"
},
{
"path": "src/pyJianYingDraft/metadata/transition_meta.py",
"chars": 71921,
"preview": "\"\"\"转场效果元数据\"\"\"\n\nfrom .effect_meta import EffectEnum, TransitionMeta\n\nclass TransitionType(EffectEnum):\n \"\"\"转场类型\"\"\"\n\n "
},
{
"path": "src/pyJianYingDraft/metadata/video_character_effect.py",
"chars": 124049,
"preview": "\"\"\"视频人物特效元数据\"\"\"\n\nfrom .effect_meta import EffectEnum\nfrom .effect_meta import EffectMeta, EffectParam\n\nclass VideoCharac"
},
{
"path": "src/pyJianYingDraft/metadata/video_group_animation.py",
"chars": 16069,
"preview": "\"\"\"视频组合动画元数据\"\"\"\n\nfrom .effect_meta import EffectEnum, AnimationMeta\n\nclass GroupAnimationType(EffectEnum):\n \"\"\"视频组合动画"
},
{
"path": "src/pyJianYingDraft/metadata/video_intro.py",
"chars": 20175,
"preview": "\"\"\"视频片段入场动画元数据\"\"\"\n\nfrom .effect_meta import EffectEnum, AnimationMeta\n\nclass IntroType(EffectEnum):\n \"\"\"视频/图片入场动画类型\"\""
},
{
"path": "src/pyJianYingDraft/metadata/video_outro.py",
"chars": 16169,
"preview": "\"\"\"视频片段出场动画元数据\"\"\"\n\nfrom .effect_meta import EffectEnum, AnimationMeta\n\nclass OutroType(EffectEnum):\n \"\"\"视频/图片出场动画类型\"\""
},
{
"path": "src/pyJianYingDraft/metadata/video_scene_effect.py",
"chars": 566375,
"preview": "\"\"\"视频画面特效元数据\"\"\"\n\nfrom .effect_meta import EffectEnum\nfrom .effect_meta import EffectMeta, EffectParam\n\nclass VideoSceneE"
},
{
"path": "src/pyJianYingDraft/script_file.py",
"chars": 35624,
"preview": "import os\nimport json\nimport math\nfrom copy import deepcopy\n\nfrom typing import Optional, Literal, Union, overload\nfrom "
},
{
"path": "src/pyJianYingDraft/segment.py",
"chars": 9279,
"preview": "\"\"\"定义片段基类及部分比较通用的属性类\"\"\"\n\nimport uuid\nfrom typing import Optional, Dict, List, Any, Union\n\nfrom .animation import Segment"
},
{
"path": "src/pyJianYingDraft/template_mode.py",
"chars": 7529,
"preview": "\"\"\"与模板模式相关的类及函数等\"\"\"\n\nfrom enum import Enum\nfrom copy import deepcopy\n\nfrom . import util\nfrom . import exceptions\nfrom ."
},
{
"path": "src/pyJianYingDraft/text_segment.py",
"chars": 16174,
"preview": "\"\"\"定义文本片段及其相关类\"\"\"\n\nimport json\nimport uuid\nfrom copy import deepcopy\n\nfrom typing import Dict, Tuple, Any, List\nfrom typ"
},
{
"path": "src/pyJianYingDraft/time_util.py",
"chars": 2697,
"preview": "\"\"\"定义时间范围类以及与时间相关的辅助函数\"\"\"\n\nfrom typing import Union\nfrom typing import Dict\n\nSEC = 1000000\n\"\"\"一秒=1e6微秒\"\"\"\n\ndef tim(inp: "
},
{
"path": "src/pyJianYingDraft/track.py",
"chars": 4007,
"preview": "\"\"\"轨道类及其元数据\"\"\"\n\nimport uuid\n\nfrom enum import Enum\nfrom typing import TypeVar, Generic, Type\nfrom typing import Dict, Li"
},
{
"path": "src/pyJianYingDraft/util.py",
"chars": 1920,
"preview": "\"\"\"辅助函数,主要与模板模式有关\"\"\"\n\nimport inspect\n\nfrom typing import Union, Type\nfrom typing import List, Dict, Any\n\nJsonExportable "
},
{
"path": "src/pyJianYingDraft/video_segment.py",
"chars": 21224,
"preview": "\"\"\"定义视频片段及其相关类\n\n包含图像调节设置、动画效果、特效、转场等相关类\n\"\"\"\n\nimport uuid\nfrom copy import deepcopy\n\nfrom typing import Optional, Literal"
},
{
"path": "src/router/__init__.py",
"chars": 60,
"preview": "from .v1 import router as v1_router\n\n__all__ = [\"v1_router\"]"
},
{
"path": "src/router/v1.py",
"chars": 24692,
"preview": "from src.schemas.gen_video import GenVideoResponse\nfrom src.schemas.get_draft import GetDraftResponse\nfrom src.schemas.a"
},
{
"path": "src/schemas/__init__.py",
"chars": 713,
"preview": "from .create_draft import CreateDraftRequest, CreateDraftResponse\nfrom .add_videos import AddVideosRequest, AddVideosRes"
},
{
"path": "src/schemas/add_audios.py",
"chars": 1392,
"preview": "import json\nfrom pydantic import BaseModel, Field, field_validator\nfrom typing import List\n\n\nclass AddAudiosRequest(Base"
},
{
"path": "src/schemas/add_captions.py",
"chars": 3986,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional\n\n\nclass ShadowInfo(BaseModel):\n \"\"\"文本阴影参数\"\"\"\n"
},
{
"path": "src/schemas/add_effects.py",
"chars": 783,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List\n\n\nclass AddEffectsRequest(BaseModel):\n \"\"\"添加特效请求参数\"\"\"\n "
},
{
"path": "src/schemas/add_filters.py",
"chars": 869,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List\n\n\nclass AddFiltersRequest(BaseModel):\n \"\"\"添加滤镜请求参数\"\"\"\n "
},
{
"path": "src/schemas/add_images.py",
"chars": 2066,
"preview": "import json\nfrom pydantic import BaseModel, Field, field_validator\nfrom typing import List, Dict, Any\n\n\nclass AddImagesR"
},
{
"path": "src/schemas/add_keyframes.py",
"chars": 917,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List\n\n\nclass AddKeyframesRequest(BaseModel):\n \"\"\"添加关键帧请求参数\"\""
},
{
"path": "src/schemas/add_masks.py",
"chars": 1122,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List\n\n\nclass AddMasksRequest(BaseModel):\n \"\"\"添加遮罩请求参数\"\"\"\n "
},
{
"path": "src/schemas/add_sticker.py",
"chars": 922,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List\n\nclass AddStickerRequest(BaseModel):\n \"\"\"添加贴纸请求参数\"\"\"\n "
},
{
"path": "src/schemas/add_text_style.py",
"chars": 555,
"preview": "from pydantic import BaseModel, Field\n\n\nclass AddTextStyleRequest(BaseModel):\n \"\"\"创建文本富文本样式请求参数\"\"\"\n text: str = Fi"
},
{
"path": "src/schemas/add_videos.py",
"chars": 2378,
"preview": "import json\nfrom pydantic import BaseModel, Field, field_validator\nfrom typing import List, Optional\n\n\nclass SceneTimeli"
},
{
"path": "src/schemas/audio_infos.py",
"chars": 547,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional, Any\nfrom .audio_timelines import TimelineItem\n\n"
},
{
"path": "src/schemas/audio_timelines.py",
"chars": 552,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional\n\n\nclass AudioTimelinesRequest(BaseModel):\n \"\""
},
{
"path": "src/schemas/caption_infos.py",
"chars": 1411,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional\nfrom .audio_timelines import TimelineItem\n\n\nclas"
},
{
"path": "src/schemas/create_draft.py",
"chars": 409,
"preview": "from pydantic import BaseModel, Field\n\n\nclass CreateDraftRequest(BaseModel):\n \"\"\"创建草稿请求参数\"\"\"\n height: int = Field("
},
{
"path": "src/schemas/easy_create_material.py",
"chars": 1632,
"preview": "from pydantic import BaseModel, Field, field_validator\nfrom typing import Optional\n\n\nclass EasyCreateMaterialRequest(Bas"
},
{
"path": "src/schemas/effect_infos.py",
"chars": 404,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List\nfrom .audio_timelines import TimelineItem\n\n\nclass EffectIn"
},
{
"path": "src/schemas/filter_infos.py",
"chars": 782,
"preview": "from pydantic import BaseModel, Field, field_validator\nfrom typing import List, Optional\nfrom .audio_timelines import Ti"
},
{
"path": "src/schemas/gen_video.py",
"chars": 719,
"preview": "import uuid\nfrom pydantic import BaseModel, Field\nfrom pydantic.functional_validators import field_validator\nfrom typing"
},
{
"path": "src/schemas/gen_video_active_count.py",
"chars": 216,
"preview": "\"\"\"云渲染进行中数量查询\"\"\"\nfrom pydantic import BaseModel, Field\n\n\nclass GenVideoActiveCountResponse(BaseModel):\n \"\"\"当前排队与渲染中的云"
},
{
"path": "src/schemas/gen_video_status.py",
"chars": 869,
"preview": "\"\"\"\n视频生成状态查询的数据模型定义\n\"\"\"\nfrom typing import Optional\nfrom pydantic import BaseModel, Field\n\n\nclass GenVideoStatusRequest("
},
{
"path": "src/schemas/get_audio_duration.py",
"chars": 698,
"preview": "from pydantic import BaseModel, Field, HttpUrl\n\n\nclass GetAudioDurationRequest(BaseModel):\n \"\"\"获取音频时长请求参数\"\"\"\n mp3_"
},
{
"path": "src/schemas/get_draft.py",
"chars": 315,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List\n\n\nclass GetDraftRequest(BaseModel):\n \"\"\"获取草稿请求参数\"\"\"\n "
},
{
"path": "src/schemas/get_effects.py",
"chars": 722,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional\n\n\nclass GetEffectsRequest(BaseModel):\n \"\"\"获取特"
},
{
"path": "src/schemas/get_filters.py",
"chars": 669,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional\n\n\nclass GetFiltersRequest(BaseModel):\n \"\"\"获取滤"
},
{
"path": "src/schemas/get_image_animations.py",
"chars": 1330,
"preview": "\"\"\"\n获取图片出入场动画的数据模型定义\n\"\"\"\nfrom typing import Literal, List, Dict, Any\nfrom pydantic import BaseModel, Field\n\n\nclass GetIm"
},
{
"path": "src/schemas/get_text_animations.py",
"chars": 1326,
"preview": "\"\"\"\n获取文字出入场动画的数据模型定义\n\"\"\"\nfrom typing import Literal, List, Dict, Any\nfrom pydantic import BaseModel, Field\n\n\nclass GetTe"
},
{
"path": "src/schemas/get_text_effects.py",
"chars": 586,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional\n\n\nclass GetTextEffectsRequest(BaseModel):\n \"\""
},
{
"path": "src/schemas/get_url.py",
"chars": 242,
"preview": "from pydantic import BaseModel, Field\n\n\nclass GetUrlRequest(BaseModel):\n \"\"\"提取链接请求参数\"\"\"\n output: str = Field(..., "
},
{
"path": "src/schemas/imgs_infos.py",
"chars": 1138,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional\nfrom .audio_timelines import TimelineItem\n\n\nclas"
},
{
"path": "src/schemas/keyframes_infos.py",
"chars": 1106,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional\n\n\nclass SegmentInfoItem(BaseModel):\n \"\"\"轨道数据项"
},
{
"path": "src/schemas/objs_to_str_list.py",
"chars": 415,
"preview": "from pydantic import BaseModel, Field\nfrom typing import List, Optional\n\n\nclass ObjItem(BaseModel):\n \"\"\"对象项\"\"\"\n ou"
},
{
"path": "src/schemas/save_draft.py",
"chars": 271,
"preview": "from pydantic import BaseModel, Field\n\n\nclass SaveDraftRequest(BaseModel):\n \"\"\"创建草稿请求参数\"\"\"\n draft_url: str = Field"
}
]
// ... and 142 more files (download for full content)
About this extraction
This page contains the full source code of the Hommy-master/capcut-mate GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 342 files (136.6 MB), approximately 893.5k tokens, and a symbol index with 1154 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.