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
"""定义片段基类及部分比较通用的属性类"""
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