pycapcut 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pycapcut-0.0.1/PKG-INFO +77 -0
- pycapcut-0.0.1/README.md +506 -0
- pycapcut-0.0.1/pycapcut/__init__.py +276 -0
- pycapcut-0.0.1/pycapcut/animation.py +140 -0
- pycapcut-0.0.1/pycapcut/assets/__init__.py +45 -0
- pycapcut-0.0.1/pycapcut/assets/draft_content_template.json +132 -0
- pycapcut-0.0.1/pycapcut/assets/draft_meta_info.json +73 -0
- pycapcut-0.0.1/pycapcut/audio_segment.py +225 -0
- pycapcut-0.0.1/pycapcut/draft_folder.py +153 -0
- pycapcut-0.0.1/pycapcut/effect_segment.py +36 -0
- pycapcut-0.0.1/pycapcut/exceptions.py +23 -0
- pycapcut-0.0.1/pycapcut/jianying_controller.py +230 -0
- pycapcut-0.0.1/pycapcut/keyframe.py +94 -0
- pycapcut-0.0.1/pycapcut/local_materials.py +198 -0
- pycapcut-0.0.1/pycapcut/metadata/__init__.py +51 -0
- pycapcut-0.0.1/pycapcut/metadata/audio_scene_effect.py +252 -0
- pycapcut-0.0.1/pycapcut/metadata/effect_meta.py +191 -0
- pycapcut-0.0.1/pycapcut/metadata/filter_meta.py +603 -0
- pycapcut-0.0.1/pycapcut/metadata/font_meta.py +341 -0
- pycapcut-0.0.1/pycapcut/metadata/mask_meta.py +15 -0
- pycapcut-0.0.1/pycapcut/metadata/speech_to_song.py +12 -0
- pycapcut-0.0.1/pycapcut/metadata/text_intro.py +152 -0
- pycapcut-0.0.1/pycapcut/metadata/text_loop.py +105 -0
- pycapcut-0.0.1/pycapcut/metadata/text_outro.py +105 -0
- pycapcut-0.0.1/pycapcut/metadata/tone_effect.py +107 -0
- pycapcut-0.0.1/pycapcut/metadata/transition_meta.py +733 -0
- pycapcut-0.0.1/pycapcut/metadata/video_character_effect.py +1913 -0
- pycapcut-0.0.1/pycapcut/metadata/video_group_animation.py +131 -0
- pycapcut-0.0.1/pycapcut/metadata/video_intro.py +103 -0
- pycapcut-0.0.1/pycapcut/metadata/video_outro.py +80 -0
- pycapcut-0.0.1/pycapcut/metadata/video_scene_effect.py +7706 -0
- pycapcut-0.0.1/pycapcut/script_file.py +808 -0
- pycapcut-0.0.1/pycapcut/segment.py +256 -0
- pycapcut-0.0.1/pycapcut/template_mode.py +221 -0
- pycapcut-0.0.1/pycapcut/text_segment.py +436 -0
- pycapcut-0.0.1/pycapcut/time_util.py +99 -0
- pycapcut-0.0.1/pycapcut/track.py +138 -0
- pycapcut-0.0.1/pycapcut/util.py +58 -0
- pycapcut-0.0.1/pycapcut/video_segment.py +526 -0
- pycapcut-0.0.1/pycapcut.egg-info/PKG-INFO +77 -0
- pycapcut-0.0.1/pycapcut.egg-info/SOURCES.txt +44 -0
- pycapcut-0.0.1/pycapcut.egg-info/dependency_links.txt +1 -0
- pycapcut-0.0.1/pycapcut.egg-info/requires.txt +5 -0
- pycapcut-0.0.1/pycapcut.egg-info/top_level.txt +1 -0
- pycapcut-0.0.1/setup.cfg +4 -0
- pycapcut-0.0.1/setup.py +26 -0
pycapcut-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: pycapcut
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: 轻量、灵活、易上手的Python CapCut草稿生成及导出工具,构建全自动化视频剪辑/混剪流水线
|
|
5
|
+
Home-page: https://github.com/GuanYixuan/pycapcut
|
|
6
|
+
Author: gary318
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Topic :: Multimedia :: Video
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: pymediainfo
|
|
13
|
+
Requires-Dist: imageio
|
|
14
|
+
Requires-Dist: uiautomation>=2; sys_platform == "win32"
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: classifier
|
|
17
|
+
Dynamic: description
|
|
18
|
+
Dynamic: description-content-type
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: requires-dist
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
24
|
+
### 轻量、灵活、易上手的Python CapCut草稿生成及导出工具,构建全自动视频剪辑/混剪流水线!
|
|
25
|
+
|
|
26
|
+
> 🧪 本项目正在从[PyJianYingDraft](https://github.com/GuanYixuan/pyJianYingDraft)进行迁移,欢迎⭐️此项目保持关注!
|
|
27
|
+
|
|
28
|
+
> 📢 欢迎加入[Discord服务器](https://discord.gg/WfHgGQvhyW)进行用法或新功能的讨论
|
|
29
|
+
|
|
30
|
+
## 使用思路
|
|
31
|
+

|
|
32
|
+
|
|
33
|
+
# 功能清单
|
|
34
|
+
|
|
35
|
+
### 模板模式
|
|
36
|
+
- ☑️ [加载](#加载模板)(未加密的)`draft_content.json`文件作为模板
|
|
37
|
+
- ☑️ [替换音视频片段的素材](#根据名称替换素材)
|
|
38
|
+
- ☑️ [修改文本片段的文本内容](#替换文本片段的内容)
|
|
39
|
+
- ☑️ [将模板草稿中的音视频/文本轨道整体导入到另一草稿中](#导入模板草稿中的轨道)
|
|
40
|
+
- ☑️ [提取模板中出现的贴纸/气泡/花字等元信息](#提取素材元数据)
|
|
41
|
+
|
|
42
|
+
### 批量导出
|
|
43
|
+
> ⚠️ 本模块正在迁移中,若有兴趣可参见[PyJianYingDraft中相应部分](https://github.com/GuanYixuan/pyJianYingDraft?tab=readme-ov-file#%E6%89%B9%E9%87%8F%E5%AF%BC%E5%87%BA%E8%8D%89%E7%A8%BF)
|
|
44
|
+
|
|
45
|
+
- ☑️ 控制剪映打开指定草稿
|
|
46
|
+
- ☑️ [导出草稿至指定位置](#批量导出草稿)
|
|
47
|
+
- ☑️ 调节导出分辨率和帧率
|
|
48
|
+
|
|
49
|
+
### 视频与图片
|
|
50
|
+
> ⚠️ 本模块与特效/滤镜/动画等相关的功能正在迁移中,若有兴趣可参见[PyJianYingDraft中相应部分](https://github.com/GuanYixuan/pyJianYingDraft?tab=readme-ov-file#%E8%A7%86%E9%A2%91%E4%B8%8E%E5%9B%BE%E7%89%87)
|
|
51
|
+
|
|
52
|
+
- ☑️ 添加本地视频/图片素材,并[自定义片段的时间、持续时长或播放速度](#素材截取与整体变速)
|
|
53
|
+
- ☑️ [视频整体调节](#视频整体调节)(旋转、缩放、亮度等)以及[关键帧生成](#关键帧)
|
|
54
|
+
- ☑️ 视频片段的[入场/出场/组合动画](#添加片段动画)
|
|
55
|
+
- ☑️ 添加[蒙版](#蒙版)、[片段特效](#添加片段特效)和[滤镜](#添加片段滤镜)
|
|
56
|
+
- ☑️ 视频背景填充[(示例代码)](demo.py)
|
|
57
|
+
### 贴纸
|
|
58
|
+
- ☑️ 根据元信息[添加贴纸](#提取素材元数据)
|
|
59
|
+
- ☑️ 贴纸的[关键帧](#关键帧)生成
|
|
60
|
+
### 音频
|
|
61
|
+
- ☑️ 添加本地音频素材,并[自定义片段的时间、持续时长或播放速度](#素材截取与整体变速)
|
|
62
|
+
- ☑️ 调整淡入淡出时长[(示例代码)](demo.py),调整音量[(示例代码)](demo.py)及其[关键帧](#关键帧)
|
|
63
|
+
- ☑️ 添加音频片段的[场景音效果](#添加片段特效),并设置参数
|
|
64
|
+
### 轨道
|
|
65
|
+
- ☑️ [添加轨道](#多轨道操作)以及[将片段添加到指定轨道](#多轨道操作)
|
|
66
|
+
- ☑️ 自定义视频/滤镜/特效轨道的[层级关系](#多轨道操作)
|
|
67
|
+
### 特效、滤镜和转场
|
|
68
|
+
- ☑️ 吸附于片段上的[特效](#添加片段特效)、[滤镜](#添加片段滤镜)和[动画](#添加片段动画)
|
|
69
|
+
- ☑️ 位于[独立轨道的特效和滤镜](#独立轨道上的特效和滤镜)
|
|
70
|
+
- ☑️ 添加转场[(示例代码)](demo.py),并自定义其时长
|
|
71
|
+
### 文本及字幕
|
|
72
|
+
- ☑️ [添加文本、设置字体及样式](#添加文本)、修改文本片段的[位置及旋转设置](#视频整体调节)
|
|
73
|
+
- ☑️ 文本的[关键帧](#关键帧)以及[动画](#添加片段动画)
|
|
74
|
+
- ☑️ 文字描边和文字背景
|
|
75
|
+
- ☑️ 文字气泡效果和花字效果[(示例代码)](demo.py)
|
|
76
|
+
- ☑️ 文本[自动换行](#文本自动换行),支持设置最大行宽
|
|
77
|
+
- ☑️ [导入`.srt`文件](#导入字幕)生成字幕并批量设置格式
|
pycapcut-0.0.1/README.md
ADDED
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
# pyCapCut
|
|
2
|
+
### 与[PyJianYingDraft](https://github.com/GuanYixuan/pyJianYingDraft)同源的轻量、灵活、易上手Python CapCut草稿生成及导出工具,构建全自动视频剪辑/混剪流水线!
|
|
3
|
+
|
|
4
|
+
> 🧪 本项目正在从[PyJianYingDraft](https://github.com/GuanYixuan/pyJianYingDraft)进行迁移,欢迎⭐️此项目保持关注!
|
|
5
|
+
|
|
6
|
+
> 📢 欢迎加入[Discord服务器](https://discord.gg/WfHgGQvhyW)进行用法或新功能的讨论
|
|
7
|
+
|
|
8
|
+
## 使用思路
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
# 功能清单
|
|
12
|
+
|
|
13
|
+
### 模板模式
|
|
14
|
+
- ☑️ [加载](#加载模板)(未加密的)`draft_content.json`文件作为模板
|
|
15
|
+
- ☑️ [替换音视频片段的素材](#根据名称替换素材)
|
|
16
|
+
- ☑️ [修改文本片段的文本内容](#替换文本片段的内容)
|
|
17
|
+
- ☑️ [将模板草稿中的音视频/文本轨道整体导入到另一草稿中](#导入模板草稿中的轨道)
|
|
18
|
+
- ☑️ [提取模板中出现的贴纸/气泡/花字等元信息](#提取素材元数据)
|
|
19
|
+
|
|
20
|
+
### 批量导出
|
|
21
|
+
> ⚠️ 本模块正在迁移中,若有兴趣可参见[PyJianYingDraft中相应部分](https://github.com/GuanYixuan/pyJianYingDraft?tab=readme-ov-file#%E6%89%B9%E9%87%8F%E5%AF%BC%E5%87%BA%E8%8D%89%E7%A8%BF)
|
|
22
|
+
|
|
23
|
+
- ☑️ 控制剪映打开指定草稿
|
|
24
|
+
- ☑️ [导出草稿至指定位置](#批量导出草稿)
|
|
25
|
+
- ☑️ 调节导出分辨率和帧率
|
|
26
|
+
|
|
27
|
+
### 视频与图片
|
|
28
|
+
> ⚠️ 本模块与特效/滤镜/动画等相关的功能正在迁移中,若有兴趣可参见[PyJianYingDraft中相应部分](https://github.com/GuanYixuan/pyJianYingDraft?tab=readme-ov-file#%E8%A7%86%E9%A2%91%E4%B8%8E%E5%9B%BE%E7%89%87)
|
|
29
|
+
|
|
30
|
+
- ☑️ 添加本地视频/图片素材,并[自定义片段的时间、持续时长或播放速度](#素材截取与整体变速)
|
|
31
|
+
- ☑️ [视频整体调节](#视频整体调节)(旋转、缩放、亮度等)以及[关键帧生成](#关键帧)
|
|
32
|
+
- ☑️ 视频片段的[入场/出场/组合动画](#添加片段动画)
|
|
33
|
+
- ☑️ 添加[蒙版](#蒙版)、[片段特效](#添加片段特效)和[滤镜](#添加片段滤镜)
|
|
34
|
+
- ☑️ 视频背景填充[(示例代码)](demo.py)
|
|
35
|
+
### 贴纸
|
|
36
|
+
- ☑️ 根据元信息[添加贴纸](#提取素材元数据)
|
|
37
|
+
- ☑️ 贴纸的[关键帧](#关键帧)生成
|
|
38
|
+
### 音频
|
|
39
|
+
- ☑️ 添加本地音频素材,并[自定义片段的时间、持续时长或播放速度](#素材截取与整体变速)
|
|
40
|
+
- ☑️ 调整淡入淡出时长[(示例代码)](demo.py),调整音量[(示例代码)](demo.py)及其[关键帧](#关键帧)
|
|
41
|
+
- ☑️ 添加音频片段的[场景音效果](#添加片段特效),并设置参数
|
|
42
|
+
### 轨道
|
|
43
|
+
- ☑️ [添加轨道](#多轨道操作)以及[将片段添加到指定轨道](#多轨道操作)
|
|
44
|
+
- ☑️ 自定义视频/滤镜/特效轨道的[层级关系](#多轨道操作)
|
|
45
|
+
### 特效、滤镜和转场
|
|
46
|
+
- ☑️ 吸附于片段上的[特效](#添加片段特效)、[滤镜](#添加片段滤镜)和[动画](#添加片段动画)
|
|
47
|
+
- ☑️ 位于[独立轨道的特效和滤镜](#独立轨道上的特效和滤镜)
|
|
48
|
+
- ☑️ 添加转场[(示例代码)](demo.py),并自定义其时长
|
|
49
|
+
### 文本及字幕
|
|
50
|
+
- ☑️ [添加文本、设置字体及样式](#添加文本)、修改文本片段的[位置及旋转设置](#视频整体调节)
|
|
51
|
+
- ☑️ 文本的[关键帧](#关键帧)以及[动画](#添加片段动画)
|
|
52
|
+
- ☑️ 文字描边和文字背景
|
|
53
|
+
- ☑️ 文字气泡效果和花字效果[(示例代码)](demo.py)
|
|
54
|
+
- ☑️ 文本[自动换行](#文本自动换行),支持设置最大行宽
|
|
55
|
+
- ☑️ [导入`.srt`文件](#导入字幕)生成字幕并批量设置格式
|
|
56
|
+
|
|
57
|
+
# 快速上手
|
|
58
|
+
例程`demo.py`将创建包含音视频素材和一行文本的剪映草稿文件,并且添加了音频淡入、视频入场动画、转场效果和文本气泡/花字。
|
|
59
|
+
|
|
60
|
+
这个例程的操作方法如下:
|
|
61
|
+
1. 找到剪映的**草稿文件夹路径**(类似`.../JianyingPro Drafts`),用其替换代码中的`<你的草稿文件夹>`
|
|
62
|
+
2. 运行`demo.py`
|
|
63
|
+
3. 在剪映中**找到并打开新创建的`demo`草稿**(可能需要进入再退出某个已有草稿,或重启剪映以刷新草稿列表),你应该看到类似如下的时间轴:
|
|
64
|
+
|
|
65
|
+

|
|
66
|
+
|
|
67
|
+
> ⚠️ 由于项目元数据正在迁移中,demo目前会出现“动画丢失”和“转场丢失”的情况,若对完整效果感兴趣可参见[PyJianYingDraft中的快速上手部分](https://github.com/GuanYixuan/pyJianYingDraft?tab=readme-ov-file#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B)
|
|
68
|
+
|
|
69
|
+
你可以仔细检查音频片段的音量设置、淡入效果时长等,看看是否符合上述代码的设置
|
|
70
|
+
|
|
71
|
+
# 用法文档
|
|
72
|
+
|
|
73
|
+
> ℹ 文档部分推荐从[功能清单](#功能清单)一节中选取感兴趣的功能阅读,而非直接按顺序阅读
|
|
74
|
+
|
|
75
|
+
### 模板模式
|
|
76
|
+
为了保留部分复杂特性(文本特效、复合片段...),可以加载一个已有的剪映草稿作为模板,然后将其中内容导入到另一的草稿中,或直接**替换其中部分片段的内容**。
|
|
77
|
+
|
|
78
|
+
目前提供了**三种替换功能**:
|
|
79
|
+
- [根据名称替换素材](#根据名称替换素材):直接替换素材本身,自然影响所有引用该素材的片段
|
|
80
|
+
- [根据片段替换素材](#根据片段替换素材):替换某个特定片段的素材,同时重新选取其引用的素材范围
|
|
81
|
+
- [替换文本片段的内容](#替换文本片段的内容):保留所有文本格式,但替换其内容
|
|
82
|
+
|
|
83
|
+
除此之外,对于某些没有特定名称的特性(贴纸、花字等),提供了[提取素材元数据](#提取素材元数据)的功能以提取其`resource_id`
|
|
84
|
+
|
|
85
|
+
> ⚠️ 由于剪映6+版本对草稿文件进行了加密,故**暂不支持加载来自6+版本的草稿文件**作为模板
|
|
86
|
+
|
|
87
|
+
> ℹ 若出现模板内容丢失的情况,欢迎反馈
|
|
88
|
+
|
|
89
|
+
#### 加载模板
|
|
90
|
+
推荐使用`DraftFolder`来管理剪映的草稿文件夹(可以在剪映的`全局设置`-`草稿位置`中查询),这样能够方便地根据已有模板生成新草稿。
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
import pyJianYingDraft as draft
|
|
94
|
+
|
|
95
|
+
draft_folder = draft.DraftFolder("<剪映草稿文件夹>") # 一般形如 ".../JianyingPro Drafts"
|
|
96
|
+
script = draft_folder.duplicate_as_template("模板草稿", "新草稿") # 复制"模板草稿",并命名为"新草稿",同时打开新草稿供编辑
|
|
97
|
+
|
|
98
|
+
# 对返回的ScriptFile对象进行编辑,如替换素材、添加轨道、片段等
|
|
99
|
+
|
|
100
|
+
script.save() # 保存你的"新草稿"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
为了最大限度地兼容模板中的复杂特性,**导入的轨道与pyJianYingDraft创建的轨道是分离开的**,具体地讲:
|
|
104
|
+
|
|
105
|
+
- 除下述替换功能外,不能在导入的轨道上添加片段、转场、淡入淡出、特效等
|
|
106
|
+
- **仍然可以创建新的轨道,并在其上添加片段等**,就像非模板模式一样
|
|
107
|
+
|
|
108
|
+
> ℹ 导入轨道的限制也许会在后续版本中逐渐取消
|
|
109
|
+
|
|
110
|
+
#### 提取素材元数据
|
|
111
|
+
对导入的`ScriptFile`对象,可以调用`inspect_material`方法提取部分素材的`resource_id`。
|
|
112
|
+
`DraftFolder`也有相应的方法来提取指定草稿的素材元数据。
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import pyJianYingDraft as draft
|
|
116
|
+
|
|
117
|
+
draft_folder = draft.DraftFolder("<剪映草稿文件夹>")
|
|
118
|
+
draft_folder.inspect_material("草稿名称")
|
|
119
|
+
|
|
120
|
+
# 或者
|
|
121
|
+
script = draft_folder.load_template("草稿名称")
|
|
122
|
+
script.inspect_material()
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
上述代码的输出可能类似于
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
贴纸素材:
|
|
129
|
+
Resource id: 7405878923323641129 '秋日手绘-枫叶'
|
|
130
|
+
Resource id: 7429353555447893260 '电商购物促销/哇哦'
|
|
131
|
+
Resource id: 7437707455267671315 '冬日涂鸦winter雪花冬天vlog装饰文字'
|
|
132
|
+
Resource id: 7343931192204463401 '爱心'
|
|
133
|
+
文字气泡效果:
|
|
134
|
+
Effect id: 763870 ,Resource id: 6838834573413978631 '标题59'
|
|
135
|
+
花字效果:
|
|
136
|
+
Resource id: 7342020000812731658 '彩色手绘线条花字'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
其中的元数据可用于添加相应素材(例如通过`StickerSegment`的`resource_id`参数)
|
|
140
|
+
|
|
141
|
+
#### 根据名称替换素材
|
|
142
|
+
这种方法将替换素材本身,而不对片段进行直接修改。
|
|
143
|
+
|
|
144
|
+
> ℹ 由于素材有名称(默认是本地文件的名称),这种替换方式的定位比较方便
|
|
145
|
+
|
|
146
|
+
> ℹ 由于不涉及时间范围的修改,这种替换方式**尤其适合图像素材**,且几乎不会产生兼容性的问题
|
|
147
|
+
|
|
148
|
+
以[快速上手](#快速上手)中的草稿为例,假如我们希望换用新的音频素材,可以:
|
|
149
|
+
```python
|
|
150
|
+
new_material = draft.AudioMaterial("<新的音频素材路径>")
|
|
151
|
+
script.replace_material_by_name("audio.mp3", new_material) # 替换名称为"audio.mp3"的素材
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
替换新素材后,片段所截取的部分仍是素材前5秒,且音量、淡入淡出、播放速度等仍保持不变。
|
|
155
|
+
|
|
156
|
+
#### 根据片段替换素材
|
|
157
|
+
这种方法将替换某个**特定片段**的素材,同时可以**重新选取其引用的素材范围**并**根据新时长在时间轴上伸缩片段**。
|
|
158
|
+
|
|
159
|
+
> ℹ 由于片段没有名称,故通常需要**依靠片段的下标来定位**
|
|
160
|
+
|
|
161
|
+
此过程分为两步:**选取轨道**和**替换素材**,以上方音频素材的替换为例:
|
|
162
|
+
```python
|
|
163
|
+
from pyJianYingDraft import trange, ShrinkMode, ExtendMode
|
|
164
|
+
|
|
165
|
+
audio_track = script.get_imported_track(
|
|
166
|
+
draft.TrackType.audio, # 选取导入的音频轨道
|
|
167
|
+
#name="audio", # 假如轨道有名称,最好利用名称来定位
|
|
168
|
+
index=0 # 也可用下标定位, 0表示最底层的同类型轨道
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
script.replace_material_by_seg(
|
|
172
|
+
audio_track, 0, new_material, # 选取audio_track中下标为0的片段,也即第一个片段
|
|
173
|
+
#source_timerange=None, # 若不指定,则默认使用整个素材
|
|
174
|
+
source_timerange=trange("0s", "10s"), # 此处指定截取素材前10秒(注意原片段时长为5秒)
|
|
175
|
+
handle_shrink=ShrinkMode.cut_tail, # 片段若要缩短,则依靠前移终止点来实现
|
|
176
|
+
handle_extend=ExtendMode.push_tail # 片段若要延长,则依靠后移终止点来实现,必要时允许后移后续片段
|
|
177
|
+
)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
从例子中可见,此替换方法可能会造成片段的时长变化,故可以利用`handle_shrink`和`handle_extend`参数指定片段在缩短和延长时的处理方式。
|
|
181
|
+
|
|
182
|
+
> ℹ 不显式指定`handle_shrink`和`handle_extend`时,默认的处理方式如下:
|
|
183
|
+
> - 新素材比原素材短,则前移片段终止点,使得片段长度与新素材长度一致
|
|
184
|
+
> - 新素材比原素材长,则裁剪素材范围,保持片段原长不变
|
|
185
|
+
|
|
186
|
+
具体的处理方式列表可参见枚举类`ShrinkMode`和`ExtendMode`的定义。
|
|
187
|
+
|
|
188
|
+
> ℹ 目前已知替换带有组合出入场动画的片段不会自动刷新动画时间
|
|
189
|
+
|
|
190
|
+
#### 替换文本片段的内容
|
|
191
|
+
这种方法将替换某个**特定文本片段**的内容,但保留其所有格式。
|
|
192
|
+
|
|
193
|
+
此过程同样分为**选取轨道**和**替换内容**两个步骤:其中“选取轨道”可参考[根据片段替换素材](#根据片段替换素材)中的示例。
|
|
194
|
+
|
|
195
|
+
以下假定我们已经选取了合适的文本轨道`text_track`,则只需:
|
|
196
|
+
```python
|
|
197
|
+
script.replace_text(
|
|
198
|
+
text_track, 0, # 选取text_track中下标为0的片段,也即第一个片段
|
|
199
|
+
"新文本内容" # 新的文本内容
|
|
200
|
+
)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### 导入模板草稿中的轨道
|
|
204
|
+
|
|
205
|
+
此功能会字面意义地复制模板草稿中的指定轨道到新草稿中, 适合用于拼接多个模板草稿。
|
|
206
|
+
|
|
207
|
+
> ℹ **目前仅支持导入音视频/文本轨道**, 支持的范围将来会继续扩展
|
|
208
|
+
|
|
209
|
+
> ⚠️ 本方法会保留各片段及其素材的id, 因而**不支持向同一草稿多次导入同一轨道**
|
|
210
|
+
|
|
211
|
+
例如
|
|
212
|
+
```python
|
|
213
|
+
source_script = draft_folder.load_template("<模板草稿名称>") # 加载模板草稿
|
|
214
|
+
target_script = draft_folder.create_draft("新草稿", 1920, 1080) # 创建新草稿
|
|
215
|
+
|
|
216
|
+
# 选取模板中的一个文本轨道
|
|
217
|
+
text_track = source_script.get_imported_track(
|
|
218
|
+
draft.TrackType.text, # 选取导入的文本轨道
|
|
219
|
+
#name="text", # 假如轨道有名称,最好利用名称来定位
|
|
220
|
+
index=0 # 也可用下标定位, 0表示最底层的同类型轨道
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
# 导入文本轨道到新草稿
|
|
224
|
+
target_script.import_track(
|
|
225
|
+
source_script, text_track,
|
|
226
|
+
offset=target_script.duration, # 导入的轨道将放在新草稿末尾
|
|
227
|
+
new_name="imported_text", # 可选的新轨道名
|
|
228
|
+
relative_index=1, # 相对于所有文本轨道的位置, 值越大越接近前景, 可以是负数
|
|
229
|
+
)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 批量导出草稿
|
|
233
|
+
作为整个自动化流程中的最后一步,本项目提供了基础的草稿批量导出功能。
|
|
234
|
+
|
|
235
|
+
> ⚠️ 剪映7+版本对控件进行了隐藏,故本功能目前**仅支持剪映6及以下版本**
|
|
236
|
+
|
|
237
|
+
> ⚠️ 本部分功能依赖于`uiautomation`库,故目前**仅支持在Windows系统下运行**
|
|
238
|
+
|
|
239
|
+
> ℹ 导出程序会将剪映窗口置顶,且需要控制光标进行点击,**建议在闲时/夜间运行**
|
|
240
|
+
|
|
241
|
+
> ℹ 本部分功能**在剪映专业版5.9和6.8中测试通过**
|
|
242
|
+
|
|
243
|
+
> ℹ 有用户反映部分Python版本(如3.13)下`uiautomation`会出现依赖问题, 推荐使用3.8、3.10或3.11, [详见此处](https://github.com/GuanYixuan/pyJianYingDraft/issues/12)
|
|
244
|
+
|
|
245
|
+
> ⚠️ 请**确认有导出草稿的相关权限(不使用VIP功能或已开通VIP)**, 否则可能陷入死循环
|
|
246
|
+
|
|
247
|
+
导出利用`JianyingController`类进行,具体用法如下:
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
import pyJianYingDraft as draft
|
|
251
|
+
from pyJianYingDraft import ExportResolution, ExportFramerate
|
|
252
|
+
|
|
253
|
+
# 此前需要将剪映打开,并位于目录页
|
|
254
|
+
ctrl = draft.JianyingController()
|
|
255
|
+
|
|
256
|
+
# 然后即可导出指定名称的草稿, 注意导出结束后视频才会被剪切(重命名)至指定位置
|
|
257
|
+
ctrl.export_draft("要导出的草稿名称", "<导出路径>") # "导出路径"可以指向文件夹或直接指向文件
|
|
258
|
+
|
|
259
|
+
# 若希望调节分辨率或帧率, 可使用`resolution`和`framerate`参数
|
|
260
|
+
ctrl.export_draft("要导出的草稿名称", "<导出路径>",
|
|
261
|
+
resolution=ExportResolution.RES_1080P,
|
|
262
|
+
framerate=ExportFramerate.FR_24)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
重复上述单次导出操作即可实现批量导出,类似如下代码:
|
|
266
|
+
```python
|
|
267
|
+
draft_names = ...
|
|
268
|
+
export_folder = ...
|
|
269
|
+
for name in draft_names:
|
|
270
|
+
ctrl.export_draft(name, os.path.join(export_folder, name, ".mp4"))
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### 时间与轨道
|
|
274
|
+
|
|
275
|
+
#### 时间格式
|
|
276
|
+
**剪映(和本项目)内部均采用微秒为单位保存时间**,但这不便于输入,故我们增加了一种“字符串形式”的时间,大部分时间参数均同时支持这两种形式:
|
|
277
|
+
- 微秒形式:用`int`表达,适于计算
|
|
278
|
+
- 字符串形式:用`str`表达,如`"1.5s"`、`"1h3m12s"`等,易于输入
|
|
279
|
+
|
|
280
|
+
如果你希望显式地将字符串形式转换为微秒形式,可以使用`tim`函数;`trange`函数则是支持字符串形式输入的`Timerange`便捷构造函数。
|
|
281
|
+
|
|
282
|
+
> ⚠️ 注意`trange`的第二个参数是**持续时长**,而不是结束时间
|
|
283
|
+
|
|
284
|
+
例如:
|
|
285
|
+
```python
|
|
286
|
+
import pyJianYingDraft as draft
|
|
287
|
+
from pyJianYingDraft import SEC, tim, trange
|
|
288
|
+
|
|
289
|
+
# 1秒钟
|
|
290
|
+
assert 1000000 == SEC == tim("1s") == tim("0.01666667m")
|
|
291
|
+
|
|
292
|
+
# 0~1分钟
|
|
293
|
+
assert draft.Timerange(0, 60*SEC) == trange("0s", "1m") == trange("0s", "0.5m30s")
|
|
294
|
+
|
|
295
|
+
# 片段开始后2秒
|
|
296
|
+
seg: draft.VideoSegment
|
|
297
|
+
assert seg.target_timerange.start + 2*SEC == seg.target_timerange.start + tim("2s")
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
#### 素材截取与整体变速
|
|
301
|
+
截取和变速均在`Segment`创建时设置完成,具体是通过`target_timerange`、`source_timerange`和`speed`参数来共同实现的。
|
|
302
|
+
> ℹ 目前暂不支持设置曲线变速
|
|
303
|
+
|
|
304
|
+
以下以`VideoSegment`为例,`AudioSegment`的用法相同,此二者支持两种构造方式:
|
|
305
|
+
1. **便捷构造**:直接传入素材路径字符串,自动构造素材实例
|
|
306
|
+
2. **传统构造**:先创建素材实例,再传入片段构造函数。**若需要设置素材的图像裁剪属性请使用此方式**
|
|
307
|
+
|
|
308
|
+
```python
|
|
309
|
+
import os
|
|
310
|
+
import pyJianYingDraft as draft
|
|
311
|
+
from pyJianYingDraft import trange, SEC
|
|
312
|
+
|
|
313
|
+
# 假定已有草稿文件script(参见“快速上手”),创建三个轨道
|
|
314
|
+
for i in range(3, 0, -1): # 倒序
|
|
315
|
+
script.add_track(draft.TrackType.video, "%d" % i)
|
|
316
|
+
|
|
317
|
+
# 以下部分讲解素材与片段的创建
|
|
318
|
+
# 方式一:便捷构造(推荐)
|
|
319
|
+
tutorial_asset_dir = os.path.join(os.path.dirname(__file__), 'readme_assets', 'tutorial')
|
|
320
|
+
video_path = os.path.join(tutorial_asset_dir, 'video.mp4')
|
|
321
|
+
|
|
322
|
+
# 直接传入素材路径
|
|
323
|
+
seg1 = draft.VideoSegment(video_path, trange("0s", "4s")) # 截取素材的前4秒
|
|
324
|
+
|
|
325
|
+
# 方式二:传统构造
|
|
326
|
+
mat = draft.VideoMaterial(video_path) # 先创建素材实例
|
|
327
|
+
seg2 = draft.VideoSegment(mat, trange("0s", "4s")) # 再传入片段构造函数
|
|
328
|
+
|
|
329
|
+
# 视频素材长度为 5s
|
|
330
|
+
print("Video material length: %f s" % (mat.duration / SEC))
|
|
331
|
+
|
|
332
|
+
# 以下部分讲解素材的时间截取与变速
|
|
333
|
+
# 不指定source_timerange,则自动从头截取素材等长片段
|
|
334
|
+
seg11 = draft.VideoSegment(video_path, trange("0s", "4s")) # 自动截取素材的前4秒(4s表示持续时长)
|
|
335
|
+
seg2 = draft.VideoSegment(video_path, trange("0s", "4s"), speed=1.25) # 自动截取素材的前4*1.25=5秒
|
|
336
|
+
seg4 = draft.VideoSegment(video_path, trange("0s", "3s"), speed=3.0) # 截取前3*3.0=9秒,素材不够长故报错
|
|
337
|
+
|
|
338
|
+
# 指定source_timerange,则截取素材的指定片段,自动设置速度
|
|
339
|
+
seg12 = draft.VideoSegment(video_path, trange("4s", "1s"),
|
|
340
|
+
source_timerange=trange(0, "4s")) # 将素材在1s内放完,速度自动设置为5.0
|
|
341
|
+
|
|
342
|
+
# 同时指定source_timerange和speed,则截取素材的指定片段,并根据播放速度覆盖target_timerange的duration
|
|
343
|
+
seg3 = draft.VideoSegment(video_path, trange("1s", "66666h"),
|
|
344
|
+
source_timerange=trange(0, "5s"),
|
|
345
|
+
speed=2.0) # 将长5s的素材按2倍速放完,target_timerange的duration自动设为2.5s
|
|
346
|
+
|
|
347
|
+
# 将片段加入轨道
|
|
348
|
+
script.add_segment(seg11, "1").add_segment(seg12, "1")
|
|
349
|
+
script.add_segment(seg2, "2")
|
|
350
|
+
script.add_segment(seg3, "3")
|
|
351
|
+
|
|
352
|
+
# 保存草稿
|
|
353
|
+
script.dump("*你的草稿工程文件夹*/draft_content.json")
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
#### 多轨道操作
|
|
357
|
+
目前`ScriptFile.add_track`方法已支持创建多个同类型轨道,并支持自定义其顺序:
|
|
358
|
+
```python
|
|
359
|
+
script.add_track(draft.TrackType.video,
|
|
360
|
+
track_name="前景", # 轨道名
|
|
361
|
+
relative_index=2) # 在所有视频轨道中的相对位置
|
|
362
|
+
script.add_track(draft.TrackType.video,
|
|
363
|
+
track_name="背景",
|
|
364
|
+
relative_index=1) # 由于1<2,所以前景轨道位于更上方
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
> ℹ 对于相同index的轨道,默认**后创建的轨道位于上方**
|
|
368
|
+
|
|
369
|
+
一旦创建了多个同类轨道,则在添加片段时必须指定目标轨道,例如:
|
|
370
|
+
```python
|
|
371
|
+
script.add_segment(video_segment, "背景")
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### 视频整体调节
|
|
375
|
+
每个视频片段都可以单独设置裁剪、旋转、翻转、缩放、透明度、亮度等属性,这些设置通过`VideoSegment`构造函数中的`clip_settings`参数传入
|
|
376
|
+
> ℹ 关键帧的优先级高于整体调节,故前者会覆盖后者的相应设置
|
|
377
|
+
|
|
378
|
+
下方的例子将创建一个视频片段,并设置其不透明度为0.5、打开水平翻转:
|
|
379
|
+
```python
|
|
380
|
+
from pyJianYingDraft import ClipSettings
|
|
381
|
+
video_segment = draft.VideoSegment(video_material,
|
|
382
|
+
draft.Timerange(0, video_material.duration), # 与素材等长
|
|
383
|
+
clip_settings=ClipSettings(alpha=0.5, # 不透明度为0.5
|
|
384
|
+
flip_horizontal=True) # 打开水平翻转
|
|
385
|
+
)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
更具体的参数说明可参见`ClipSettings`的构造函数。
|
|
389
|
+
|
|
390
|
+
### 关键帧
|
|
391
|
+
关键帧是吸附在**片段**上的“时刻-数值”对,所以创建关键帧只需要在`add_keyframe`方法中指定**相对片段头部的**时刻、数值以及控制的属性即可。
|
|
392
|
+
> ℹ 目前不支持设置特效或滤镜参数的关键帧
|
|
393
|
+
|
|
394
|
+
下方的例子尝试使用两个不透明度关键帧模拟视频的淡出效果:
|
|
395
|
+
```python
|
|
396
|
+
import os
|
|
397
|
+
import pyJianYingDraft as draft
|
|
398
|
+
from pyJianYingDraft import KeyframeProperty, SEC
|
|
399
|
+
|
|
400
|
+
# 假定已有草稿文件script(参见“快速上手”),创建视频轨道
|
|
401
|
+
script.add_track(draft.TrackType.video)
|
|
402
|
+
tutorial_asset_dir = os.path.join(os.path.dirname(__file__), 'readme_assets', 'tutorial')
|
|
403
|
+
|
|
404
|
+
# 创建视频片段
|
|
405
|
+
video_material = draft.VideoMaterial(os.path.join(tutorial_asset_dir, 'video.mp4'))
|
|
406
|
+
video_segment = draft.VideoSegment(video_material,
|
|
407
|
+
draft.Timerange(0, video_material.duration)) # 与素材等长
|
|
408
|
+
|
|
409
|
+
# 添加两个不透明度关键帧形成1s的淡出效果
|
|
410
|
+
video_segment.add_keyframe(KeyframeProperty.alpha, video_segment.duration - SEC, 1.0) # 结束前1s完全不透明
|
|
411
|
+
video_segment.add_keyframe(KeyframeProperty.alpha, video_segment.duration, 0.0) # 片段结束时完全透明
|
|
412
|
+
|
|
413
|
+
# 添加片段到轨道
|
|
414
|
+
script.add_segment(video_segment)
|
|
415
|
+
|
|
416
|
+
# 保存草稿
|
|
417
|
+
script.dump("*你的草稿工程文件夹*/draft_content.json")
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
除了`alpha`外,`KeyframeProperty`中还有平移、旋转、缩放、音量、饱和度等属性,它们都可以设置关键帧。
|
|
421
|
+
文本和贴纸片段的关键帧也可以用相同方法进行设置,但注意它们只支持位置和大小相关的那些属性。
|
|
422
|
+
|
|
423
|
+
对音频片段,目前只能设置音量的关键帧,此时你不需要指定`KeyframeProperty`
|
|
424
|
+
```python
|
|
425
|
+
audio_segment: draft.AudioSegment
|
|
426
|
+
audio_segment.add_keyframe("0s", 0.6) # 片段开始时的音量为60%
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### 蒙版
|
|
430
|
+
蒙版的添加非常简单:调用`VideoSegment`的`add_mask`方法即可:
|
|
431
|
+
```python
|
|
432
|
+
from pyJianYingDraft import MaskType
|
|
433
|
+
|
|
434
|
+
# 添加一个线性蒙版,中心点在素材的(100, 0)像素处,顺时针旋转45度
|
|
435
|
+
video_segment1.add_mask(MaskType.线性, center_x=100, rotation=45)
|
|
436
|
+
# 添加一个圆形蒙版,直径占素材的50%
|
|
437
|
+
video_segment2.add_mask(MaskType.圆形, size=0.5)
|
|
438
|
+
```
|
|
439
|
+
其中:
|
|
440
|
+
- `MaskType`保存了剪映自带的蒙版类型
|
|
441
|
+
- `center_x`和`center_y`参数表示蒙版中心点的坐标,与剪映中意义一致
|
|
442
|
+
- `rotation`、`feather`、`round_corner`分别表示旋转、羽化、圆角参数,与剪映中意义一致
|
|
443
|
+
- `size`参数表示蒙版的“主要尺寸”(镜面的可视部分高度/圆形直径/爱心高度等)占素材的比例
|
|
444
|
+
|
|
445
|
+
更具体的参数说明请参见`add_mask`方法的注释。
|
|
446
|
+
|
|
447
|
+
### 文本及字幕
|
|
448
|
+
#### 添加文本
|
|
449
|
+
添加文本与添加视频/音频片段类似,只需创建`TextSegment`对象并利用`add_segment`添加到`ScriptFile`中即可。
|
|
450
|
+
其**字体**、**文字样式**及**图像调节**设置可分别通过`font`, `style`和`clip_settings`参数设置。
|
|
451
|
+
|
|
452
|
+
例如:
|
|
453
|
+
```python
|
|
454
|
+
import pyJianYingDraft as draft
|
|
455
|
+
from pyJianYingDraft import FontType, TextStyle, ClipSettings
|
|
456
|
+
|
|
457
|
+
# 带下划线、位置及大小类似字幕的浅蓝色文本
|
|
458
|
+
seg1 = draft.TextSegment("Subtitle", trange("0s", "10s"),
|
|
459
|
+
font=FontType.文轩体,
|
|
460
|
+
style=TextStyle(size=5.0, color=(0.7, 0.7, 1.0), underline=True, align=1),
|
|
461
|
+
clip_settings=ClipSettings(transform_y=-0.8))
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
更具体的参数说明可参见`TextStyle`和`ClipSettings`的构造函数。
|
|
465
|
+
|
|
466
|
+
#### 文本自动换行
|
|
467
|
+
文本片段支持自动换行功能,可以通过`TextStyle`的`auto_wrapping`和`max_line_width`参数来控制:
|
|
468
|
+
|
|
469
|
+
```python
|
|
470
|
+
# 启用自动换行,设置最大行宽为屏幕宽度的70%
|
|
471
|
+
seg2 = draft.TextSegment("这是一段很长的文本内容,当超过设定的最大行宽时会自动换行显示",
|
|
472
|
+
trange("0s", "10s"),
|
|
473
|
+
font=FontType.文轩体,
|
|
474
|
+
style=TextStyle(size=5.0,
|
|
475
|
+
auto_wrapping=True, # 启用自动换行
|
|
476
|
+
max_line_width=0.7)) # 最大行宽占屏幕70%
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
#### 导入字幕
|
|
480
|
+
> ℹ 目前只支持导入**SRT格式**的字幕文件
|
|
481
|
+
|
|
482
|
+
导入字幕本质上是根据每条字幕的时间戳及内容创建一系列文本,并添加到轨道中。这一过程通过`ScriptFile.import_srt`来实现。
|
|
483
|
+
导入的字幕默认启用自动换行功能。
|
|
484
|
+
|
|
485
|
+
例如:
|
|
486
|
+
```python
|
|
487
|
+
import pyJianYingDraft as draft
|
|
488
|
+
|
|
489
|
+
# 假定已有草稿文件script(参见“快速上手”)
|
|
490
|
+
|
|
491
|
+
# 将字幕导入到名为"subtitle"的轨道中,若轨道不存在将自动创建
|
|
492
|
+
# 不指定style和clip_settings,则默认模拟剪映导入字幕时的样式
|
|
493
|
+
script.import_srt("subtitle.srt", track_name="subtitle", time_offset="1.5s") # 字幕整体后移1.5秒
|
|
494
|
+
|
|
495
|
+
# 可以利用`text_style`和`clip_settings`参数对字幕的样式进行调整, 上述参数的意义与`TextSegment()`中的相同
|
|
496
|
+
script.import_srt("subtitle.srt", track_name="subtitle",
|
|
497
|
+
text_style=draft.TextStyle(size=10.0, color=(1.0, 0.0, 0.0))
|
|
498
|
+
clip_settings=draft.ClipSettings(transform_y=0.8)) # 将字幕放置在屏幕上方
|
|
499
|
+
|
|
500
|
+
# 如果需要更复杂的样式或希望为字幕应用动画,可以为`style_reference`参数传入一个`TextSegment`对象作为样式参考(忽略其文本和片段长度设置)
|
|
501
|
+
# 注意动画时间不会根据字幕片段长度进行调节,故当字幕片段过短时可能出现奇怪的效果
|
|
502
|
+
script.import_srt("subtitle.srt", track_name="subtitle", style_reference=seg1) # 以上一节“添加文本”中的文本作为参考
|
|
503
|
+
|
|
504
|
+
# 默认不会采用`style_reference`片段中的`clip_settings`设置,如果需要的话请显式传入`clip_settings=None`
|
|
505
|
+
script.import_srt("subtitle.srt", track_name="subtitle", style_reference=seg1, clip_settings=None) # 相当于clip_settings=seg1.clip_settings
|
|
506
|
+
```
|