modalDeploy/src/cluster/ffmpeg_apps/slice_media.py

86 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import modal
from ..ffmpeg_app import ffmpeg_worker_image, app, config, s3_mount, local_copy_to_s3, output_path_prefix
with ffmpeg_worker_image.imports():
from BowongModalFunctions.models.ffmpeg_worker_model import FFMpegSliceSegment
from BowongModalFunctions.models.media_model import MediaSources, MediaProtocol, MediaSource
from BowongModalFunctions.models.web_model import SentryTransactionInfo, WebhookNotify, FFMPEGResult
from BowongModalFunctions.utils.PathUtils import FileUtils
from BowongModalFunctions.utils.SentryUtils import SentryUtils
from BowongModalFunctions.utils.VideoUtils import VideoUtils, FFMPEGSliceOptions
import sentry_sdk
from loguru import logger
from typing import Optional, Tuple, List
from modal import current_function_call_id
@app.function(
timeout=900,
cloud="aws",
cpu=(0.5, 64),
max_containers=config.ffmpeg_slice_worker_concurrency,
volumes={
s3_mount: modal.CloudBucketMount(
bucket_name=config.S3_bucket_name,
secret=modal.Secret.from_name("aws-s3-secret",
environment_name=config.modal_environment),
),
},
)
@modal.concurrent(max_inputs=1)
async def ffmpeg_slice_media(media: MediaSource,
markers: List[FFMpegSliceSegment],
options: FFMPEGSliceOptions,
sentry_trace: Optional[SentryTransactionInfo] = None,
webhook: Optional[WebhookNotify] = None) -> Tuple[
List[FFMPEGResult], Optional[SentryTransactionInfo]]:
fn_id = current_function_call_id()
@SentryUtils.sentry_tracker(name="视频文件/直播切割任务", op="ffmpeg.slice.media", 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_slice_process(media_source: MediaSource, media_markers: List[FFMpegSliceSegment],
fn_id: str, options: FFMPEGSliceOptions = None, is_streams: bool = False,
) -> List[FFMPEGResult]:
if not is_streams:
cache_filepath = f"{s3_mount}/{media_source.cache_filepath}"
logger.info(f"{media_source.urn}切割")
for i, marker in enumerate(media_markers):
logger.info(f"[{i}] {marker.start.toFormatStr()} --> {marker.end.toFormatStr()}")
else:
cache_filepath = media_source.path
segments = await VideoUtils.ffmpeg_slice_media(media_path=cache_filepath,
media_markers=media_markers,
options=options,
is_streams=is_streams,
output_path=f"{output_path_prefix}/{config.modal_environment}/slice/outputs/{fn_id}/output.mp4")
return [FFMPEGResult(urn=local_copy_to_s3([segment[0]])[0], metadata=segment[1],
content_length=FileUtils.get_file_size(segment[0])) for segment in segments]
match media.protocol:
case MediaProtocol.hls:
outputs = await ffmpeg_slice_process(media_source=media,
media_markers=markers,
options=options,
is_streams=True,
fn_id=fn_id)
case MediaProtocol.vod:
outputs = await ffmpeg_slice_process(media_source=media,
media_markers=markers,
options=options,
is_streams=False,
fn_id=fn_id)
case MediaProtocol.s3:
outputs = await ffmpeg_slice_process(media_source=media,
media_markers=markers,
options=options,
is_streams=False,
fn_id=fn_id)
case _: # webhook不会报错需要确认
raise NotImplementedError("暂不支持的协议")
return [result for result in outputs], sentry_trace