2604007 更新短视频广告合成方法

This commit is contained in:
liubiren 2026-04-07 19:00:13 +08:00
parent af44e24d60
commit cf790bc3db
3 changed files with 71 additions and 32 deletions

Binary file not shown.

View File

@ -21,7 +21,7 @@ from drafts import Drafts
sys.path.append(Path(__file__).parent.parent.as_posix()) sys.path.append(Path(__file__).parent.parent.as_posix())
class JianYingManager: class DraftsManager:
""" """
剪映草稿管理器 剪映草稿管理器
""" """
@ -45,11 +45,11 @@ class JianYingManager:
# 初始化所有素材 # 初始化所有素材
self.materials = self._init_materials() self.materials = self._init_materials()
# 初始化成品文件夹路径 # 初始化导出视频文件夹路径
self.products_folder_path = Path( self.products_folder_path = Path(
materials_folder_path.replace("materials", "products") materials_folder_path.replace("materials", "products")
) )
# 若成品文件夹存路径已存在则先删除 # 若导出视频文件夹路径已存在则先删除
if self.products_folder_path.exists(): if self.products_folder_path.exists():
shutil.rmtree(self.products_folder_path) shutil.rmtree(self.products_folder_path)
self.products_folder_path.mkdir(parents=True) self.products_folder_path.mkdir(parents=True)
@ -150,7 +150,7 @@ class JianYingManager:
# 构建标识图片路径 # 构建标识图片路径
logo_image_path = self.materials_folder_path / "标识图片.png" logo_image_path = self.materials_folder_path / "标识图片.png"
if logo_image_path.exists() and logo_image_path.is_file(): if logo_image_path.exists() and logo_image_path.is_file():
materials["logo_image_path"] = [logo_image_path] # 有且只有一张标识 materials["logo_image_path"] = [logo_image_path] # 有且只有一张标识图片
else: else:
materials["logo_image_path"] = [] materials["logo_image_path"] = []
@ -175,6 +175,15 @@ class JianYingManager:
else: else:
materials["statement_texts"] = [] materials["statement_texts"] = []
# 构建声明图片路径
statement_image_path = self.materials_folder_path / "声明图片.png"
if statement_image_path.exists() and statement_image_path.is_file():
materials["statement_image_path"] = [
statement_image_path
] # 有且只有一张声明图片
else:
materials["statement_image_path"] = []
# 构建声明视频文件夹路径 # 构建声明视频文件夹路径
statement_video_folder_path = self.materials_folder_path / "声明视频" statement_video_folder_path = self.materials_folder_path / "声明视频"
if ( if (
@ -215,11 +224,16 @@ class JianYingManager:
"淘宝闪购_达人": [ "淘宝闪购_达人": [
"add_background_video", "add_background_video",
"add_background_audio", "add_background_audio",
"add_subtitle_video",
"add_mid_roll_video", "add_mid_roll_video",
"add_post_roll_video", "add_post_roll_video",
"add_logo_video", "add_logo_video",
"add_statement_video", "add_statement_video",
], # 淘宝闪购_达人先就背景视频、背景音频、字幕视频截取前 5 秒,再添加中贴视频、后贴视频、标识视频、声明视频和生成视频 ], # 先分别添加背景视频(其中背景视频叠加背景音频和字幕视频,支持设置截取背景视频持续时长)、中贴视频和后贴视频,最后叠加标识视频和声明视频
"存量": [
"add_background_video",
"add_statement_image",
], # 就背景视频添加声明图片
} }
# 默认以素材文件夹名称为工作流名称 # 默认以素材文件夹名称为工作流名称
workflow_name = self.materials_folder_path.stem workflow_name = self.materials_folder_path.stem
@ -228,7 +242,7 @@ class JianYingManager:
if not workflow: if not workflow:
raise RuntimeError(f"该工作流 {workflow_name} 未配置") raise RuntimeError(f"该工作流 {workflow_name} 未配置")
# 节点配置模板 # 所有工作配置
configurations = { configurations = {
"generate_subtitle": { "generate_subtitle": {
"texts": self.materials["subtitle_texts"], "texts": self.materials["subtitle_texts"],
@ -318,6 +332,17 @@ class JianYingManager:
}, },
], # 图像调节设置 ], # 图像调节设置
}, # 添加声明工作配置 }, # 添加声明工作配置
"add_statement_image": {
"material_path": self.materials["statement_image_path"],
"clip_settings": [
{
"scale_x": 0.4,
"scale_y": 0.4,
"transform_x": 0.00,
"transform_y": -0.85,
},
],
}, # 添加声明图片工作配置
"add_statement_video": { "add_statement_video": {
"material_path": self.materials["statement_video_path"], "material_path": self.materials["statement_video_path"],
"volume": [1.0], # 播放音量 "volume": [1.0], # 播放音量
@ -379,7 +404,7 @@ class JianYingManager:
video_width: int = 1080, video_width: int = 1080,
video_height: int = 1920, video_height: int = 1920,
video_fps: int = 30, video_fps: int = 30,
duration_capture: Optional[int] = None, capture_duration: Optional[int] = None,
) -> None: ) -> None:
""" """
批量创建草稿 批量创建草稿
@ -387,29 +412,38 @@ class JianYingManager:
:param video_width: 视频宽度单位为像素默认为 1080 :param video_width: 视频宽度单位为像素默认为 1080
:param video_height: 视频高度单位为像素默认为 1920 :param video_height: 视频高度单位为像素默认为 1920
:param video_fps: 视频帧率单位为帧/默认为 30 :param video_fps: 视频帧率单位为帧/默认为 30
:param duration_capture: 截取背景视频时长单位为秒默认为 None :param capture_duration: 截取背景视频时长单位为秒默认为 None
:return: :return:
""" """
draft_index = 1 # 草稿索引 draft_index = 1 # 草稿索引
while True: while True:
# 获取节点配置 # 获取工作配置
configurations = self._get_configurations(duration_capture=duration_capture) configurations = self._get_configurations(capture_duration=capture_duration)
# 若包含添加字幕视频则使用字幕视频时长作为视频时长,否则使用背景视频时长作为视频时长 # 若包含添加字幕视频则使用字幕视频时长作为视频时长,否则使用背景视频时长作为视频时长
if "add_subtitle_video" in configurations: if "add_subtitle_video" in configurations:
video_duration = VideoMaterial( video_duration = min(
path=configurations["add_subtitle_video"][ VideoMaterial(
"material_path" path=configurations["add_background_video"][
].as_posix() "material_path"
).duration ].as_posix()
).duration,
VideoMaterial(
path=configurations["add_subtitle_video"][
"material_path"
].as_posix()
).duration,
)
else: else:
video_duration = video_duration = VideoMaterial( video_duration = video_duration = VideoMaterial(
path=configurations["add_background_video"][ path=configurations["add_background_video"][
"material_path" "material_path"
].as_posix() ].as_posix()
).duration ).duration
if duration_capture:
video_duration = duration_capture * 1_000_000 # 转换为微秒单位 # 转换为微秒单位
if capture_duration:
video_duration = capture_duration * 1_000_000
# 添加中贴视频持续时长 # 添加中贴视频持续时长
if "add_mid_roll_video" in configurations: if "add_mid_roll_video" in configurations:
@ -479,7 +513,7 @@ class JianYingManager:
print("-> 正在添加字幕视频...", end="") print("-> 正在添加字幕视频...", end="")
draft.add_video_segment(**configurations[node_name]) draft.add_video_segment(**configurations[node_name])
print("已完成") print("已完成")
# 添加标识 # 添加标识图片
case "add_logo_image": case "add_logo_image":
print("-> 正在添加标识图片...", end="") print("-> 正在添加标识图片...", end="")
draft.add_video_segment(**configurations[node_name]) draft.add_video_segment(**configurations[node_name])
@ -494,6 +528,11 @@ class JianYingManager:
print("-> 正在添加声明文本...", end="") print("-> 正在添加声明文本...", end="")
draft.add_text_segment(**configurations[node_name]) draft.add_text_segment(**configurations[node_name])
print("已完成") print("已完成")
# 添加声明图片
case "add_statement_image":
print("-> 正在添加声明图片...", end="")
draft.add_video_segment(**configurations[node_name])
print("已完成")
# 添加声明视频 # 添加声明视频
case "add_statement_video": case "add_statement_video":
print("-> 正在添加声明视频...", end="") print("-> 正在添加声明视频...", end="")
@ -525,12 +564,12 @@ class JianYingManager:
def _get_configurations( def _get_configurations(
self, self,
duration_capture: Optional[int] = None, capture_duration: Optional[int] = None,
) -> Dict[str, Any]: ) -> Dict[str, Any]:
""" """
获取节点配置 获取工作配置
:param duration_capture: 截取背景视频时长单位为秒默认为 None :param capture_duration: 截取背景视频时长单位为秒默认为 None
:return: 节点配置 :return: 工作配置
""" """
configurations = {} configurations = {}
for node_name in self.configurations: for node_name in self.configurations:
@ -559,11 +598,11 @@ class JianYingManager:
background_video_duration = VideoMaterial( background_video_duration = VideoMaterial(
path=configurations["add_background_video"]["material_path"].as_posix() path=configurations["add_background_video"]["material_path"].as_posix()
).duration ).duration
if duration_capture: if capture_duration:
background_video_duration = duration_capture * 1_000_000 background_video_duration = capture_duration * 1_000_000
# 若包含添加字幕频则在添加背景视频时其播放音量设置为 0 # 若包含添加字幕频则在添加背景视频时其播放音量设置为 0
if "add_subtitle_audio" in configurations: if "add_subtitle_video" in configurations:
configurations["add_background_video"]["volume"] = 0.0 configurations["add_background_video"]["volume"] = 0.0
# 中贴视频特殊处理:背景视频、背景音频和字幕视频在轨道上的范围为 (0, 背景视频时长),中贴视频在轨道上的范围为 (背景视频时长, 中贴视频时长) # 中贴视频特殊处理:背景视频、背景音频和字幕视频在轨道上的范围为 (0, 背景视频时长),中贴视频在轨道上的范围为 (背景视频时长, 中贴视频时长)

View File

@ -4,15 +4,15 @@
""" """
# 列举导入模块 # 列举导入模块
from jiangying_manager import JianYingManager from drafts_manager import DraftsManager
if __name__ == "__main__": if __name__ == "__main__":
# 实例化 JianYingManager # 实例化 DraftsManager
jianying_manager = JianYingManager( drafts_manager = DraftsManager(
materials_folder_path=r"E:\jianying\materials\淘宝闪购_达人", materials_folder_path=r"E:\jianying\materials\存量",
) )
# 导出视频 # 导出视频
jianying_manager.batch_create( drafts_manager.batch_create(
draft_counts=200, draft_counts=1,
) )