You've already forked FrameTour-RenderWorker
79 lines
2.8 KiB
Python
79 lines
2.8 KiB
Python
from typing import List, Dict, Any
|
|
from .base import EffectProcessor
|
|
|
|
class CameraShotEffect(EffectProcessor):
|
|
"""相机镜头效果处理器"""
|
|
|
|
def validate_params(self) -> bool:
|
|
"""验证参数:start_time,duration,rotate_deg"""
|
|
params = self.parse_params()
|
|
if not params:
|
|
return True # 使用默认参数
|
|
|
|
# 参数格式: "start_time,duration,rotate_deg"
|
|
if len(params) > 3:
|
|
return False
|
|
|
|
try:
|
|
for i, param in enumerate(params):
|
|
if param == '':
|
|
continue
|
|
if i == 2: # rotate_deg
|
|
int(param)
|
|
else: # start_time, duration
|
|
float(param)
|
|
return True
|
|
except ValueError:
|
|
return False
|
|
|
|
def generate_filter_args(self, video_input: str, effect_index: int) -> tuple[List[str], str]:
|
|
"""生成相机镜头效果的滤镜参数"""
|
|
if not self.validate_params():
|
|
return [], video_input
|
|
|
|
params = self.parse_params()
|
|
|
|
# 设置默认值
|
|
start = 3.0
|
|
duration = 1.0
|
|
rotate_deg = 0
|
|
|
|
if len(params) >= 1 and params[0] != '':
|
|
start = float(params[0])
|
|
if len(params) >= 2 and params[1] != '':
|
|
duration = float(params[1])
|
|
if len(params) >= 3 and params[2] != '':
|
|
rotate_deg = int(params[2])
|
|
|
|
filter_args = []
|
|
|
|
# 生成输出流标识符
|
|
start_out_str = "[eff_s]"
|
|
mid_out_str = "[eff_m]"
|
|
end_out_str = "[eff_e]"
|
|
final_output = f"[v_eff{effect_index}]"
|
|
|
|
# 分割视频流为三部分
|
|
filter_args.append(f"{video_input}split=3{start_out_str}{mid_out_str}{end_out_str}")
|
|
|
|
# 选择开始部分帧
|
|
filter_args.append(f"{start_out_str}select=lt(n\\,{int(start * self.frame_rate)}){start_out_str}")
|
|
|
|
# 选择结束部分帧
|
|
filter_args.append(f"{end_out_str}select=gt(n\\,{int(start * self.frame_rate)}){end_out_str}")
|
|
|
|
# 选择中间特定帧并扩展
|
|
filter_args.append(f"{mid_out_str}select=eq(n\\,{int(start * self.frame_rate)}){mid_out_str}")
|
|
filter_args.append(f"{mid_out_str}tpad=start_mode=clone:start_duration={duration:.4f}{mid_out_str}")
|
|
|
|
# 如果需要旋转
|
|
if rotate_deg != 0:
|
|
filter_args.append(f"{mid_out_str}rotate=PI*{rotate_deg}/180{mid_out_str}")
|
|
|
|
# 连接三部分
|
|
filter_args.append(f"{start_out_str}{mid_out_str}{end_out_str}concat=n=3:v=1:a=0,setpts=N/{self.frame_rate}/TB{final_output}")
|
|
|
|
return filter_args, final_output
|
|
|
|
def get_effect_name(self) -> str:
|
|
return "cameraShot" |