diff --git a/src/BowongModalFunctions/utils/VideoUtils.py b/src/BowongModalFunctions/utils/VideoUtils.py index b07148e..df63ca8 100644 --- a/src/BowongModalFunctions/utils/VideoUtils.py +++ b/src/BowongModalFunctions/utils/VideoUtils.py @@ -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"):