Skip to main content
Glama

JianYing MCP

by hey-jian-wei
segment.py9.97 kB
"""定义片段基类及部分比较通用的属性类""" import uuid from typing import Optional, Dict, List, Any, Union from .animation import SegmentAnimations from .time_util import Timerange, tim from .keyframe import KeyframeList, KeyframeProperty class BaseSegment: """片段基类""" segment_id: str """片段全局id, 由程序自动生成""" material_id: str """使用的素材id""" target_timerange: Timerange """片段在轨道上的时间范围""" common_keyframes: List[KeyframeList] """各属性的关键帧列表""" def __init__(self, material_id: str, target_timerange: Timerange): self.segment_id = uuid.uuid4().hex self.material_id = material_id self.target_timerange = target_timerange self.common_keyframes = [] @property def start(self) -> int: """片段开始时间, 单位为微秒""" return self.target_timerange.start @start.setter def start(self, value: int): self.target_timerange.start = value @property def duration(self) -> int: """片段持续时间, 单位为微秒""" return self.target_timerange.duration @duration.setter def duration(self, value: int): self.target_timerange.duration = value @property def end(self) -> int: """片段结束时间, 单位为微秒""" return self.target_timerange.end def overlaps(self, other: "BaseSegment") -> bool: """判断是否与另一个片段有重叠""" return self.target_timerange.overlaps(other.target_timerange) def export_json(self) -> Dict[str, Any]: """返回通用于各种片段的属性""" return { "enable_adjust": True, "enable_color_correct_adjust": False, "enable_color_curves": True, "enable_color_match_adjust": False, "enable_color_wheels": True, "enable_lut": True, "enable_smart_color_adjust": False, "last_nonzero_volume": 1.0, "reverse": False, "track_attribute": 0, "track_render_index": 0, "visible": True, # 写入自定义字段 "id": self.segment_id, "material_id": self.material_id, "target_timerange": self.target_timerange.export_json(), "common_keyframes": [kf_list.export_json() for kf_list in self.common_keyframes], "keyframe_refs": [], # 意义不明 } class Speed: """播放速度对象, 目前只支持固定速度""" global_id: str """全局id, 由程序自动生成""" speed: float """播放速度""" def __init__(self, speed: float): self.global_id = uuid.uuid4().hex self.speed = speed def export_json(self) -> Dict[str, Any]: return { "curve_speed": None, "id": self.global_id, "mode": 0, "speed": self.speed, "type": "speed" } class ClipSettings: """素材片段的图像调节设置""" alpha: float """图像不透明度, 0-1""" flip_horizontal: bool """是否水平翻转""" flip_vertical: bool """是否垂直翻转""" rotation: float """顺时针旋转的**角度**, 可正可负""" scale_x: float """水平缩放比例""" scale_y: float """垂直缩放比例""" transform_x: float """水平位移, 单位为半个画布宽""" transform_y: float """垂直位移, 单位为半个画布高""" def __init__(self, *, alpha: float = 1.0, flip_horizontal: bool = False, flip_vertical: bool = False, rotation: float = 0.0, scale_x: float = 1.0, scale_y: float = 1.0, transform_x: float = 0.0, transform_y: float = 0.0): """初始化图像调节设置, 默认不作任何图像变换 Args: alpha (float, optional): 图像不透明度, 0-1. 默认为1.0. flip_horizontal (bool, optional): 是否水平翻转. 默认为False. flip_vertical (bool, optional): 是否垂直翻转. 默认为False. rotation (float, optional): 顺时针旋转的**角度**, 可正可负. 默认为0.0. scale_x (float, optional): 水平缩放比例. 默认为1.0. scale_y (float, optional): 垂直缩放比例. 默认为1.0. transform_x (float, optional): 水平位移, 单位为半个画布宽. 默认为0.0. transform_y (float, optional): 垂直位移, 单位为半个画布高. 默认为0.0. 参考: 剪映导入的字幕似乎取此值为-0.8 """ self.alpha = alpha self.flip_horizontal, self.flip_vertical = flip_horizontal, flip_vertical self.rotation = rotation self.scale_x, self.scale_y = scale_x, scale_y self.transform_x, self.transform_y = transform_x, transform_y def export_json(self) -> Dict[str, Any]: clip_settings_json = { "alpha": self.alpha, "flip": {"horizontal": self.flip_horizontal, "vertical": self.flip_vertical}, "rotation": self.rotation, "scale": {"x": self.scale_x, "y": self.scale_y}, "transform": {"x": self.transform_x, "y": self.transform_y} } return clip_settings_json class MediaSegment(BaseSegment): """媒体片段基类""" source_timerange: Optional[Timerange] """截取的素材片段的时间范围, 对贴纸而言不存在""" speed: Speed """播放速度设置""" volume: float """音量""" change_pitch: bool """是否跟随变速改变音调""" extra_material_refs: List[str] """附加的素材id列表, 用于链接动画/特效等""" def __init__(self, material_id: str, source_timerange: Optional[Timerange], target_timerange: Timerange, speed: float, volume: float, change_pitch: bool): super().__init__(material_id, target_timerange) self.source_timerange = source_timerange self.speed = Speed(speed) self.volume = volume self.change_pitch = change_pitch self.extra_material_refs = [self.speed.global_id] def export_json(self) -> Dict[str, Any]: """返回通用于音频和视频片段的默认属性""" ret = super().export_json() ret.update({ "source_timerange": self.source_timerange.export_json() if self.source_timerange else None, "speed": self.speed.speed, "volume": self.volume, "extra_material_refs": self.extra_material_refs, "is_tone_modify": self.change_pitch, }) return ret class VisualSegment(MediaSegment): """视觉片段基类,用于处理所有可见片段(视频、贴纸、文本)的共同属性和行为""" clip_settings: ClipSettings """图像调节设置, 其效果可被关键帧覆盖""" uniform_scale: bool """是否锁定XY轴缩放比例""" animations_instance: Optional[SegmentAnimations] """动画实例, 可能为空 在放入轨道时自动添加到素材列表中 """ def __init__(self, material_id: str, source_timerange: Optional[Timerange], target_timerange: Timerange, speed: float, volume: float, change_pitch: bool, *, clip_settings: Optional[ClipSettings]): """初始化视觉片段基类 Args: material_id (`str`): 素材id source_timerange (`Timerange`, optional): 截取的素材片段的时间范围 target_timerange (`Timerange`): 片段在轨道上的目标时间范围 speed (`float`): 播放速度 volume (`float`): 音量 change_pitch (`bool`): 是否跟随变速改变音调 clip_settings (`ClipSettings`, optional): 图像调节设置, 默认不作任何变换 """ super().__init__(material_id, source_timerange, target_timerange, speed, volume, change_pitch) self.clip_settings = clip_settings if clip_settings is not None else ClipSettings() self.uniform_scale = True self.animations_instance = None def add_keyframe(self, _property: KeyframeProperty, time_offset: Union[int, str], value: float) -> "VisualSegment": """为给定属性创建一个关键帧, 并自动加入到关键帧列表中 Args: _property (`KeyframeProperty`): 要控制的属性 time_offset (`int` or `str`): 关键帧的时间偏移量, 单位为微秒. 若传入字符串则会调用`tim()`函数进行解析. value (`float`): 属性在`time_offset`处的值 Raises: `ValueError`: 试图同时设置`uniform_scale`以及`scale_x`或`scale_y`其中一者 """ if (_property == KeyframeProperty.scale_x or _property == KeyframeProperty.scale_y) and self.uniform_scale: self.uniform_scale = False elif _property == KeyframeProperty.uniform_scale: if not self.uniform_scale: raise ValueError("已设置 scale_x 或 scale_y 时, 不能再设置 uniform_scale") _property = KeyframeProperty.scale_x if isinstance(time_offset, str): time_offset = tim(time_offset) for kf_list in self.common_keyframes: if kf_list.keyframe_property == _property: kf_list.add_keyframe(time_offset, value) return self kf_list = KeyframeList(_property) kf_list.add_keyframe(time_offset, value) self.common_keyframes.append(kf_list) return self def export_json(self) -> Dict[str, Any]: """导出通用于所有视觉片段的JSON数据""" json_dict = super().export_json() json_dict.update({ "clip": self.clip_settings.export_json(), "uniform_scale": {"on": self.uniform_scale, "value": 1.0}, }) return json_dict

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