Skip to main content
Glama

add_video_segment

Add video segments to specific tracks in JianYing MCP for video editing, allowing precise timing, speed adjustments, volume control, and visual transformations.

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")

# 指定源时间范围
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})

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
track_idYes
materialYes
target_start_endYes
source_start_endNo
speedNo
volumeNo
change_pitchNo
clip_settingsNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
dataNo
messageYes
successYes

Implementation Reference

  • MCP tool handler: validates and parses input parameters (target_start_end to timerange), resolves track_id to draft_id/track_name via index_manager, calls service layer, indexes the new video_segment_id.
    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 layer: instantiates VideoSegment with draft_id and track_name, calls its add_video_segment method passing all parameters, captures video_segment_id, returns ToolResponse with results.
    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 business logic: parses time ranges, downloads and validates material, conditionally assembles params, validates track and overlaps, generates ID, constructs operation JSON, appends to draft/video.json via add_json_to_file, sets instance ID.
    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
  • Main server entrypoint: imports and invokes video_tools(mcp) to register the video tools including add_video_segment with FastMCP instance.
    from jianyingdraft.tool.draft_tool import draft_tools
    from jianyingdraft.tool.track_tool import track_tools
    from jianyingdraft.tool.video_tool import video_tools
    from jianyingdraft.tool.text_tool import text_tools
    from jianyingdraft.tool.audio_tool import audio_tools
    from jianyingdraft.tool.utility_tool import utility_tools
    
    
    def main():
        # 注册所有工具
        draft_tools(mcp)
        track_tools(mcp)
        video_tools(mcp)
        text_tools(mcp)
        audio_tools(mcp)
        utility_tools(mcp)
        mcp.run()
  • Detailed input schema and parameter descriptions in the tool function docstring, including examples and constraints.
    """
    添加视频片段到指定轨道,须注意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})
    """
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden and does well. It explains critical behavioral constraints: target timeranges cannot overlap on the same track, source timerange defaults to full duration, and speed parameter overrides target timerange duration when combined with source timerange. It also describes the return format with video_segment_id.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is comprehensive but lengthy with parameter documentation that might be better handled in schema descriptions. However, it's well-structured with clear sections (Args, Returns, Examples) and every sentence adds value. The front-loaded purpose statement is clear, but the overall length reduces conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 8-parameter mutation tool with no annotations and 0% schema coverage, the description provides exceptional completeness. It covers purpose, parameter semantics, behavioral constraints, return format with video_segment_id, and includes practical examples. The output schema exists but the description still adds valuable context about the response structure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by providing detailed semantic explanations for all 8 parameters. It clarifies format requirements (e.g., '1s-4.2s'), default values, optional vs required status, interaction rules between parameters, and even provides a complete default structure for clip_settings with all sub-parameters documented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a clear purpose statement: '添加视频片段到指定轨道' (Add video segment to specified track). It specifies the exact action (add) and resource (video segment to track), and distinguishes from siblings like add_audio_segment, add_text_segment, and add_video_effect by focusing specifically on video segments.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context about when to use source_start_end ('一般情况下不设置,除非用户说明' - generally not set unless user specifies) and explains interaction rules between speed and target_timerange. However, it doesn't explicitly state when to use this tool versus alternatives like add_video_effect or add_video_transition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hey-jian-wei/jianying-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server