add_video_segment
Add a video segment to a specific track in JianYing (CapCut) video editing, allowing precise timing, speed adjustments, volume control, and visual transformations for professional video production.
Instructions
添加视频片段到指定轨道,须注意target_timerange和source_timerange的使用规则
Args:
track_id: 轨道ID,通过create_track获得
material: 视频文件路径,包括文本文件路径或者url
target_start_end: 片段在轨道上的目标时间范围,格式如 "1s-4.2s",表示在轨道上从1s开始,到4.2s结束,target_start_end参数描述的是轨道上的时间范围,同一轨道中不可有重复时间段,即0s-4.2s和4s-5s,第一段素材最后0.2s与第二段素材重叠了,只能是0s-4.2s和4.ss-5s
source_start_end: 从源视频文件中截取的时间范围,格式如 "1s-4.2s",表示从源视频的1s开始截取,到4.2s结束(可选),source_start_end参数描述的是素材本身取的时长,默认取全部时长,一般情况下不设置,除非用户说明,若素材时长为5s,用户需要取其中1s-5s的内容,才配置
speed: (float, optional): 播放速度, 默认为1.0,此项与source_timerange同时指定时, 将覆盖target_timerange中的时长
volume: (float, optional): 音量, 默认为1.0
change_pitch: (bool, optional): 是否跟随变速改变音调, 默认为否
clip_settings: (Dict, optional)图像调节设置字典(可选),哪些需要修改就填哪些字段
默认 clip_settings = {
"alpha": 1.0, # 图像不透明度, 0-1. 默认为1.0.
"flip_horizontal": False, # 是否水平翻转. 默认为False.
"flip_vertical": False, # 是否垂直翻转. 默认为False.
"rotation": 0.0, # 顺时针旋转的角度, 可正可负. 默认为0.0.
"scale_x": 1.0, # 水平缩放比例. 默认为1.0.
"scale_y": 1.0, # 垂直缩放比例. 默认为1.0.
"transform_x": 0.0, # 水平位移, 单位为半个画布宽. 默认为0.0.
"transform_y": 0.0 # 垂直位移, 单位为半个画布高. 默认为0.0.
}
Returns: ToolResponse: 包含操作结果的响应,格式为 {"success": bool, "message": str, "data": dict, "video_segment_id": str}
Examples: # 基本用法 add_video_segment("track_id", "/path/to/video.mp4", "0s-5s")
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| track_id | Yes | ||
| material | Yes | ||
| target_start_end | Yes | ||
| source_start_end | No | ||
| speed | No | ||
| volume | No | ||
| change_pitch | No | ||
| clip_settings | No |
Implementation Reference
- jianyingdraft/tool/video_tool.py:22-127 (handler)MCP tool registration and handler function for 'add_video_segment'. Parses time formats, resolves draft_id and track_name from track_id using index_manager, calls the service layer, and manages video_segment_id indexing.@mcp.tool() def add_video_segment( track_id: str, material: str, target_start_end: str, source_start_end: Optional[str] = None, speed: Optional[float] = None, volume: float = 1.0, change_pitch: bool = False, clip_settings: Optional[Dict[str, Any]] = None ) -> ToolResponse: """ 添加视频片段到指定轨道,须注意target_timerange和source_timerange的使用规则 Args: track_id: 轨道ID,通过create_track获得 material: 视频文件路径,包括文本文件路径或者url target_start_end: 片段在轨道上的目标时间范围,格式如 "1s-4.2s",表示在轨道上从1s开始,到4.2s结束,target_start_end参数描述的是轨道上的时间范围,同一轨道中不可有重复时间段,即0s-4.2s和4s-5s,第一段素材最后0.2s与第二段素材重叠了,只能是0s-4.2s和4.ss-5s source_start_end: 从源视频文件中截取的时间范围,格式如 "1s-4.2s",表示从源视频的1s开始截取,到4.2s结束(可选),source_start_end参数描述的是素材本身取的时长,默认取全部时长,一般情况下不设置,除非用户说明,若素材时长为5s,用户需要取其中1s-5s的内容,才配置 speed: (`float`, optional): 播放速度, 默认为1.0,此项与`source_timerange`同时指定时, 将覆盖`target_timerange`中的时长 volume: (`float`, optional): 音量, 默认为1.0 change_pitch: (`bool`, optional): 是否跟随变速改变音调, 默认为否 clip_settings: (`Dict`, optional)图像调节设置字典(可选),哪些需要修改就填哪些字段 默认 clip_settings = { "alpha": 1.0, # 图像不透明度, 0-1. 默认为1.0. "flip_horizontal": False, # 是否水平翻转. 默认为False. "flip_vertical": False, # 是否垂直翻转. 默认为False. "rotation": 0.0, # 顺时针旋转的**角度**, 可正可负. 默认为0.0. "scale_x": 1.0, # 水平缩放比例. 默认为1.0. "scale_y": 1.0, # 垂直缩放比例. 默认为1.0. "transform_x": 0.0, # 水平位移, 单位为半个画布宽. 默认为0.0. "transform_y": 0.0 # 垂直位移, 单位为半个画布高. 默认为0.0. } Returns: ToolResponse: 包含操作结果的响应,格式为 {"success": bool, "message": str, "data": dict, "video_segment_id": str} Examples: # 基本用法 add_video_segment("track_id", "/path/to/video.mp4", "0s-5s") # 指定源时间范围 add_video_segment("track_id", "/path/to/video.mp4", "0s-3s", source_timerange="10s-3s") # 设置播放速度和音量 add_video_segment("track_id", "/path/to/video.mp4", "0s-5s", speed=2.0, volume=0.8) # 设置图像调节 add_video_segment("track_id", "/path/to/video.mp4", "0s-5s", clip_settings={"alpha": 0.8, "scale_x": 1.2, "rotation": 45}) """ # 将新格式转换为原来的格式 try: target_timerange = parse_start_end_format(target_start_end) except ValueError as e: return ToolResponse( success=False, message=f"target_start_end格式错误: {str(e)}" ) source_timerange = None if source_start_end is not None: try: source_timerange = parse_start_end_format(source_start_end) except ValueError as e: return ToolResponse( success=False, message=f"source_start_end格式错误: {str(e)}" ) # 通过track_id获取draft_id和track_name draft_id = index_manager.get_draft_id_by_track_id(track_id) track_name = index_manager.get_track_name_by_track_id(track_id) if not draft_id: return ToolResponse( success=False, message=f"未找到轨道ID对应的草稿: {track_id}" ) if not track_name: return ToolResponse( success=False, message=f"未找到轨道ID对应的轨道名: {track_id}" ) # 调用服务层处理业务逻辑 result = add_video_segment_service( draft_id=draft_id, material=material, target_timerange=target_timerange, source_timerange=source_timerange, speed=speed, volume=volume, change_pitch=change_pitch, clip_settings=clip_settings, track_name=track_name ) # 如果视频片段添加成功,添加索引记录 if result.success and result.data and "video_segment_id" in result.data: video_segment_id = result.data["video_segment_id"] index_manager.add_video_segment_mapping(video_segment_id, track_id) return result
- Service function that instantiates VideoSegment with draft_id and track_name, calls its add_video_segment method with provided parameters, constructs response data including video_segment_id, and returns wrapped ToolResponse.def add_video_segment_service( draft_id: str, material: str, target_timerange: str, source_timerange: Optional[str] = None, speed: Optional[float] = None, volume: float = 1.0, change_pitch: bool = False, clip_settings: Optional[Dict[str, Any]] = None, track_name: Optional[str] = None ) -> ToolResponse: """ 视频片段创建服务 - 封装复杂的视频片段创建逻辑 Args: draft_id: 草稿ID material: 视频文件路径,包括文本文件路径或者url target_timerange: 片段在轨道上的目标时间范围,格式如 "0s-4.2s" source_timerange: 从源视频文件中截取的时间范围,格式如 "1s-4.2s"(可选) speed: 播放速度,默认为1.0(可选) volume: 音量,默认为1.0(可选) change_pitch: 是否跟随变速改变音调,默认为False(可选) clip_settings: 图像调节设置字典(可选) track_name: 指定的轨道名称(可选) Returns: ToolResponse: 包含操作结果的响应对象 """ try: # 创建VideoSegment实例 video_segment = VideoSegment(draft_id, track_name=track_name) # 调用视频片段创建方法 result_data = video_segment.add_video_segment( material=material, target_timerange=target_timerange, source_timerange=source_timerange, speed=speed, volume=volume, change_pitch=change_pitch, clip_settings=clip_settings, track_name=track_name ) # 构建返回数据,包含video_segment_id response_data = { "video_segment_id": video_segment.video_segment_id, "draft_id": draft_id, "add_video_segment": result_data } # 如果有轨道名称,添加到返回数据中 if track_name: response_data["track_name"] = track_name return ToolResponse( success=True, message="视频片段创建成功", data=response_data ) except ValueError as e: # 处理参数错误(时间范围格式、轨道类型等) return ToolResponse( success=False, message=f"参数错误: {str(e)}" ) except NameError as e: # 处理轨道不存在错误 return ToolResponse( success=False, message=f"轨道错误: {str(e)}" ) except TypeError as e: # 处理轨道类型错误 return ToolResponse( success=False, message=f"轨道类型错误: {str(e)}" ) except FileNotFoundError as e: # 处理文件不存在错误 return ToolResponse( success=False, message=f"文件错误: {str(e)}" ) except Exception as e: # 处理其他未预期的错误 return ToolResponse( success=False, message=f"视频片段创建失败: {str(e)}" )
- Core implementation in VideoSegment class: parses time ranges, downloads/validates material to local path, builds operation parameters, validates track type and overlap, generates UUID for video_segment_id, saves JSON operation to file, and returns params.def add_video_segment(self, material: str, target_timerange: str, source_timerange: Optional[str] = None, speed: Optional[float] = None, volume: float = 1.0, change_pitch: bool = False, clip_settings: Optional[Dict[str, Any]] = None, track_name: Optional[str] = None) -> Dict[str, Any]: """ 创建视频片段配置 Args: material: 视频文件路径,包括文本文件路径或者url target_timerange: 片段在轨道上的目标时间范围,格式如 "0s-4.2s",表示在轨道上从0s开始,持续4.2s source_timerange: 从源视频文件中截取的时间范围,格式如 "1s-4.2s",表示从源视频的1s开始截取,持续4.2s,默认从开头根据`speed`截取与`target_timerange`等长的一部分 speed: (`float`, optional): 播放速度, 默认为1.0,此项与`source_timerange`同时指定时, 将覆盖`target_timerange`中的时长 volume: (`float`, optional): 音量, 默认为1.0 change_pitch: (`bool`, optional): 是否跟随变速改变音调, 默认为否,一般不修改 clip_settings: (`Dict`, optional)图像调节设置字典(可选),哪些需要修改就填哪些字段 默认 clip_settings = { "alpha": 1.0, # 图像不透明度, 0-1. 默认为1.0. "flip_horizontal": False, # 是否水平翻转. 默认为False. "flip_vertical": False, # 是否垂直翻转. 默认为False. "rotation": 0.0, # 顺时针旋转的**角度**, 可正可负. 默认为0.0. "scale_x": 1.0, # 水平缩放比例. 默认为1.0. "scale_y": 1.0, # 垂直缩放比例. 默认为1.0. "transform_x": 0.0, # 水平位移, 单位为半个画布宽. 默认为0.0. "transform_y": 0.0 # 垂直位移, 单位为半个画布高. 默认为0.0. } track_name: 指定的轨道名称(可选),如果不指定则使用实例的track_name Returns: Dict[str, Any]: 构造的参数字典 """ # if self.video_segment_id is None: # raise ValueError("video_segment_id不能为空") video_segment_id = str(uuid.uuid4()) # 解析target_timerange if not target_timerange or "-" not in target_timerange: raise ValueError(f"Invalid target_timerange format: {target_timerange}") start_str, duration_str = target_timerange.split("-", 1) target_timerange_data = { "start": start_str.strip(), "duration": duration_str.strip() } # 解析source_timerange(如果提供) source_timerange_data = None if source_timerange: if "-" not in source_timerange: raise ValueError(f"Invalid source_timerange format: {source_timerange}") source_start_str, source_duration_str = source_timerange.split("-", 1) source_timerange_data = { "start": source_start_str.strip(), "duration": source_duration_str.strip() } # 确定使用的轨道名称(参数优先,然后是实例属性) final_track_name = track_name or self.track_name # 下载并验证素材,获取本地化路径 local_material_path = download_and_validate_material( self.draft_id, material, "video", target_timerange_data ) # 构建add_video_segment参数(使用本地化后的路径) add_video_segment_params = { "material": local_material_path, # 使用本地化后的相对路径 "target_timerange": target_timerange_data } # 只添加用户明确传入的可选参数 if source_timerange is not None: add_video_segment_params["source_timerange"] = source_timerange_data if speed is not None: add_video_segment_params["speed"] = speed if volume != 1.0: # 只有非默认值才保存 add_video_segment_params["volume"] = volume if change_pitch: # 只有True才保存 add_video_segment_params["change_pitch"] = change_pitch if clip_settings: # 只有非空才保存 add_video_segment_params["clip_settings"] = clip_settings # 验证轨道 if final_track_name: self._validate_track_for_video(final_track_name) # 验证片段重叠 if final_track_name: validate_overlap(self.draft_id, "video", final_track_name, target_timerange_data) # 构建完整的片段数据 segment_data = { "video_segment_id": video_segment_id, "operation": "add_video_segment", "add_video_segment": add_video_segment_params, } # 只在指定了轨道名称时才添加track_name字段 if final_track_name: segment_data["track_name"] = final_track_name # 保存参数 self.add_json_to_file(segment_data) self.video_segment_id = video_segment_id return add_video_segment_params