[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-72315":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":22,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":31,"readmeContent":32,"aiSummary":33,"trendingCount":16,"starSnapshotCount":16,"syncStatus":34,"lastSyncTime":35,"discoverSource":36},72315,"pyJianYingDraft","GuanYixuan\u002FpyJianYingDraft","GuanYixuan","轻量、灵活、易上手的Python剪映草稿生成及导出工具，构建全自动化视频剪辑\u002F混剪流水线。本项目的CapCut版本正于 https:\u002F\u002Fgithub.com\u002FGuanYixuan\u002FpyCapCut 内开发","",null,"Python",3427,589,23,49,0,3,40,187,21,93.31,false,"main",[25,26,27,28,29,30],"api","automation","capcut","jianying","video-editing","video-production","2026-06-12 04:01:04","# pyJianYingDraft\n### 轻量、灵活、易上手的Python剪映草稿生成及导出工具，构建全自动视频剪辑\u002F混剪流水线！\n\n> 🧪 本项目的**CapCut版本**正在开发中，欢迎关注[CapCut版本仓库](https:\u002F\u002Fgithub.com\u002FGuanYixuan\u002FpyCapCut)\n\n> 📢 欢迎加入[Discord服务器](https:\u002F\u002Fdiscord.gg\u002FWfHgGQvhyW)进行用法或新功能的讨论\n\n## 使用思路\n![使用思路](readme_assets\u002F使用思路.jpg)\n\n# 功能清单\n> ℹ 如未额外注明，一般仅在5.9版本上测试过\n\n> 标注☑️的特性**已实现**，标注⬜的特性**待实现**\n\n### 模板模式\n> ⚠️ 剪映6+版本对`draft_content.json`文件进行了加密，故**本系列功能目前仅支持剪映5.9及以下版本**\n\n> ℹ 欢迎为本项目补充6+版本草稿文件的解密方式\n\n- ☑️ [加载](#加载模板)（未加密的）`draft_content.json`文件作为模板\n- ☑️ [替换音视频片段的素材](#根据名称替换素材)\n- ☑️ [修改文本片段的文本内容](#替换文本片段的内容)\n- ☑️ [将模板草稿中的音视频\u002F文本轨道整体导入到另一草稿中](#导入模板草稿中的轨道)\n- ☑️ [提取模板中出现的贴纸\u002F气泡\u002F花字等元信息](#提取素材元数据)\n\n### 批量导出\n> ⚠️ 剪映7+版本隐藏了控件，故**本系列功能目前仅支持剪映6及以下版本**\n\n- ☑️ 控制剪映打开指定草稿\n- ☑️ [导出草稿至指定位置](#批量导出草稿)\n- ☑️ 调节导出分辨率和帧率\n\n### 视频与图片\n> ℹ 以下草稿生成功能（音视频、贴纸、文本、特效等）**支持剪映5及以上的所有版本**\n\n- ☑️ 添加本地视频\u002F图片素材，并[自定义片段的时间、持续时长或播放速度](#素材截取与整体变速)\n- ☑️ 视频片段的[音频淡入淡出效果](#音频淡入淡出)\n- ☑️ [视频整体调节](#视频整体调节)（旋转、缩放、亮度等）以及[关键帧生成](#关键帧)\n- ☑️ 视频片段的[入场\u002F出场\u002F组合动画](#添加片段动画)\n- ☑️ 添加[蒙版](#蒙版)、[片段特效](#添加片段特效)和[滤镜](#添加片段滤镜)\n- ☑️ （项目700⭐️回馈功能）视频背景填充[(示例代码)](demo.py)\n- ☑️ （项目2k⭐️回馈功能）[视频混合模式](#视频混合模式)（正片叠底、滤色、叠加等）\n### 贴纸\n- ☑️ 根据元信息[添加贴纸](#提取素材元数据)\n- ☑️ 贴纸的[关键帧](#关键帧)生成\n### 音频\n- ☑️ 添加本地音频素材，并[自定义片段的时间、持续时长或播放速度](#素材截取与整体变速)\n- ☑️ 调整[淡入淡出](#音频淡入淡出)时长[(示例代码)](demo.py)，调整音量[(示例代码)](demo.py)及其[关键帧](#关键帧)\n- ☑️ 添加音频片段的[场景音效果](#添加片段特效)，并设置参数\n### 轨道\n- ☑️ [添加轨道](#多轨道操作)以及[将片段添加到指定轨道](#多轨道操作)\n- ☑️ 自定义视频\u002F滤镜\u002F特效轨道的[层级关系](#多轨道操作)\n### 特效、滤镜和转场\n- ☑️ 吸附于片段上的[特效](#添加片段特效)、[滤镜](#添加片段滤镜)和[动画](#添加片段动画)\n- ☑️ 位于[独立轨道的特效和滤镜](#独立轨道上的特效和滤镜)\n- ☑️ 添加转场[(示例代码)](demo.py)，并自定义其时长\n### 文本及字幕\n- ☑️ [添加文本、设置字体及样式](#添加文本)、修改文本片段的[位置及旋转设置](#视频整体调节)\n- ☑️ 文本的[关键帧](#关键帧)以及[动画](#添加片段动画)\n- ☑️ 文字描边、背景和阴影\n- ☑️ 文字气泡效果和花字效果[(示例代码)](demo.py)\n- ☑️ 文本[自动换行](#文本自动换行)，支持设置最大行宽\n- ☑️ [导入`.srt`文件](#导入字幕)生成字幕并批量设置格式\n\n# 安装\npyJianYingDraft现已支持pip安装（不含demo），推荐使用开发时测试的Python版本3.8或3.11\n```\npip install pyJianYingDraft\n```\n\n> ℹ 关于剪映5.9版本的自动升级问题，可参见[相关issue](https:\u002F\u002Fgithub.com\u002FGuanYixuan\u002FpyJianYingDraft\u002Fissues\u002F115)\n\n### 跨平台兼容性\n- **Windows**：支持包括草稿生成、模板模式和自动导出在内的所有功能（具体可能受到剪映版本限制）\n- **Linux\u002FMacOS**：支持草稿生成和模板模式，但**不支持自动导出**，且注意**生成的草稿仍然需要在Windows版剪映下导出**。\n\n# 快速上手\n例程`demo.py`将创建包含音视频素材和一行文本的剪映草稿文件，并且添加了音频淡入、视频入场动画、转场效果和文本气泡\u002F花字。\n\n这个例程的操作方法如下：\n1. 找到剪映的**草稿文件夹路径**（类似`...\u002FJianyingPro Drafts`），用其替换代码中的`\u003C你的草稿文件夹>`\n2. 运行`demo.py`\n3. 在剪映中**找到并打开新创建的`demo`草稿**（可能需要进入再退出某个已有草稿，或重启剪映以刷新草稿列表），你应该看到类似如下的时间轴：\n\n![快速上手](readme_assets\u002F快速上手.png)\n\n你可以仔细检查音频片段的音量设置、淡入效果时长以及视频片段的入场动画效果等，看看是否符合上述代码的设置\n\n# 用法文档\n\n> ℹ 文档部分推荐从[功能清单](#功能清单)一节中选取感兴趣的功能阅读，而非直接按顺序阅读\n\n### 模板模式\n为了保留部分复杂特性（文本特效、复合片段...），可以加载一个已有的剪映草稿作为模板，然后将其中内容导入到另一的草稿中，或直接**替换其中部分片段的内容**。\n\n目前提供了**三种替换功能**：\n- [根据名称替换素材](#根据名称替换素材)：直接替换素材本身，自然影响所有引用该素材的片段\n- [根据片段替换素材](#根据片段替换素材)：替换某个特定片段的素材，同时重新选取其引用的素材范围\n- [替换文本片段的内容](#替换文本片段的内容)：保留所有文本格式，但替换其内容\n\n除此之外，对于某些没有特定名称的特性（贴纸、花字等），提供了[提取素材元数据](#提取素材元数据)的功能以提取其`resource_id`\n\n> ⚠️ 由于剪映6+版本对草稿文件进行了加密，故**暂不支持加载来自6+版本的草稿文件**作为模板\n\n> ℹ 若出现模板内容丢失的情况，欢迎反馈\n\n#### 加载模板\n推荐使用`DraftFolder`来管理剪映的草稿文件夹（可以在剪映的`全局设置`-`草稿位置`中查询），这样能够方便地根据已有模板生成新草稿。\n\n```python\nimport pyJianYingDraft as draft\n\ndraft_folder = draft.DraftFolder(\"\u003C剪映草稿文件夹>\")  # 一般形如 \"...\u002FJianyingPro Drafts\"\nscript = draft_folder.duplicate_as_template(\"模板草稿\", \"新草稿\")  # 复制\"模板草稿\"，并命名为\"新草稿\"，同时打开新草稿供编辑\n\n# 对返回的ScriptFile对象进行编辑，如替换素材、添加轨道、片段等\n\nscript.save()  # 保存你的\"新草稿\"\n```\n\n为了最大限度地兼容模板中的复杂特性，**导入的轨道与pyJianYingDraft创建的轨道是分离开的**，具体地讲：\n\n- 除下述替换功能外，不能在导入的轨道上添加片段、转场、淡入淡出、特效等\n- **仍然可以创建新的轨道，并在其上添加片段等**，就像非模板模式一样\n\n> ℹ 导入轨道的限制也许会在后续版本中逐渐取消\n\n#### 提取素材元数据\n对导入的`ScriptFile`对象，可以调用`inspect_material`方法提取部分素材的`resource_id`。\n`DraftFolder`也有相应的方法来提取指定草稿的素材元数据。\n\n```python\nimport pyJianYingDraft as draft\n\ndraft_folder = draft.DraftFolder(\"\u003C剪映草稿文件夹>\")\ndraft_folder.inspect_material(\"草稿名称\")\n\n# 或者\nscript = draft_folder.load_template(\"草稿名称\")\nscript.inspect_material()\n```\n\n上述代码的输出可能类似于\n\n```\n贴纸素材:\n        Resource id: 7405878923323641129 '秋日手绘-枫叶'\n        Resource id: 7429353555447893260 '电商购物促销\u002F哇哦'\n        Resource id: 7437707455267671315 '冬日涂鸦winter雪花冬天vlog装饰文字'\n        Resource id: 7343931192204463401 '爱心'\n文字气泡效果:\n        Effect id: 763870 ,Resource id: 6838834573413978631 '标题59'\n花字效果:\n        Resource id: 7342020000812731658 '彩色手绘线条花字'\n```\n\n其中的元数据可用于添加相应素材（例如通过`StickerSegment`的`resource_id`参数）\n\n#### 根据名称替换素材\n这种方法将替换素材本身，而不对片段进行直接修改。\n\n> ℹ 由于素材有名称（默认是本地文件的名称），这种替换方式的定位比较方便\n\n> ℹ 由于不涉及时间范围的修改，这种替换方式**尤其适合图像素材**，且几乎不会产生兼容性的问题\n\n以[快速上手](#快速上手)中的草稿为例，假如我们希望换用新的音频素材，可以：\n```python\nnew_material = draft.AudioMaterial(\"\u003C新的音频素材路径>\")\nscript.replace_material_by_name(\"audio.mp3\", new_material)  # 替换名称为\"audio.mp3\"的素材\n```\n\n替换新素材后，片段所截取的部分仍是素材前5秒，且音量、淡入淡出、播放速度等仍保持不变。\n\n#### 根据片段替换素材\n这种方法将替换某个**特定片段**的素材，同时可以**重新选取其引用的素材范围**并**根据新时长在时间轴上伸缩片段**。\n\n> ℹ 由于片段没有名称，故通常需要**依靠片段的下标来定位**\n\n此过程分为两步：**选取轨道**和**替换素材**，以上方音频素材的替换为例：\n```python\nfrom pyJianYingDraft import trange, ShrinkMode, ExtendMode\n\naudio_track = script.get_imported_track(\n    draft.TrackType.audio,                # 选取导入的音频轨道\n    #name=\"audio\",                         # 假如轨道有名称，最好利用名称来定位\n    index=0                                # 也可用下标定位, 0表示最底层的同类型轨道\n)\n\nscript.replace_material_by_seg(\n    audio_track, 0, new_material,          # 选取audio_track中下标为0的片段，也即第一个片段\n    #source_timerange=None,                # 若不指定，则默认使用整个素材\n    source_timerange=trange(\"0s\", \"10s\"),  # 此处指定截取素材前10秒(注意原片段时长为5秒)\n    handle_shrink=ShrinkMode.cut_tail,     # 片段若要缩短，则依靠前移终止点来实现\nhandle_extend=ExtendMode.push_tail         # 片段若要延长，则依靠后移终止点来实现，必要时允许后移后续片段\n)\n```\n\n从例子中可见，此替换方法可能会造成片段的时长变化，故可以利用`handle_shrink`和`handle_extend`参数指定片段在缩短和延长时的处理方式。\n\n> ℹ 不显式指定`handle_shrink`和`handle_extend`时，默认的处理方式如下：\n> - 新素材比原素材短，则前移片段终止点，使得片段长度与新素材长度一致\n> - 新素材比原素材长，则裁剪素材范围，保持片段原长不变\n\n具体的处理方式列表可参见枚举类`ShrinkMode`和`ExtendMode`的定义。\n\n> ℹ 目前已知替换带有组合出入场动画的片段不会自动刷新动画时间\n\n#### 替换文本片段的内容\n这种方法将替换某个**特定文本片段**的内容，但保留其所有格式。\n\n此过程同样分为**选取轨道**和**替换内容**两个步骤：其中“选取轨道”可参考[根据片段替换素材](#根据片段替换素材)中的示例。\n\n以下假定我们已经选取了合适的文本轨道`text_track`，则只需：\n```python\nscript.replace_text(\n    text_track, 0,  # 选取text_track中下标为0的片段，也即第一个片段\n    \"新文本内容\"     # 新的文本内容\n)\n```\n\n#### 导入模板草稿中的轨道\n\n此功能会字面意义地复制模板草稿中的指定轨道到新草稿中, 适合用于拼接多个模板草稿。\n\n> ℹ **目前仅支持导入音视频\u002F文本轨道**, 支持的范围将来会继续扩展\n\n> ⚠️ 本方法会保留各片段及其素材的id, 因而**不支持向同一草稿多次导入同一轨道**\n\n例如\n```python\nsource_script = draft_folder.load_template(\"\u003C模板草稿名称>\")     # 加载模板草稿\ntarget_script = draft_folder.create_draft(\"新草稿\", 1920, 1080)  # 创建新草稿\n\n# 选取模板中的一个文本轨道\ntext_track = source_script.get_imported_track(\n    draft.TrackType.text,                # 选取导入的文本轨道\n    #name=\"text\",                        # 假如轨道有名称，最好利用名称来定位\n    index=0                              # 也可用下标定位, 0表示最底层的同类型轨道\n)\n\n# 导入文本轨道到新草稿\ntarget_script.import_track(\n    source_script, text_track,\n    offset=target_script.duration,  # 导入的轨道将放在新草稿末尾\n    new_name=\"imported_text\",       # 可选的新轨道名\n    relative_index=1,               # 相对于所有文本轨道的位置, 值越大越接近前景, 可以是负数\n)\n```\n\n### 批量导出草稿\n作为整个自动化流程中的最后一步，本项目提供了基础的草稿批量导出功能。\n\n> ⚠️ 剪映7+版本对控件进行了隐藏，故本功能目前**仅支持剪映6及以下版本**\n\n> ⚠️ 本部分功能依赖于`uiautomation`库，故目前**仅支持在Windows系统下运行**\n\n> ℹ 导出程序会将剪映窗口置顶，且需要控制光标进行点击，**建议在闲时\u002F夜间运行**\n\n> ℹ 本部分功能**在剪映专业版5.9和6.8中测试通过**\n\n> ℹ 有用户反映部分Python版本(如3.13)下`uiautomation`会出现依赖问题, 推荐使用3.8、3.10或3.11, [详见此处](https:\u002F\u002Fgithub.com\u002FGuanYixuan\u002FpyJianYingDraft\u002Fissues\u002F12)\n\n> ⚠️ 请**确认有导出草稿的相关权限(不使用VIP功能或已开通VIP)**, 否则可能陷入死循环\n\n导出利用`JianyingController`类进行，具体用法如下：\n\n```python\nimport pyJianYingDraft as draft\nfrom pyJianYingDraft import ExportResolution, ExportFramerate\n\n# 此前需要将剪映打开，并位于目录页\nctrl = draft.JianyingController()\n\n# 然后即可导出指定名称的草稿, 注意导出结束后视频才会被剪切(重命名)至指定位置\nctrl.export_draft(\"要导出的草稿名称\", \"\u003C导出路径>\")  # \"导出路径\"可以指向文件夹或直接指向文件\n\n# 若希望调节分辨率或帧率, 可使用`resolution`和`framerate`参数\nctrl.export_draft(\"要导出的草稿名称\", \"\u003C导出路径>\",\n                  resolution=ExportResolution.RES_1080P,\nframerate=ExportFramerate.FR_24)\n```\n\n重复上述单次导出操作即可实现批量导出，类似如下代码：\n```python\ndraft_names = ...\nexport_folder = ...\nfor name in draft_names:\n    ctrl.export_draft(name, os.path.join(export_folder, name, \".mp4\"))\n```\n\n### 时间与轨道\n\n#### 时间格式\n**剪映（和本项目）内部均采用微秒为单位保存时间**，但这不便于输入，故我们增加了一种“字符串形式”的时间，大部分时间参数均同时支持这两种形式：\n- 微秒形式：用`int`表达，适于计算\n- 字符串形式：用`str`表达，如`\"1.5s\"`、`\"1h3m12s\"`等，易于输入\n\n如果你希望显式地将字符串形式转换为微秒形式，可以使用`tim`函数；`trange`函数则是支持字符串形式输入的`Timerange`便捷构造函数。\n\n> ⚠️ 注意`trange`的第二个参数是**持续时长**，而不是结束时间\n\n例如：\n```python\nimport pyJianYingDraft as draft\nfrom pyJianYingDraft import SEC, tim, trange\n\n# 1秒钟\nassert 1000000 == SEC == tim(\"1s\") == tim(\"0.01666667m\")\n\n# 0~1分钟\nassert draft.Timerange(0, 60*SEC) == trange(\"0s\", \"1m\") == trange(\"0s\", \"0.5m30s\")\n\n# 片段开始后2秒\nseg: draft.VideoSegment\nassert seg.target_timerange.start + 2*SEC == seg.target_timerange.start + tim(\"2s\")\n```\n\n#### 素材截取与整体变速\n截取和变速均在`Segment`创建时设置完成，具体是通过`target_timerange`、`source_timerange`和`speed`参数来共同实现的。\n> ℹ 目前暂不支持设置曲线变速\n\n以下以`VideoSegment`为例，`AudioSegment`的用法相同，此二者支持两种构造方式：\n1. **便捷构造**：直接传入素材路径字符串，自动构造素材实例\n2. **传统构造**：先创建素材实例，再传入片段构造函数。**若需要设置素材的图像裁剪属性请使用此方式**\n\n```python\nimport os\nimport pyJianYingDraft as draft\nfrom pyJianYingDraft import trange, SEC\n\n# 假定已有草稿文件script（参见“快速上手”），创建三个轨道\nfor i in range(3, 0, -1): # 倒序\n    script.add_track(draft.TrackType.video, \"%d\" % i)\n\n# 以下部分讲解素材与片段的创建\n# 方式一：便捷构造（推荐）\ntutorial_asset_dir = os.path.join(os.path.dirname(__file__), 'readme_assets', 'tutorial')\nvideo_path = os.path.join(tutorial_asset_dir, 'video.mp4')\n\n# 直接传入素材路径\nseg1 = draft.VideoSegment(video_path, trange(\"0s\", \"4s\"))  # 截取素材的前4秒\n\n# 方式二：传统构造\nmat = draft.VideoMaterial(video_path)  # 先创建素材实例\nseg2 = draft.VideoSegment(mat, trange(\"0s\", \"4s\"))  # 再传入片段构造函数\n\n# 视频素材长度为 5s\nprint(\"Video material length: %f s\" % (mat.duration \u002F SEC))\n\n# 以下部分讲解素材的时间截取与变速\n# 不指定source_timerange，则自动从头截取素材等长片段\nseg11 = draft.VideoSegment(video_path, trange(\"0s\", \"4s\"))              # 自动截取素材的前4秒（4s表示持续时长）\nseg2  = draft.VideoSegment(video_path, trange(\"0s\", \"4s\"), speed=1.25)  # 自动截取素材的前4*1.25=5秒\nseg4  = draft.VideoSegment(video_path, trange(\"0s\", \"3s\"), speed=3.0)   # 截取前3*3.0=9秒，素材不够长故报错\n\n# 指定source_timerange，则截取素材的指定片段，自动设置速度\nseg12 = draft.VideoSegment(video_path, trange(\"4s\", \"1s\"),\n                            source_timerange=trange(0, \"4s\"))     # 将素材在1s内放完，速度自动设置为5.0\n\n# 同时指定source_timerange和speed，则截取素材的指定片段，并根据播放速度覆盖target_timerange的duration\nseg3  = draft.VideoSegment(video_path, trange(\"1s\", \"66666h\"),\n                            source_timerange=trange(0, \"5s\"),\n                            speed=2.0) # 将长5s的素材按2倍速放完，target_timerange的duration自动设为2.5s\n\n# 将片段加入轨道\nscript.add_segment(seg11, \"1\").add_segment(seg12, \"1\")\nscript.add_segment(seg2, \"2\")\nscript.add_segment(seg3, \"3\")\n\n# 保存草稿\nscript.dump(\"*你的草稿工程文件夹*\u002Fdraft_content.json\")\n```\n\n#### 多轨道操作\n目前`ScriptFile.add_track`方法已支持创建多个同类型轨道，并支持自定义其顺序：\n```python\nscript.add_track(draft.TrackType.video,\n                 track_name=\"前景\",       # 轨道名\n                 relative_index=2)        # 在所有视频轨道中的相对位置\nscript.add_track(draft.TrackType.video,\n                 track_name=\"背景\",\n                 relative_index=1)        # 由于1\u003C2，所以前景轨道位于更上方\n```\n\n> ℹ 对于相同index的轨道，默认**后创建的轨道位于上方**\n\n一旦创建了多个同类轨道，则在添加片段时必须指定目标轨道，例如：\n```python\nscript.add_segment(video_segment, \"背景\")\n```\n\n### 视频整体调节\n每个视频片段都可以单独设置裁剪、旋转、翻转、缩放、透明度、亮度等属性，这些设置通过`VideoSegment`构造函数中的`clip_settings`参数传入\n> ℹ 关键帧的优先级高于整体调节，故前者会覆盖后者的相应设置\n\n下方的例子将创建一个视频片段，并设置其不透明度为0.5、打开水平翻转：\n```python\nfrom pyJianYingDraft import ClipSettings\nvideo_segment = draft.VideoSegment(video_material,\n                                   draft.Timerange(0, video_material.duration),      # 与素材等长\n                                   clip_settings=ClipSettings(alpha=0.5,             # 不透明度为0.5\n                                                              flip_horizontal=True)  # 打开水平翻转\n                                    )\n```\n\n更具体的参数说明可参见`ClipSettings`的构造函数。\n\n### 关键帧\n关键帧是吸附在**片段**上的“时刻-数值”对，所以创建关键帧只需要在`add_keyframe`方法中指定**相对片段头部的**时刻、数值以及控制的属性即可。\n> ℹ 目前不支持设置特效或滤镜参数的关键帧\n\n下方的例子尝试使用两个不透明度关键帧模拟视频的淡出效果：\n```python\nimport os\nimport pyJianYingDraft as draft\nfrom pyJianYingDraft import KeyframeProperty, SEC\n\n# 假定已有草稿文件script（参见“快速上手”），创建视频轨道\nscript.add_track(draft.TrackType.video)\ntutorial_asset_dir = os.path.join(os.path.dirname(__file__), 'readme_assets', 'tutorial')\n\n# 创建视频片段\nvideo_material = draft.VideoMaterial(os.path.join(tutorial_asset_dir, 'video.mp4'))\nvideo_segment = draft.VideoSegment(video_material,\n                                   draft.Timerange(0, video_material.duration)) # 与素材等长\n\n# 添加两个不透明度关键帧形成1s的淡出效果\nvideo_segment.add_keyframe(KeyframeProperty.alpha, video_segment.duration - SEC, 1.0) # 结束前1s完全不透明\nvideo_segment.add_keyframe(KeyframeProperty.alpha, video_segment.duration, 0.0) # 片段结束时完全透明\n\n# 添加片段到轨道\nscript.add_segment(video_segment)\n\n# 保存草稿\nscript.dump(\"*你的草稿工程文件夹*\u002Fdraft_content.json\")\n```\n\n除了`alpha`外，`KeyframeProperty`中还有平移、旋转、缩放、音量、饱和度等属性，它们都可以设置关键帧。\n文本和贴纸片段的关键帧也可以用相同方法进行设置，但注意它们只支持位置和大小相关的那些属性。\n\n对音频片段，目前只能设置音量的关键帧，此时你不需要指定`KeyframeProperty`\n```python\naudio_segment: draft.AudioSegment\naudio_segment.add_keyframe(\"0s\", 0.6) # 片段开始时的音量为60%\n```\n\n### 音频淡入淡出\n音频淡入淡出效果可以为音频片段和带音轨的视频片段添加平滑的音量过渡。使用`add_fade()`方法即可实现：\n\n```python\nimport pyJianYingDraft as draft\nfrom pyJianYingDraft import trange\n\n# 为音频片段添加淡入淡出\naudio_segment = draft.AudioSegment(\"audio.mp3\", trange(\"0s\", \"10s\"))\naudio_segment.add_fade(\"1s\", \"2s\")  # 1秒淡入，2秒淡出\n\n# 为带音轨的视频片段添加淡入淡出\nvideo_segment = draft.VideoSegment(\"video_with_audio.mp4\", trange(\"0s\", \"10s\"))\nvideo_segment.add_fade(\"1.5s\", \"1.5s\")  # 1.5秒淡入，1.5秒淡出\n```\n\n其中：\n- `add_fade()`方法接受两个参数：淡入时长和淡出时长\n- 对于视频片段，淡入淡出效果仅对有音轨的视频有效\n- 每个片段只能添加一次淡入淡出效果，重复调用会抛出`ValueError`\n\n### 蒙版\n蒙版的添加非常简单：调用`VideoSegment`的`add_mask`方法即可：\n```python\nfrom pyJianYingDraft import MaskType\n\n# 添加一个线性蒙版，中心点在素材的(100, 0)像素处，顺时针旋转45度\nvideo_segment1.add_mask(MaskType.线性, center_x=100, rotation=45)\n# 添加一个圆形蒙版，直径占素材的50%\nvideo_segment2.add_mask(MaskType.圆形, size=0.5)\n```\n其中：\n- `MaskType`保存了剪映自带的蒙版类型\n- `center_x`和`center_y`参数表示蒙版中心点的坐标，与剪映中意义一致\n- `rotation`、`feather`、`round_corner`分别表示旋转、羽化、圆角参数，与剪映中意义一致\n- `size`参数表示蒙版的”主要尺寸”（镜面的可视部分高度\u002F圆形直径\u002F爱心高度等）占素材的比例\n\n更具体的参数说明请参见`add_mask`方法的注释。\n\n### 视频混合模式\n混合模式用于控制视频片段与下层内容的混合方式，实现正片叠底、滤色、叠加等效果。\n\n> ℹ 混合模式需要至少两个视频轨道：一个基础轨道和一个叠加轨道\n\n> ℹ 叠加轨道必须位于基础轨道上方，可通过`relative_index`参数控制层次\n\n使用`VideoSegment.set_mix_mode()`方法为视频片段设置混合模式：\n```python\nfrom pyJianYingDraft import MixModeType\n\n# 创建两个视频轨道，明确层次关系\nscript.add_track(draft.TrackType.video, \"base\", relative_index=1)      # 基础轨道在下层\nscript.add_track(draft.TrackType.video, \"overlay\", relative_index=2)   # 叠加轨道在上层\n\n# 基础视频片段\nbase_video = draft.VideoSegment(\"base.mp4\", trange(\"0s\", \"10s\"))\nscript.add_segment(base_video, track_name=\"base\")\n\n# 叠加视频片段，使用”滤色”混合模式\noverlay_video = draft.VideoSegment(\"overlay.mp4\", trange(\"0s\", \"10s\"))\noverlay_video.set_mix_mode(MixModeType.滤色)\nscript.add_segment(overlay_video, track_name=\"overlay\")\n```\n\n`MixModeType`支持以下10种混合模式：\n- `正片叠底`、`颜色减淡`、`颜色加深`、`线性加深`\n- `柔光`、`强光`、`滤色`、`叠加`\n- `变亮`、`变暗`\n\n### 特效、动画和滤镜\n#### 特效类型\n目前支持的**特效**类型由以下枚举类定义：\n- 音频：`AudioSceneEffectType`（场景音）\n- 视频：`VideoSceneEffectType`（画面特效）、`VideoCharacterEffectType`（人物特效）\n\n目前支持的**动画**类型由以下枚举类定义：\n- 视频：`IntroType`（入场）, `OutroType`（出场）, `GroupAnimationType`（组合动画）\n- 文本：`TextIntro`（入场）、`TextOutro`（出场）, `TextLoopAnim`（循环动画）\n\n**滤镜**类型则保存在`FilterType`中，仅对视频片段有效。\n\n上述枚举类中的成员（通常）直接**以特效或滤镜的名字命名**，并注释了相应参数，例如：\n\n![特效类型](readme_assets\u002F片段特效_annotation.jpg)\n\n你也可以使用`from_name`方法来获取特定的成员，其忽略大小写、空格和下划线，例如：\n\n```python\nassert VideoSceneEffectType.from_name(\"__全息 扫描__\") == VideoSceneEffectType.全息扫描\n```\n\n#### 添加片段特效\n添加特效使用的方法是`segment.add_effect()`，它接受特效类型和一个参数数组，参数数组的顺序**与特效类型注释中的参数顺序一致**，但**不一定与剪映内的参数顺序一致**。\n\n下方的例子为视频片段添加一个`全息扫描`特效，并且指定其`氛围`参数为（剪映中的）100，其余参数默认：\n```python\nfrom pyJianYingDraft import VideoSceneEffectType\n\nvideo_segment.add_effect(VideoSceneEffectType.全息扫描,\n                         [None, None, 100.0]) # 不设置前两个参数, 第三个参数（氛围）为100，其余参数也不设置\n```\n音频片段的特效添加方法与视频片段相似\n\n#### 添加片段滤镜\n滤镜的添加方法与特效类似，其使用的是`VideoSegment.add_filter()`方法。\n与特效不同的是，滤镜只支持一个“滤镜强度”参数，且仅当所选滤镜能够调节强度时有效。\n\n```python\nfrom pyJianYingDraft import FilterType\n\nvideo_segment1.add_filter(FilterType.原生肤, 10)  # 设置\"原生肤\"强度为10\nvideo_segment2.add_filter(FilterType.冰雪世界, 50)  # 设置\"冰雪世界\"强度为50\n```\n\n#### 独立轨道上的特效和滤镜\n除了为视频片段添加特效和滤镜外，你还可以创建独立的特效轨道和滤镜轨道，并在其上添加特效和滤镜片段。\n\n首先使用`ScriptFile.add_track()`方法创建特效轨道或滤镜轨道。若需要指定顺序请参考[多轨道操作](#多轨道操作)\n```python\nscript.add_track(draft.TrackType.effect, \"my_effect\")  # 创建名为\"my_effect\"的特效轨道\nscript.add_track(draft.TrackType.filter, \"my_filter\")  # 创建名为\"my_filter\"的滤镜轨道\n```\n\n接下来便可使用`add_effect`和`add_filter`方法向这些轨道添加片段：\n```python\nfrom pyJianYingDraft import VideoSceneEffectType, FilterType, trange\n\n# 在特效轨道上添加一个\"胶片闪切\"特效，持续5秒，并设置其参数\nscript.add_effect(VideoSceneEffectType.胶片闪切, trange(\"0s\", \"5s\"),\n                  track_name=\"my_effect\",  # 当特效轨道只有一条时可省略\n                  params=[50, None, 80])  # 设置速度为50，保持强度默认(100)，设置纹理为80\n\n# 在滤镜轨道上添加一个\"哈苏蓝\"滤镜，持续整个视频，强度为70\nscript.add_filter(FilterType.哈苏蓝, trange(0, script.duration),\n                  track_name=\"my_filter\",  # 当滤镜轨道只有一条时可省略\n                  intensity=70)\n```\n\n#### 添加片段动画\n添加动画使用的方法是`segment.add_animation()`，其仅接收一个动画类型作为参数，动画的持续时间由其默认值决定。若需要添加多个动画，可对同一个片段调用多次该方法。\n\n> ℹ 为**文本片段**同时设置循环动画和入出场动画时, 请**先添加出入场动画再添加循环动画**\n\n以下是为一个文本片段添加三种动画的例子：\n```python\nfrom pyJianYingDraft import TextIntro, TextOutro, TextLoopAnim\n\ntext_seg.add_animation(TextIntro.复古打字机).add_animation(TextOutro.弹簧)\ntext_seg.add_animation(TextLoopAnim.色差故障)  # 注意：循环动画必须在出入场动画之后添加\n```\n\n### 文本及字幕\n#### 添加文本\n添加文本与添加视频\u002F音频片段类似，只需创建`TextSegment`对象并利用`add_segment`添加到`ScriptFile`中即可。\n其**字体**、**文字样式**及**图像调节**设置可分别通过`font`, `style`和`clip_settings`参数设置。\n\n例如：\n```python\nimport pyJianYingDraft as draft\nfrom pyJianYingDraft import FontType, TextStyle, ClipSettings\n\n# 带下划线、位置及大小类似字幕的浅蓝色文本\nseg1 = draft.TextSegment(\"Subtitle\", trange(\"0s\", \"10s\"),\n                          font=FontType.文轩体,\n                          style=TextStyle(size=5.0, color=(0.7, 0.7, 1.0), underline=True, align=1),\n                          clip_settings=ClipSettings(transform_y=-0.8))\n```\n\n更具体的参数说明可参见`TextStyle`和`ClipSettings`的构造函数。\n\n#### 文本自动换行\n文本片段支持自动换行功能，可以通过`TextStyle`的`auto_wrapping`和`max_line_width`参数来控制：\n\n```python\n# 启用自动换行，设置最大行宽为屏幕宽度的70%\nseg2 = draft.TextSegment(\"这是一段很长的文本内容，当超过设定的最大行宽时会自动换行显示\",\n                          trange(\"0s\", \"10s\"),\n                          font=FontType.文轩体,\n                          style=TextStyle(size=5.0,\n                                          auto_wrapping=True,      # 启用自动换行\n                                          max_line_width=0.7))     # 最大行宽占屏幕70%\n```\n\n#### 导入字幕\n> ℹ 目前只支持导入**SRT格式**的字幕文件\n\n导入字幕本质上是根据每条字幕的时间戳及内容创建一系列文本，并添加到轨道中。这一过程通过`ScriptFile.import_srt`来实现。\n导入的字幕默认启用自动换行功能。\n\n例如：\n```python\nimport pyJianYingDraft as draft\n\n# 假定已有草稿文件script（参见“快速上手”）\n\n# 将字幕导入到名为\"subtitle\"的轨道中，若轨道不存在将自动创建\n# 不指定style和clip_settings，则默认模拟剪映导入字幕时的样式\nscript.import_srt(\"subtitle.srt\", track_name=\"subtitle\", time_offset=\"1.5s\")  # 字幕整体后移1.5秒\n\n# 可以利用`text_style`和`clip_settings`参数对字幕的样式进行调整, 上述参数的意义与`TextSegment()`中的相同\nscript.import_srt(\"subtitle.srt\", track_name=\"subtitle\",\n                  text_style=draft.TextStyle(size=10.0, color=(1.0, 0.0, 0.0))\n                  clip_settings=draft.ClipSettings(transform_y=0.8))  # 将字幕放置在屏幕上方\n\n# 如果需要更复杂的样式或希望为字幕应用动画，可以为`style_reference`参数传入一个`TextSegment`对象作为样式参考（忽略其文本和片段长度设置）\n# 注意动画时间不会根据字幕片段长度进行调节，故当字幕片段过短时可能出现奇怪的效果\nscript.import_srt(\"subtitle.srt\", track_name=\"subtitle\", style_reference=seg1)  # 以上一节“添加文本”中的文本作为参考\n\n# 默认不会采用`style_reference`片段中的`clip_settings`设置，如果需要的话请显式传入`clip_settings=None`\nscript.import_srt(\"subtitle.srt\", track_name=\"subtitle\", style_reference=seg1, clip_settings=None)  # 相当于clip_settings=seg1.clip_settings\n```\n","pyJianYingDraft 是一个轻量、灵活且易于上手的 Python 工具，用于生成和导出剪映草稿文件，支持构建全自动视频剪辑\u002F混剪流水线。该项目通过提供模板模式、批量导出等功能，允许用户加载未加密的 `draft_content.json` 文件作为模板，并进行音视频片段替换、文本内容修改等操作；同时支持自定义导出位置及调节导出分辨率和帧率。此外，它还具备添加本地素材、调整音频效果、创建多轨道以及应用特效、滤镜和转场等多种高级编辑功能。适用于需要自动化处理大量视频剪辑任务的场景，尤其适合那些希望在剪映平台上实现高效视频生产的创作者或团队。注意，部分功能对剪映版本有特定要求，如模板模式目前仅支持5.9及以下版本。",2,"2026-06-11 03:41:20","high_star"]