You've already forked FrameTour-RenderWorker
Compare commits
5 Commits
4b080771f6
...
bf912037d1
Author | SHA1 | Date | |
---|---|---|---|
bf912037d1 | |||
1119a7b030 | |||
5282e58a10 | |||
f7141e5d4e | |||
f23bcfdd25 |
@@ -24,6 +24,13 @@ def parse_ffmpeg_task(task_info, template_info):
|
||||
span.set_attribute("task_params", task_params_str)
|
||||
task_params: dict = json.loads(task_params_str)
|
||||
task_params_orig = json.loads(task_params_str)
|
||||
|
||||
# 统计only_if占位符的使用次数
|
||||
only_if_usage_count = {}
|
||||
for part in template_info.get("video_parts", []):
|
||||
only_if = part.get('only_if', '')
|
||||
if only_if:
|
||||
only_if_usage_count[only_if] = only_if_usage_count.get(only_if, 0) + 1
|
||||
with tracer.start_as_current_span("parse_ffmpeg_task.download_all") as sub_span:
|
||||
with ThreadPoolExecutor(max_workers=8) as executor:
|
||||
param_list: list[dict]
|
||||
@@ -41,8 +48,9 @@ def parse_ffmpeg_task(task_info, template_info):
|
||||
continue
|
||||
only_if = part.get('only_if', '')
|
||||
if only_if:
|
||||
if not check_placeholder_exist(only_if, task_params_orig):
|
||||
logger.info("because only_if exist, placeholder: %s not exist, skip part: %s", only_if, part)
|
||||
required_count = only_if_usage_count.get(only_if, 1)
|
||||
if not check_placeholder_exist_with_count(only_if, task_params_orig, required_count):
|
||||
logger.info("because only_if exist, placeholder: %s insufficient (need %d), skip part: %s", only_if, required_count, part)
|
||||
continue
|
||||
sub_ffmpeg_task = FfmpegTask(source)
|
||||
sub_ffmpeg_task.resolution = template_info.get("video_size", "")
|
||||
@@ -50,10 +58,11 @@ def parse_ffmpeg_task(task_info, template_info):
|
||||
sub_ffmpeg_task.ext_data = ext_data or {}
|
||||
sub_ffmpeg_task.frame_rate = template_info.get("frame_rate", 25)
|
||||
sub_ffmpeg_task.center_cut = part.get("crop_mode", None)
|
||||
sub_ffmpeg_task.zoom_cut = part.get("zoom_cut", None)
|
||||
for effect in part.get('effects', []):
|
||||
sub_ffmpeg_task.add_effect(effect)
|
||||
for lut in part.get('filters', []):
|
||||
sub_ffmpeg_task.add_lut(os.path.join(template_info.get("local_path"), lut))
|
||||
for lut in part.get('luts', []):
|
||||
sub_ffmpeg_task.add_lut(os.path.join(template_info.get("local_path"), lut).replace("\\", "/"))
|
||||
for audio in part.get('audios', []):
|
||||
sub_ffmpeg_task.add_audios(os.path.join(template_info.get("local_path"), audio))
|
||||
for overlay in part.get('overlays', []):
|
||||
@@ -64,6 +73,7 @@ def parse_ffmpeg_task(task_info, template_info):
|
||||
task.resolution = template_info.get("video_size", "")
|
||||
overall = template_info.get("overall_template")
|
||||
task.center_cut = template_info.get("crop_mode", None)
|
||||
task.zoom_cut = template_info.get("zoom_cut", None)
|
||||
task.frame_rate = template_info.get("frame_rate", 25)
|
||||
# if overall.get('source', ''):
|
||||
# source, ext_data = parse_video(overall.get('source'), task_params, template_info)
|
||||
@@ -71,8 +81,8 @@ def parse_ffmpeg_task(task_info, template_info):
|
||||
# task.ext_data = ext_data or {}
|
||||
for effect in overall.get('effects', []):
|
||||
task.add_effect(effect)
|
||||
for lut in overall.get('filters', []):
|
||||
task.add_lut(os.path.join(template_info.get("local_path"), lut))
|
||||
for lut in overall.get('luts', []):
|
||||
task.add_lut(os.path.join(template_info.get("local_path"), lut).replace("\\", "/"))
|
||||
for audio in overall.get('audios', []):
|
||||
task.add_audios(os.path.join(template_info.get("local_path"), audio))
|
||||
for overlay in overall.get('overlays', []):
|
||||
@@ -112,6 +122,16 @@ def check_placeholder_exist(placeholder_id, task_params):
|
||||
return False
|
||||
|
||||
|
||||
def check_placeholder_exist_with_count(placeholder_id, task_params, required_count=1):
|
||||
"""检查占位符是否存在足够数量的片段"""
|
||||
if placeholder_id in task_params:
|
||||
new_sources = task_params.get(placeholder_id, [])
|
||||
if type(new_sources) is list:
|
||||
return len(new_sources) >= required_count
|
||||
return required_count <= 1
|
||||
return False
|
||||
|
||||
|
||||
def start_ffmpeg_task(ffmpeg_task):
|
||||
tracer = get_tracer(__name__)
|
||||
with tracer.start_as_current_span("start_ffmpeg_task") as span:
|
||||
|
@@ -187,6 +187,32 @@ class FfmpegTask(object):
|
||||
filter_args.append(f"{video_output_str}crop=x={_x}:y=0:w=ih*ih/iw:h=ih[v_cut{effect_index}]")
|
||||
video_output_str = f"[v_cut{effect_index}]"
|
||||
effect_index += 1
|
||||
if self.zoom_cut == 1 and self.resolution:
|
||||
_input = None
|
||||
for input_file in self.input_file:
|
||||
if type(input_file) is str:
|
||||
_input = input_file
|
||||
break
|
||||
elif isinstance(input_file, FfmpegTask):
|
||||
_input = input_file.get_output_file()
|
||||
break
|
||||
if _input:
|
||||
from util.ffmpeg import probe_video_info
|
||||
_iw, _ih, _ = probe_video_info(_input)
|
||||
_w, _h = self.resolution.split('x', 1)
|
||||
pos_json_str = self.ext_data.get('posJson', '{}')
|
||||
pos_json = json.loads(pos_json_str)
|
||||
_v_w = pos_json.get('imgWidth', 1)
|
||||
_v_h = pos_json.get('imgHeight', 1)
|
||||
_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)
|
||||
_x = min(max(0, (_f_x + _f_x2) / 2 - int(_w) / 2), _iw - int(_w))
|
||||
_y = min(max(0, (_f_y + _f_y2) / 2 - int(_h) / 2), _ih - int(_h))
|
||||
filter_args.append(f"{video_output_str}crop=x={_x}:y={_y}:w={_w}:h={_h}[vz_cut{effect_index}]")
|
||||
video_output_str = f"[vz_cut{effect_index}]"
|
||||
effect_index += 1
|
||||
for effect in self.effects:
|
||||
if effect.startswith("cameraShot:"):
|
||||
param = effect.split(":", 2)[1]
|
||||
@@ -234,11 +260,11 @@ class FfmpegTask(object):
|
||||
elif effect.startswith("zoom:"):
|
||||
...
|
||||
...
|
||||
for lut in self.luts:
|
||||
filter_args.append(f"{video_output_str}lut3d=file={lut}{video_output_str}")
|
||||
if self.resolution:
|
||||
filter_args.append(f"{video_output_str}scale={self.resolution.replace('x', ':')}[v]")
|
||||
video_output_str = "[v]"
|
||||
for lut in self.luts:
|
||||
filter_args.append(f"{video_output_str}lut3d=file={lut}{video_output_str}")
|
||||
for overlay in self.overlays:
|
||||
input_index = input_args.count("-i")
|
||||
input_args.append("-i")
|
||||
|
@@ -1,7 +1,8 @@
|
||||
requests~=2.32.3
|
||||
psutil~=6.1.0
|
||||
python-dotenv~=1.0.1
|
||||
opentelemetry-api~=1.30.0
|
||||
opentelemetry-sdk~=1.30.0
|
||||
opentelemetry-exporter-otlp~=1.30.0
|
||||
opentelemetry-api~=1.35.0
|
||||
opentelemetry-sdk~=1.35.0
|
||||
opentelemetry-exporter-otlp~=1.35.0
|
||||
opentelemetry-instrumentation-threading~=0.56b0
|
||||
flask~=3.1.0
|
@@ -6,7 +6,9 @@ from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExport
|
||||
from opentelemetry.sdk.resources import DEPLOYMENT_ENVIRONMENT, HOST_NAME, Resource, SERVICE_NAME, SERVICE_VERSION
|
||||
from opentelemetry.sdk.trace import TracerProvider
|
||||
from opentelemetry.sdk.trace.export import BatchSpanProcessor, SimpleSpanProcessor
|
||||
from opentelemetry.instrumentation.threading import ThreadingInstrumentor
|
||||
|
||||
ThreadingInstrumentor().instrument()
|
||||
|
||||
def get_tracer(name):
|
||||
return trace.get_tracer(name)
|
||||
|
@@ -35,7 +35,7 @@ def upload_to_oss(url, file_path):
|
||||
new_url = new_url.split("?", 1)[0]
|
||||
r_span.set_attribute("rclone.target_dir", new_url)
|
||||
if new_url != url:
|
||||
result = os.system(f"rclone copyto --no-check-dest --ignore-existing --multi-thread-chunk-size 32M --multi-thread-streams 8 {file_path} {new_url}")
|
||||
result = os.system(f"rclone copyto --no-check-dest --ignore-existing --multi-thread-chunk-size 8M --multi-thread-streams 8 {file_path} {new_url}")
|
||||
r_span.set_attribute("rclone.result", result)
|
||||
if result == 0:
|
||||
span.set_status(Status(StatusCode.OK))
|
||||
|
Reference in New Issue
Block a user