From c4f368f63ae73f2fac22b0ddc4478b3efddb078f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=82=96=E5=AE=87=E8=BF=AA?= Date: Thu, 12 Jun 2025 18:33:58 +0800 Subject: [PATCH] fix : MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix : - ffmpeg_slice_stream_media_multithread结束时间点的精度问题 --------- Merge request URL: https://g-ldyi2063.coding.net/p/dev/d/modalDeploy/git/merge/4793?initial=true Co-authored-by: shuohigh@gmail.com --- src/BowongModalFunctions/utils/VideoUtils.py | 31 +++++++++++++++----- src/cluster/ffmpeg_apps/__init__.py | 0 src/cluster/ffmpeg_apps/concat_medias.py | 24 +++++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 src/cluster/ffmpeg_apps/__init__.py create mode 100644 src/cluster/ffmpeg_apps/concat_medias.py diff --git a/src/BowongModalFunctions/utils/VideoUtils.py b/src/BowongModalFunctions/utils/VideoUtils.py index 06e5b76..59607a4 100644 --- a/src/BowongModalFunctions/utils/VideoUtils.py +++ b/src/BowongModalFunctions/utils/VideoUtils.py @@ -597,20 +597,35 @@ class VideoUtils: output_path = output_path + ".mp4" os.makedirs(os.path.dirname(output_path), exist_ok=True) + diff_tolerance = 0.001 + for index, marker in enumerate(media_markers): if marker.start.total_seconds() > stream_total_duration or marker.start.total_seconds() < 0: raise ValueError( f"第{index}个切割点起始点{marker.start.total_seconds()}s超出视频时长[0-{stream_total_duration}s]范围") if marker.end.total_seconds() > stream_total_duration or marker.end.total_seconds() < 0: - raise ValueError( - f"第{index}个切割点结束点{marker.end.total_seconds()}s超出视频时长[0-{stream_total_duration}s]范围") + if marker.end.total_seconds() > 0 and math.isclose(marker.end.total_seconds(), stream_total_duration, + rel_tol=diff_tolerance): + marker.end = TimeDelta(seconds=stream_total_duration) + logger.warning( + f"第{index}个切割点结束点{marker.end.total_seconds()}s接近视频时长[0-{stream_total_duration}s]范围") + filter_complex.extend( + [ + f"[v:0]trim=start={marker.start.total_seconds()},setpts=PTS-STARTPTS[cut{index}]", + f"[a:0]atrim=start={marker.start.total_seconds()},asetpts=PTS-STARTPTS[acut{index}]", + ] + ) + else: + raise ValueError( + f"第{index}个切割点结束点{marker.end.total_seconds()}s超出视频时长[0-{stream_total_duration}s]范围") + else: + filter_complex.extend( + [ + f"[v:0]trim=start={marker.start.total_seconds()}:end={marker.end.total_seconds()},setpts=PTS-STARTPTS[cut{index}]", + f"[a:0]atrim=start={marker.start.total_seconds()}:end={marker.end.total_seconds()},asetpts=PTS-STARTPTS[acut{index}]", + ] + ) - filter_complex.extend( - [ - f"[v:0]trim=start={marker.start.total_seconds()}:end={marker.end.total_seconds()},setpts=PTS-STARTPTS[cut{index}]", - f"[a:0]atrim=start={marker.start.total_seconds()}:end={marker.end.total_seconds()},asetpts=PTS-STARTPTS[acut{index}]", - ] - ) ffmpeg_cmd.option('filter_complex', ';'.join(filter_complex)) for i, marker in enumerate(media_markers): output_filepath = FileUtils.file_path_extend(output_path, str(i)) diff --git a/src/cluster/ffmpeg_apps/__init__.py b/src/cluster/ffmpeg_apps/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/cluster/ffmpeg_apps/concat_medias.py b/src/cluster/ffmpeg_apps/concat_medias.py new file mode 100644 index 0000000..2bc6394 --- /dev/null +++ b/src/cluster/ffmpeg_apps/concat_medias.py @@ -0,0 +1,24 @@ +async def ffmpeg_concat_medias(medias: MediaSources, + sentry_trace: Optional[SentryTransactionInfo] = None, + webhook: Optional[WebhookNotify] = None) -> Tuple[ + FFMPEGResult, Optional[SentryTransactionInfo]]: + fn_id = current_function_call_id() + + @SentryUtils.sentry_tracker(name="视频合并任务", op="ffmpeg.concat", fn_id=fn_id, + sentry_trace_id=sentry_trace.x_trace_id if sentry_trace else None, + sentry_baggage=sentry_trace.x_baggage if sentry_trace else None) + @SentryUtils.webhook_handler(webhook=webhook, func_id=fn_id) + async def ffmpeg_process(media_sources: MediaSources, output_filepath: str) -> FFMPEGResult: + input_videos = [f"{s3_mount}/{media_source.cache_filepath}" for media_source in media_sources.inputs] + local_output_path, metadata = await VideoUtils.ffmpeg_concat_medias(media_paths=input_videos, + output_path=output_filepath) + s3_outputs = local_copy_to_s3([local_output_path]) + return FFMPEGResult(urn=s3_outputs[0], metadata=metadata, + content_length=FileUtils.get_file_size(local_output_path), ) + + output_path = f"{output_path_prefix}/{config.modal_environment}/concat/outputs/{fn_id}/output.mp4" + result = await ffmpeg_process(media_sources=medias, output_filepath=output_path) + if not sentry_trace: + sentry_trace = SentryTransactionInfo(x_trace_id=sentry_sdk.get_traceparent(), + x_baggage=sentry_sdk.get_baggage()) + return result, sentry_trace \ No newline at end of file