Python/营销短视频生成自动化/main.py

291 lines
9.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""
营销短视频生成自动化
"""
from pathlib import Path
from typing import Optional, Tuple, Union
import pycapcut as capcut
from pycapcut import tim, trange
class Draft:
"""剪映脚本生成器类"""
# noinspection PyShadowingNames
def __init__(
self,
draft_name: str,
drafts_path: str = r"C:\Users\admin\AppData\Local\JianyingPro\User Data\Projects\com.lveditor.draft",
stocks_path: Path = Path(__file__).parent / "materials",
video_width: int = 1920,
video_height: int = 1080,
):
"""
初始化剪映草稿生成器
:param drafts_path: 草稿文件夹路径
:param stocks_path: 素材文件夹路径
:param draft_name: 草稿名称
:param video_width: 视频宽度
:param video_height: 视频高度
"""
# 基础配置
self.drafts_path = drafts_path
self.stocks_path = stocks_path
self.draft_name = draft_name
self.video_width, self.video_height = video_width, video_height
# 尝试创建草稿文件夹和草稿
# noinspection PyBroadException
try:
self.draft_folder = capcut.DraftFolder(self.drafts_path)
self.draft = self.draft_folder.create_draft(
self.draft_name, self.video_width, self.video_height, allow_replace=True
)
# 添加基础轨道:音频、视频、文本(图片/贴纸复用视频轨)
self.draft.add_track(capcut.TrackType.audio)
self.draft.add_track(capcut.TrackType.video)
self.draft.add_track(capcut.TrackType.text)
except:
raise RuntimeError("创建草稿文件夹和草稿发生异常")
# 检查素材文件夹是否存在,若不存在则抛出异常
if not self.stocks_path.exists():
raise FileNotFoundError(f"素材文件夹不存在")
def _check_path(self, file_name: str) -> str:
"""
检查文件是否存在,若存在则返回文件路径
:param file_name: 文件名称
:return 文件路径
"""
file_path = self.stocks_path / file_name
if not file_path.exists():
raise FileNotFoundError(f"素材文件不存在")
return file_path.as_posix()
def add_audio(
self,
file_name: str,
start_time: str,
duration: str,
volume: float = 1.0,
fade_in: str = "0s",
fade_out: str = "0s",
) -> capcut.AudioSegment:
"""
添加音频片段
:param file_name: 音频文件名称
:param start_time: 音频在轨道上的开始时间(如 "0s"
:param duration: 音频持续时长(如 "1s"
:param volume: 音量(如 1.0
:param fade_in: 淡入时长(如 “0s”
:param fade_out: 淡出时长(如 “0s”
Returns: capcut.AudioSegment
"""
try:
# 创建音频片段
audio_segment = capcut.AudioSegment(
self._check_path(file_name), trange(start_time, duration), volume=volume
)
# 添加淡入淡出效果
audio_segment.add_fade(fade_in, fade_out)
self.draft.add_segment(audio_segment)
return audio_segment
except Exception:
raise RuntimeError("添加音频片段发生异常")
def add_video(
self,
file_name: str,
start_time: str,
duration: str,
animation: Optional[capcut.IntroType] = None,
transition: Optional[capcut.TransitionType] = None,
keyframes: Optional[list] = None,
) -> capcut.VideoSegment:
"""
添加视频片段
:param file_name: 视频文件名称
:param start_time: 视频在轨道上的开始时间(如 "0s"
:param duration: 视频持续时长(如 "1s"
:param animation: 动画配置
:param transition: 转场配置
:param keyframes: 关键帧配置
:return capcut.VideoSegment
"""
try:
# 创建视频片段
video_segment = capcut.VideoSegment(
self._check_path(file_name), trange(start_time, duration)
)
# 添加动画
if animation:
video_segment.add_animation(animation)
# 添加转场
if transition:
video_segment.add_transition(transition)
# 添加关键帧
if keyframes:
# noinspection PyShadowingBuiltins
for property, time, value in keyframes:
video_segment.add_keyframe(property, time, value)
self.draft.add_segment(video_segment)
return video_segment
except Exception:
raise RuntimeError("添加视频片段发生异常")
def add_image(
self,
file_name: str,
start_time: Union[str, tim],
duration: Optional[str] = None,
background_filling: Tuple[str, float] = ("blur", 0.0625),
) -> capcut.VideoSegment:
"""
添加图片/贴纸
:param file_name: 图片文件名称
:param start_time: 图片在轨道上的开始时间(如 "0s"
:param duration: 图片持续时长(如 "1s"
:param background_filling: 背景填充配置
:return: capcut.VideoSegment
"""
try:
# 创建图片素材
image_material = capcut.VideoMaterial(self._check_path(file_name))
# 创建图片片段
image_segment = capcut.VideoSegment(
image_material,
trange(start_time, duration if duration else image_material.duration),
) # 若已设置图片持续时长则使用,否则使用视频持续时长
# 添加背景填充
if background_filling:
image_segment.add_background_filling(*background_filling)
self.draft.add_segment(image_segment)
return image_segment
except Exception:
raise RuntimeError("添加图片/贴纸发生异常")
def add_text(
self,
content: str,
target_timerange: trange,
font: capcut.FontType = capcut.FontType.悠然体,
color: Tuple[float, float, float] = (1.0, 1.0, 0.0),
position_y: float = -0.8,
outro_animation: Optional[capcut.TextOutro] = capcut.TextOutro.故障闪动,
anim_duration: tim = tim("1s"),
bubble_id: Optional[str] = "7446997603268496646",
effect_id: Optional[str] = "7336825073334078725",
) -> capcut.TextSegment:
"""
添加文字片段
Args:
content: 文字内容
target_timerange: 文字显示的时间范围(通常对齐视频片段)
font: 字体类型
color: 文字颜色RGB0-1
position_y: 文字Y轴位置-0.8为屏幕下方)
outro_animation: 出场动画None则不添加
anim_duration: 动画时长
bubble_id: 气泡效果IDNone则不添加
effect_id: 花字效果IDNone则不添加
Returns:
capcut.TextSegment: 创建的文字片段对象
"""
try:
# 创建文字片段
text_segment = capcut.TextSegment(
content,
target_timerange,
font=font,
style=capcut.TextStyle(color=color),
clip_settings=capcut.ClipSettings(transform_y=position_y),
)
# 添加出场动画
if outro_animation:
text_segment.add_animation(outro_animation, duration=anim_duration)
# 添加气泡
if bubble_id:
text_segment.add_bubble(bubble_id, bubble_id)
# 添加花字
if effect_id:
text_segment.add_effect(effect_id)
self.draft.add_segment(text_segment)
return text_segment
except Exception:
raise RuntimeError("添加文字片段发生异常")
def save(self) -> None:
"""保存草稿"""
try:
self.draft.save()
print("草稿保存成功")
except Exception:
raise RuntimeError(f"保存草稿发生异常")
# ======================== 调用示例(使用抽象后的方法) ========================
def main():
"""生成脚本"""
# 实例化
draft = Draft(
draft_name="demo2",
)
# 添加音频
draft.add_audio(
file_name="audio.mp3",
start_time="0s",
duration="5s",
volume=0.6,
)
# 添加视频
video_segment = draft.add_video(
file_name="video.mp4",
start_time="0s",
duration="4.2s",
keyframes=[
(capcut.KeyframeProperty.position_x, tim(0), -2),
(capcut.KeyframeProperty.position_x, tim("0.5s"), 0),
],
)
# 添加图片/贴纸
draft.add_image(
file_name="sticker.gif",
start_time=video_segment.end, # 视频结束位置开始
background_filling=("blur", 0.0625),
)
# 添加文字
draft.add_text(
content="抽象化后更易扩展!",
target_timerange=video_segment.target_timerange,
position_y=-0.5, # 微调位置
)
# 保存草稿
draft.save()
if __name__ == "__main__":
main()