You've already forked FrameTour-RenderWorker
Compare commits
5 Commits
d770d84927
...
master
Author | SHA1 | Date | |
---|---|---|---|
d7704005b6 | |||
f85ccea933 | |||
0c7181911e | |||
cf43f6379e | |||
ce8854404b |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -32,3 +32,4 @@ target/
|
|||||||
venv/
|
venv/
|
||||||
cython_debug/
|
cython_debug/
|
||||||
.env
|
.env
|
||||||
|
.serena
|
@@ -6,4 +6,4 @@ SUPPORT_FEATURE = (
|
|||||||
'rclone_upload',
|
'rclone_upload',
|
||||||
'custom_re_encode',
|
'custom_re_encode',
|
||||||
)
|
)
|
||||||
SOFTWARE_VERSION = '0.0.5'
|
SOFTWARE_VERSION = '0.0.6'
|
||||||
|
@@ -271,7 +271,7 @@ class FfmpegTask(object):
|
|||||||
if param == '':
|
if param == '':
|
||||||
param = "1"
|
param = "1"
|
||||||
if param != "1":
|
if param != "1":
|
||||||
# 视频变速
|
# 视频变速:使用fps实现,避免PTS冲突
|
||||||
effect_index += 1
|
effect_index += 1
|
||||||
filter_args.append(f"{video_output_str}setpts={param}*PTS[v_eff{effect_index}]")
|
filter_args.append(f"{video_output_str}setpts={param}*PTS[v_eff{effect_index}]")
|
||||||
video_output_str = f"[v_eff{effect_index}]"
|
video_output_str = f"[v_eff{effect_index}]"
|
||||||
@@ -280,29 +280,24 @@ class FfmpegTask(object):
|
|||||||
if param == '':
|
if param == '':
|
||||||
continue
|
continue
|
||||||
_split = param.split(",")
|
_split = param.split(",")
|
||||||
if len(_split) < 3:
|
if len(_split) < 2:
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
start_time = float(_split[0])
|
start_time = float(_split[0])
|
||||||
zoom_factor = float(_split[1])
|
zoom_factor = float(_split[1])
|
||||||
duration = float(_split[2])
|
|
||||||
if start_time < 0:
|
if start_time < 0:
|
||||||
start_time = 0
|
start_time = 0
|
||||||
if duration < 0:
|
|
||||||
duration = 0
|
|
||||||
if zoom_factor <= 0:
|
if zoom_factor <= 0:
|
||||||
zoom_factor = 1
|
zoom_factor = 1
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError):
|
||||||
start_time = 0
|
start_time = 0
|
||||||
duration = 0
|
|
||||||
zoom_factor = 1
|
zoom_factor = 1
|
||||||
if zoom_factor == 1:
|
if zoom_factor == 1:
|
||||||
continue
|
continue
|
||||||
effect_index += 1
|
effect_index += 1
|
||||||
|
|
||||||
# 获取缩放中心点(从pos_json或使用默认中心)
|
left_x = f"iw/(2*{zoom_factor})"
|
||||||
center_x = "iw/2"
|
top_y = f"ih/(2*{zoom_factor})"
|
||||||
center_y = "ih/2"
|
|
||||||
pos_json_str = self.ext_data.get('posJson', '{}')
|
pos_json_str = self.ext_data.get('posJson', '{}')
|
||||||
try:
|
try:
|
||||||
pos_json = json.loads(pos_json_str) if pos_json_str != '{}' else {}
|
pos_json = json.loads(pos_json_str) if pos_json_str != '{}' else {}
|
||||||
@@ -318,23 +313,14 @@ class FfmpegTask(object):
|
|||||||
center_x_ratio = (_f_x + _f_x2) / (2 * _v_w)
|
center_x_ratio = (_f_x + _f_x2) / (2 * _v_w)
|
||||||
center_y_ratio = (_f_y + _f_y2) / (2 * _v_h)
|
center_y_ratio = (_f_y + _f_y2) / (2 * _v_h)
|
||||||
# 转换为视频坐标系统
|
# 转换为视频坐标系统
|
||||||
center_x = f"iw*{center_x_ratio:.6f}"
|
left_x = f"iw*({center_x_ratio:.6f}-1/(2*{zoom_factor}))"
|
||||||
center_y = f"ih*{center_y_ratio:.6f}"
|
top_y = f"ih*({center_y_ratio:.6f}-1/(2*{zoom_factor}))"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# 解析失败使用默认中心
|
# 解析失败使用默认中心
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if duration == 0:
|
# 静态缩放(整个视频时长)
|
||||||
# 静态缩放(整个视频时长)
|
filter_args.append(f"{video_output_str}scale={zoom_factor}*iw:{zoom_factor}*ih,crop=iw/{zoom_factor}:ih/{zoom_factor}:{left_x}:{top_y}[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)"
|
|
||||||
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}]"
|
video_output_str = f"[v_eff{effect_index}]"
|
||||||
elif effect.startswith("skip:"):
|
elif effect.startswith("skip:"):
|
||||||
param = effect.split(":", 2)[1]
|
param = effect.split(":", 2)[1]
|
||||||
@@ -358,6 +344,51 @@ class FfmpegTask(object):
|
|||||||
filter_args.append(f"[v_rev{effect_index}]trim=duration={tail_seconds}[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}]")
|
filter_args.append(f"[v_trim{effect_index}]reverse[v_eff{effect_index}]")
|
||||||
video_output_str = f"[v_eff{effect_index}]"
|
video_output_str = f"[v_eff{effect_index}]"
|
||||||
|
elif effect.startswith("show:"):
|
||||||
|
param = effect.split(":", 2)[1]
|
||||||
|
if param == '':
|
||||||
|
param = "0"
|
||||||
|
show_seconds = float(param)
|
||||||
|
if show_seconds > 0:
|
||||||
|
effect_index += 1
|
||||||
|
filter_args.append(f"{video_output_str}trim=end={show_seconds}[v_eff{effect_index}]")
|
||||||
|
video_output_str = f"[v_eff{effect_index}]"
|
||||||
|
elif effect.startswith("grid4:"):
|
||||||
|
param = effect.split(":", 2)[1]
|
||||||
|
if param == '':
|
||||||
|
param = "1"
|
||||||
|
delay_seconds = float(param)
|
||||||
|
effect_index += 1
|
||||||
|
|
||||||
|
# 获取分辨率,如果没有设置则使用默认值
|
||||||
|
if self.resolution:
|
||||||
|
width, height = self.resolution.split('x')
|
||||||
|
else:
|
||||||
|
width, height = "1920", "1080" # 默认分辨率
|
||||||
|
|
||||||
|
# 计算四宫格中每个象限的大小
|
||||||
|
grid_width = int(width) // 2
|
||||||
|
grid_height = int(height) // 2
|
||||||
|
|
||||||
|
# 分割视频流为4份
|
||||||
|
filter_args.append(f"{video_output_str}split=4[grid_v1_{effect_index}][grid_v2_{effect_index}][grid_v3_{effect_index}][grid_v4_{effect_index}]")
|
||||||
|
|
||||||
|
# 创建黑色背景
|
||||||
|
filter_args.append(f"color=black:size={width}x{height}:duration=1[bg_{effect_index}]")
|
||||||
|
|
||||||
|
# 缩放每个视频流到绝对尺寸
|
||||||
|
filter_args.append(f"[grid_v1_{effect_index}]scale={grid_width}:{grid_height}[v1_scaled_{effect_index}]")
|
||||||
|
filter_args.append(f"[grid_v2_{effect_index}]scale={grid_width}:{grid_height},tpad=start_duration={delay_seconds}[v2_scaled_{effect_index}]")
|
||||||
|
filter_args.append(f"[grid_v3_{effect_index}]scale={grid_width}:{grid_height},tpad=start_duration={delay_seconds*2}[v3_scaled_{effect_index}]")
|
||||||
|
filter_args.append(f"[grid_v4_{effect_index}]scale={grid_width}:{grid_height},tpad=start_duration={delay_seconds*3}[v4_scaled_{effect_index}]")
|
||||||
|
|
||||||
|
# 使用overlay将四个视频流叠加到四个位置
|
||||||
|
filter_args.append(f"[bg_{effect_index}][v1_scaled_{effect_index}]overlay=0:0:shortest=1[grid_step1_{effect_index}]")
|
||||||
|
filter_args.append(f"[grid_step1_{effect_index}][v2_scaled_{effect_index}]overlay=w/2:0:shortest=1[grid_step2_{effect_index}]")
|
||||||
|
filter_args.append(f"[grid_step2_{effect_index}][v3_scaled_{effect_index}]overlay=0:h/2:shortest=1[grid_step3_{effect_index}]")
|
||||||
|
filter_args.append(f"[grid_step3_{effect_index}][v4_scaled_{effect_index}]overlay=w/2:h/2:shortest=1[v_eff{effect_index}]")
|
||||||
|
|
||||||
|
video_output_str = f"[v_eff{effect_index}]"
|
||||||
...
|
...
|
||||||
if self.resolution:
|
if self.resolution:
|
||||||
filter_args.append(f"{video_output_str}scale={self.resolution.replace('x', ':')}[v]")
|
filter_args.append(f"{video_output_str}scale={self.resolution.replace('x', ':')}[v]")
|
||||||
|
Reference in New Issue
Block a user