python_基于主视频删减片段并插入镜头视频
# 使用此指令前,请确保安装必要的Python库,例如使用以下命令安装:
# pip install pyJianYingDraft
import pyJianYingDraft as draft
from pyJianYingDraft import trange, ClipSettings, tim
from typing import *
try:
from xbot.app.logging import trace as print
except:
from xbot import print
def create_jianying_draft_from_clips(draft_name, main_video_path, delete_ranges, lens_info_dict, draft_folder_path):
"""
title: 基于主视频删减片段并插入镜头生成剪映草稿
description: 根据主视频 %main_video_path% 创建剪映草稿,删除指定时间段 %delete_ranges%,添加镜头视频 %lens_info_dict%,并保存到草稿文件夹 %draft_folder_path%。
inputs:
– draft_name (str): 草稿项目名称,eg: "我的视频草稿"
– main_video_path (file): 主视频文件路径,eg: "C:/videos/main.mp4"
– delete_ranges (list): 需要删除的时间段列表,格式[("开始时间","结束时间")],eg: [("00:00:01,640","00:00:02,640")]
– lens_info_dict (dict): 镜头视频信息字典,格式{"镜头名":[视频路径,开始时间]},eg: {"镜头A":["C:/lens.mp4","00:00:01,640"]}
– draft_folder_path (folder): 剪映草稿文件夹路径,eg: "D:/JianyingPro Drafts"
outputs:
– None
"""
# 检查输入参数
if not draft_name or not isinstance(draft_name, str):
raise ValueError("草稿名称不能为空且必须为字符串")
if not main_video_path:
raise ValueError("主视频路径不能为空")
if not isinstance(delete_ranges, list):
raise ValueError("删除时间段必须为列表格式")
if not isinstance(lens_info_dict, dict):
raise ValueError("镜头信息必须为字典格式")
if not draft_folder_path:
raise ValueError("草稿文件夹路径不能为空")
def _convert_time(time_str):
"""时间格式转换函数(处理00:00:01,640格式)"""
try:
h, m, s_ms = time_str.replace(',', '.').split(':')
return f"{int(h)}h{int(m)}m{s_ms}s"
except Exception as e:
raise ValueError(f"时间格式错误: {time_str},正确格式应为 '00:00:01,640'")
def _add_main_video_segments(script, main_video_path, delete_ranges):
"""添加主视频片段(删除指定区间后的剩余部分)"""
script.add_track(draft.TrackType.video, "video_track") # 创建视频轨道
# 解析删除区间(转换为微秒,并按起始时间排序)
parsed_deletes = []
for start_str, end_str in delete_ranges:
start = tim(_convert_time(start_str)) # 转换为微秒
end = tim(_convert_time(end_str))
if start >= end:
raise ValueError(f"删除时间段起始时间不能大于等于结束时间: {start_str} – {end_str}")
parsed_deletes.append((start, end))
# 按起始时间排序,确保区间顺序正确
parsed_deletes.sort(key=lambda x: x[0])
# 获取视频总时长
video_material = draft.VideoMaterial(main_video_path)
total_duration = video_material.duration # 微秒
# 动态计算保留区间
keep_ranges = []
prev_end = 0 # 上一个区间的结束位置
for delete_start, delete_end in parsed_deletes:
# 若当前删除区间的起点 > 上一个区间的终点,说明中间有需要保留的部分
if delete_start > prev_end:
keep_ranges.append((prev_end, delete_start))
# 更新上一个区间的终点为当前删除区间的终点
prev_end = max(prev_end, delete_end) # 处理区间重叠的情况
# 添加最后一个保留区间(从最后一个删除区间的终点到视频结束)
if prev_end < total_duration:
keep_ranges.append((prev_end, total_duration))
# 截取并拼接保留的片段
current_start = 0 # 轨道上的起始位置(确保无缝拼接)
for keep_start, keep_end in keep_ranges:
if keep_start >= keep_end:
continue # 跳过无效区间
# 截取素材中[keep_start, keep_end)的片段
segment = draft.VideoSegment(
video_material,
target_timerange=trange(current_start, keep_end – keep_start), # 轨道上的位置和时长
source_timerange=trange(keep_start, keep_end – keep_start) # 素材中截取的区间
)
script.add_segment(segment, "video_track")
current_start += (keep_end – keep_start) # 更新下一段的起始位置
def _add_lens_videos(script, lens_info_dict, main_mat):
"""添加镜头视频到不同轨道"""
for lens_name, lens_info in lens_info_dict.items():
if len(lens_info) != 2:
raise ValueError(f"镜头信息格式错误: {lens_name},应包含[视频路径, 开始时间]")
lens_video_path, lens_start_time = lens_info
try:
lens_video_material = draft.VideoMaterial(lens_video_path)
except Exception as e:
raise ValueError(f"无法加载镜头视频: {lens_video_path}")
start_time = tim(_convert_time(lens_start_time))
# 创建视频轨道
script.add_track(draft.TrackType.video, track_name=lens_name, relative_index=1)
# 创建镜头片段
lens_segment = draft.VideoSegment(
lens_video_material,
trange(start_time, lens_video_material.duration),
# 关键设置:强制缩放镜头视频以填充整个画布,确保完全覆盖
clip_settings=ClipSettings(
scale_x=main_mat.width / lens_video_material.width, # 按宽度比例缩放
scale_y=main_mat.height / lens_video_material.height, # 按高度比例缩放
)
)
# 添加片段到对应轨道
script.add_segment(lens_segment, lens_name)
try:
# 1、创建草稿文件夹实例
draft_folder = draft.DraftFolder(draft_folder_path)
# 创建新草稿(使用主视频的分辨率)
main_mat = draft.VideoMaterial(main_video_path)
script = draft_folder.create_draft(
draft_name,
main_mat.width,
main_mat.height,
)
# 2、添加主视频片段(处理删除区间)
_add_main_video_segments(script, main_video_path, delete_ranges)
# 3、添加镜头视频
_add_lens_videos(script, lens_info_dict, main_mat)
# 4、保存草稿
script.save()
print(f"剪映草稿 '{draft_name}' 创建成功!")
except Exception as e:
raise Exception(f"创建剪映草稿失败: {str(e)}")
draft_name="草稿名称4"
main_video_path=r"C:\\Users\\Jordan\\Downloads\\【25-41格雷灰】【脚本_2】\\【25-41格雷灰】【脚本_1】.mp4"
delete_ranges=[("00:00:01,640","00:00:02,640"),("00:00:03,640","00:00:04,640")]
lens_info_dict={"镜头A":[r"C:\\Users\\Jordan\\Downloads\\【25-41格雷灰】【脚本_2】\\【25-41格雷灰】【镜头_拉链】.MP4","00:00:01,640"],"镜头B":[r"D:\\Desktop\\20251206223742_rec_.mp4","00:00:06,640"]}
draft_folder_path=r"D:\\download_software\\JianyingPro Drafts"
create_jianying_draft_from_clips(draft_name,main_video_path,delete_ranges,lens_info_dict,draft_folder_path)



