You've already forked FrameTour-RenderWorker
feat(重构): 实现新的渲染服务架构
- 新增 RenderTask
This commit is contained in:
89
entity/effects/zoom.py
Normal file
89
entity/effects/zoom.py
Normal file
@@ -0,0 +1,89 @@
|
||||
from typing import List
|
||||
import json
|
||||
from .base import EffectProcessor
|
||||
|
||||
class ZoomEffect(EffectProcessor):
|
||||
"""缩放效果处理器"""
|
||||
|
||||
def validate_params(self) -> bool:
|
||||
"""验证参数:start_time,zoom_factor,duration"""
|
||||
params = self.parse_params()
|
||||
if len(params) < 3:
|
||||
return False
|
||||
|
||||
try:
|
||||
start_time = float(params[0])
|
||||
zoom_factor = float(params[1])
|
||||
duration = float(params[2])
|
||||
|
||||
return (start_time >= 0 and
|
||||
zoom_factor > 0 and
|
||||
duration >= 0)
|
||||
except (ValueError, IndexError):
|
||||
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_time = float(params[0])
|
||||
zoom_factor = float(params[1])
|
||||
duration = float(params[2])
|
||||
|
||||
if zoom_factor == 1:
|
||||
return [], video_input # 不需要缩放
|
||||
|
||||
output_stream = f"[v_eff{effect_index}]"
|
||||
|
||||
# 获取缩放中心点
|
||||
center_x, center_y = self._get_zoom_center()
|
||||
|
||||
filter_args = []
|
||||
|
||||
if duration == 0:
|
||||
# 静态缩放(整个视频时长)
|
||||
x_expr = f"({center_x})-(ow*zoom)/2"
|
||||
y_expr = f"({center_y})-(oh*zoom)/2"
|
||||
filter_args.append(
|
||||
f"{video_input}trim=start={start_time},zoompan=z={zoom_factor}:x={x_expr}:y={y_expr}:d=1{output_stream}"
|
||||
)
|
||||
else:
|
||||
# 动态缩放(指定时间段内)
|
||||
zoom_expr = f"if(between(t\\,{start_time}\\,{start_time + duration})\\,{zoom_factor}\\,1)"
|
||||
x_expr = f"({center_x})-(ow*zoom)/2"
|
||||
y_expr = f"({center_y})-(oh*zoom)/2"
|
||||
filter_args.append(
|
||||
f"{video_input}zoompan=z={zoom_expr}:x={x_expr}:y={y_expr}:d=1{output_stream}"
|
||||
)
|
||||
|
||||
return filter_args, output_stream
|
||||
|
||||
def _get_zoom_center(self) -> tuple[str, str]:
|
||||
"""获取缩放中心点坐标表达式"""
|
||||
# 默认中心点
|
||||
center_x = "iw/2"
|
||||
center_y = "ih/2"
|
||||
|
||||
pos_json = self.get_pos_json()
|
||||
if pos_json:
|
||||
_f_x = pos_json.get('ltX', 0)
|
||||
_f_x2 = pos_json.get('rbX', 0)
|
||||
_f_y = pos_json.get('ltY', 0)
|
||||
_f_y2 = pos_json.get('rbY', 0)
|
||||
_v_w = pos_json.get('imgWidth', 1)
|
||||
_v_h = pos_json.get('imgHeight', 1)
|
||||
|
||||
if _v_w > 0 and _v_h > 0:
|
||||
# 计算坐标系统中的中心点
|
||||
center_x_ratio = (_f_x + _f_x2) / (2 * _v_w)
|
||||
center_y_ratio = (_f_y + _f_y2) / (2 * _v_h)
|
||||
# 转换为视频坐标系统
|
||||
center_x = f"iw*{center_x_ratio:.6f}"
|
||||
center_y = f"ih*{center_y_ratio:.6f}"
|
||||
|
||||
return center_x, center_y
|
||||
|
||||
def get_effect_name(self) -> str:
|
||||
return "zoom"
|
Reference in New Issue
Block a user