fix : ffmpeg_slice_media 根据seek_head处理切割点时间为相对时间, 添加了实际获取片段和请求开始时间的diff差值

This commit is contained in:
shuohigh@gmail.com 2025-06-18 12:35:53 +08:00
parent 2551702443
commit 0f66ac03c2
1 changed files with 20 additions and 14 deletions

View File

@ -454,21 +454,17 @@ class VideoUtils:
seek_tail = media_markers[-1].end.total_seconds()
duration = seek_tail - seek_head
logger.info(f"Only using {seek_head}s --> {seek_tail}s = {duration}s")
local_m3u8_path, temp_dir = await VideoUtils.convert_m3u8_to_local_source(media_path, head=seek_head,
local_m3u8_path, temp_dir, diff = await VideoUtils.convert_m3u8_to_local_source(media_path, head=seek_head,
tail=seek_tail)
logger.info(f"local_playlist: {local_m3u8_path}")
for segment in media_markers:
segment.start = segment.start - timedelta(seconds=seek_head)
segment.end = segment.end - timedelta(seconds=seek_head)
segment.start = segment.start - timedelta(seconds=seek_head) + diff
segment.end = segment.end - timedelta(seconds=seek_head) + diff
logger.info(f"Only using {seek_head}s --> {seek_tail}s = {duration}s")
ffmpeg_cmd.input(local_m3u8_path,
# ss=seek_head,
t=duration,
protocol_whitelist="file,http,https,tcp,tls")
# reconnect="1", # 自动重连
# reconnect_streamed="1",
# reconnect_delay_max="5")
filter_complex: List[str] = []
temp_outputs: List[str] = []
@ -478,8 +474,8 @@ class VideoUtils:
metadata = VideoUtils.ffprobe_media_metadata(media_path)
for index, marker in enumerate(media_markers):
start = marker.start.total_seconds() - seek_head
end = marker.end.total_seconds() - seek_head
start = marker.start.total_seconds()
end = marker.end.total_seconds()
# 处理指定的输出分辨率
if options.width and options.height:
@ -562,7 +558,7 @@ class VideoUtils:
@staticmethod
async def convert_m3u8_to_local_source(media_stream_url: str,
head: Optional[float] = None,
tail: Optional[float] = None) -> tuple[str, str]:
tail: Optional[float] = None) -> tuple[str, str, TimeDelta]:
"""
转换m3u8为本地来源
"""
@ -574,18 +570,28 @@ class VideoUtils:
playlist = m3u8.load(media_stream_url)
# duration = (tail - head) if head else None
origin_time: datetime = playlist.segments[0].current_program_date_time
logger.info(f"Start Timestamp: {origin_time}")
# 2. 解析TS片段URL
ts_urls: SegmentList[Segment] = SegmentList()
duration = 0
min_head = origin_time + timedelta(seconds=head)
max_head = origin_time + timedelta(seconds=tail)
logger.info(f"min: {min_head}, max: {max_head}")
for segment in playlist.segments:
if not head:
head = 0
if not tail:
tail = 86400 # 使用24H时长替代♾
if origin_time + timedelta(
seconds=head) <= segment.current_program_date_time <= origin_time + timedelta(seconds=tail):
if min_head - timedelta(seconds=segment.duration) <= segment.current_program_date_time <= max_head:
logger.info(f"duration: {segment.duration}, head: {segment.current_program_date_time}")
duration += segment.duration
ts_urls.append(segment)
if len(ts_urls) > 0:
delta = min_head - ts_urls[0].current_program_date_time
diff = TimeDelta.from_timedelta(delta)
else:
diff = TimeDelta(seconds=0)
logger.info(f"diff = {diff.total_seconds()}")
# 3. 并行下载TS片段
tasks = []
playlist.segments = ts_urls
@ -601,7 +607,7 @@ class VideoUtils:
local_m3u8_path = os.path.join(temp_dir, "local.m3u8")
playlist.dump(local_m3u8_path)
return local_m3u8_path, temp_dir
return local_m3u8_path, temp_dir, diff
except Exception as e:
logger.exception(e)
raise Exception(f"下载TS转换M3U8失败 {e}")
@ -617,7 +623,7 @@ class VideoUtils:
@staticmethod
async def ffmpeg_convert_stream_media(media_stream_url: str, options: FFMPEGSliceOptions,
output_path: Optional[str] = None) -> tuple[
str, VideoMetadata] | None:
str, VideoMetadata] | None:
if not output_path:
output_path = FileUtils.file_path_extend(media_stream_url, "convert")
if not output_path.endswith(".mp4"):