增加了对hls直播转换mp4的playlist结尾检查,确保使用的直播为结束直播

This commit is contained in:
shuohigh@gmail.com 2025-06-13 16:08:36 +08:00
parent 8d57e593f8
commit 2d2be4e9a7
3 changed files with 18 additions and 7 deletions

View File

@ -378,7 +378,8 @@ class VideoUtils:
raise RuntimeError("输出是空文件") raise RuntimeError("输出是空文件")
else: else:
if not quiet: if not quiet:
logger.warning(line) if "SKIP" not in line:
logger.warning(line)
return ffmpeg_cmd return ffmpeg_cmd
@ -754,7 +755,6 @@ class VideoUtils:
os.makedirs(os.path.dirname(output_path), exist_ok=True) os.makedirs(os.path.dirname(output_path), exist_ok=True)
try: try:
local_m3u8_path, temp_dir = await VideoUtils.convert_m3u8_to_local_source(media_stream_url) local_m3u8_path, temp_dir = await VideoUtils.convert_m3u8_to_local_source(media_stream_url)
# 使用ffmpeg合并TS片段 # 使用ffmpeg合并TS片段
ffmpeg_cmd = VideoUtils.async_ffmpeg_init() ffmpeg_cmd = VideoUtils.async_ffmpeg_init()
@ -1194,8 +1194,9 @@ class VideoUtils:
reconnect_at_eof="1", reconnect_at_eof="1",
reconnect_streamed="1", reconnect_streamed="1",
reconnect_delay_max="5") reconnect_delay_max="5")
output_playlist = f"{playlist_output_dir}/playlist.m3u8"
ffmpeg_cmd.output( ffmpeg_cmd.output(
f"{playlist_output_dir}/playlist.m3u8", output_playlist,
f="hls", f="hls",
hls_init_time=first_segment_duration, hls_init_time=first_segment_duration,
hls_time=segment_duration, hls_time=segment_duration,
@ -1210,3 +1211,4 @@ class VideoUtils:
) )
await ffmpeg_cmd.execute() await ffmpeg_cmd.execute()
logger.info(f'停止录制') logger.info(f'停止录制')
return output_playlist

View File

@ -44,8 +44,9 @@ with ffmpeg_worker_image.imports():
raise NotImplementedError(f"暂不支持使用{media_stream.protocol.value}协议") raise NotImplementedError(f"暂不支持使用{media_stream.protocol.value}协议")
output_path = f"{output_path_prefix}/{config.modal_environment}/convert_stream/{func_id}/output.mp4" output_path = f"{output_path_prefix}/{config.modal_environment}/convert_stream/{func_id}/output.mp4"
local_output, metadata = await VideoUtils.ffmpeg_convert_stream_media(media_stream_url=stream_url, local_output, metadata = await VideoUtils.ffmpeg_convert_stream_media_multithread(
output_path=output_path) media_stream_url=stream_url,
output_path=output_path)
s3_outputs = local_copy_to_s3([local_output]) s3_outputs = local_copy_to_s3([local_output])
return FFMPEGResult(urn=s3_outputs[0], metadata=metadata, return FFMPEGResult(urn=s3_outputs[0], metadata=metadata,

View File

@ -1,5 +1,7 @@
import os import os
import shutil import shutil
import modal
from ..ffmpeg_app import ffmpeg_worker_image, app, config, s3_mount from ..ffmpeg_app import ffmpeg_worker_image, app, config, s3_mount
@ -11,7 +13,7 @@ with ffmpeg_worker_image.imports():
import sentry_sdk import sentry_sdk
import backoff import backoff
import httpx import httpx
import modal import m3u8
from loguru import logger from loguru import logger
from typing import Optional, Tuple from typing import Optional, Tuple
from modal import current_function_call_id from modal import current_function_call_id
@ -163,13 +165,19 @@ with ffmpeg_worker_image.imports():
playlist_observer.schedule(playlist_handler, path=volume_output_dir, recursive=False) playlist_observer.schedule(playlist_handler, path=volume_output_dir, recursive=False)
playlist_observer.start() playlist_observer.start()
try: try:
await VideoUtils.ffmpeg_stream_record_as_hls(stream_url=stream_url, playlist = await VideoUtils.ffmpeg_stream_record_as_hls(stream_url=stream_url,
first_segment_duration=first_segment_duration, first_segment_duration=first_segment_duration,
segment_duration=segment_duration, segment_duration=segment_duration,
stream_content_timeout=recording_timeout, stream_content_timeout=recording_timeout,
stream_monitor_timeout=monitor_timeout, stream_monitor_timeout=monitor_timeout,
segments_output_dir=volume_output_dir, segments_output_dir=volume_output_dir,
playlist_output_dir=volume_output_dir) playlist_output_dir=volume_output_dir)
# 确保playlist有 #EXT-X-ENDLIST 结尾
pl = m3u8.load(playlist)
pl.is_endlist = True
pl.dump(playlist)
logger.info(f"[End] playlist = {playlist}")
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
playlist_observer.stop() playlist_observer.stop()