fix(entity): 修复缩放效果

fix(entity): 移除 ffmpeg缩放和裁剪滤镜中的 setpts 指令

移除了 ffmpeg 缩放、裁剪和尾部处理滤镜中的 setpts=PTS-STARTPTS指令。这个指令在某些情况下可能导致视频处理出现问题,例如在使用 zoompan 滤镜时。此修改旨在提高视频处理的稳定性和正确性。

fix(entity): 修复缩放效果中中心点计算错误

-针对静态缩放和动态缩放分别修正了中心点计算公式
- 确保在不同缩放因子下,图像中心点位置保持正确

fix(entity): 修复 ffmpeg zoompan 滤镜参数

-将 zoompan 滤镜的参数从 'z=' 改为 'z=',统一参数格式- 此修改解决了 ffmpeg 在处理某些视频时可能遇到的参数解析问题

feat(zoom): 实现视频缩放特效的自定义中心点功能

- 添加代码以解析 posJson 数据,计算并设置缩放中心点
- 使用 zoompan滤镜替代原有的 scale 和 crop滤镜,支持动态缩放
- 优化静态缩放的实现,确保整个视频时长的应用

fix(entity): 修复视频缩放效果的 FFmpeg 命令

- 在 zoom_expr 中添加转义字符,以解决 FFmpeg 解析问题
- 修改缩放和裁剪滤镜的参数,提高视频处理的准确性
This commit is contained in:
2025-09-12 11:24:24 +08:00
parent 1571934943
commit c36e838d4f

View File

@@ -299,11 +299,42 @@ class FfmpegTask(object):
if zoom_factor == 1:
continue
effect_index += 1
# 获取缩放中心点(从pos_json或使用默认中心)
center_x = "iw/2"
center_y = "ih/2"
pos_json_str = self.ext_data.get('posJson', '{}')
try:
pos_json = json.loads(pos_json_str) if pos_json_str != '{}' else {}
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}"
except Exception as e:
# 解析失败使用默认中心
pass
if duration == 0:
filter_args.append(f"{video_output_str}trim=start={start_time},scale=iw*{zoom_factor}:ih*{zoom_factor},crop=iw/{zoom_factor}:ih/{zoom_factor}:(iw-iw/{zoom_factor})/2:(ih-ih/{zoom_factor})/2,setpts=PTS-STARTPTS[v_eff{effect_index}]")
# 静态缩放(整个视频时长)
x_expr = f"({center_x})-(ow*zoom)/2"
y_expr = f"({center_y})-(oh*zoom)/2"
filter_args.append(f"{video_output_str}trim=start={start_time},zoompan=z={zoom_factor}:x={x_expr}:y={y_expr}:d=1[v_eff{effect_index}]")
else:
zoom_expr = f"if(between(t,{start_time},{start_time + duration}),{zoom_factor},1)"
filter_args.append(f"{video_output_str}scale=iw*({zoom_expr}):ih*({zoom_expr}),crop=iw:ih:(iw-iw)/2:(ih-ih)/2[v_eff{effect_index}]")
# 动态缩放(指定时间段内)
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_output_str}zoompan=z={zoom_expr}:x={x_expr}:y={y_expr}:d=1[v_eff{effect_index}]")
video_output_str = f"[v_eff{effect_index}]"
elif effect.startswith("skip:"):
param = effect.split(":", 2)[1]
@@ -312,7 +343,7 @@ class FfmpegTask(object):
skip_seconds = float(param)
if skip_seconds > 0:
effect_index += 1
filter_args.append(f"{video_output_str}trim=start={skip_seconds},setpts=PTS-STARTPTS[v_eff{effect_index}]")
filter_args.append(f"{video_output_str}trim=start={skip_seconds}[v_eff{effect_index}]")
video_output_str = f"[v_eff{effect_index}]"
elif effect.startswith("tail:"):
param = effect.split(":", 2)[1]
@@ -324,7 +355,7 @@ class FfmpegTask(object):
# 首先获取视频总时长,然后计算开始时间
# 使用reverse+trim+reverse的方法来精确获取最后N秒
filter_args.append(f"{video_output_str}reverse[v_rev{effect_index}]")
filter_args.append(f"[v_rev{effect_index}]trim=duration={tail_seconds},setpts=PTS-STARTPTS[v_trim{effect_index}]")
filter_args.append(f"[v_rev{effect_index}]trim=duration={tail_seconds}[v_trim{effect_index}]")
filter_args.append(f"[v_trim{effect_index}]reverse[v_eff{effect_index}]")
video_output_str = f"[v_eff{effect_index}]"
...