"""SRT Parser Module 解析 SRT 字幕文件格式,将字幕转换为结构化的 Segment 对象。 SRT 格式示例: 1 00:00:00,000 --> 00:00:05,000 第一句字幕内容 2 00:00:05,000 --> 00:00:10,000 第二句字幕内容 """ from __future__ import annotations import re from dataclasses import dataclass from pathlib import Path from typing import List @dataclass class Segment: """字幕分段数据结构 Attributes: id: 字幕序号 start_time: 开始时间(秒) end_time: 结束时间(秒) text: 字幕文本 """ id: int start_time: float end_time: float text: str # SRT 块正则表达式 # 格式: 序号\n时间码\n文本(可能多行)\n\n SRT_BLOCK_PATTERN = re.compile( r'(\d+)\s*\n' r'(\d{2}:\d{2}:\d{2},\d{3})\s*-->\s*(\d{2}:\d{2}:\d{2},\d{3})\s*\n' r'(.*?)(?=\n\n|\Z)', re.DOTALL ) def parse_srt_time(time_str: str) -> float: """解析 SRT 时间格式 (HH:MM:SS,mmm) 为秒数 Args: time_str: SRT 时间字符串,如 "00:05:30,500" Returns: 秒数,如 330.5 Example: >>> parse_srt_time("00:05:30,500") 330.5 >>> parse_srt_time("01:02:03,004") 3723.004 """ # 分割时间和毫秒 main_part, millis = time_str.rsplit(',', 1) hours, minutes, seconds = main_part.split(':') total_seconds = ( int(hours) * 3600 + int(minutes) * 60 + int(seconds) + int(millis) / 1000 ) return total_seconds def parse_srt(content: str) -> List[Segment]: """解析 SRT 格式字符串 将 SRT 格式的字幕内容解析为 Segment 对象列表。 Args: content: SRT 格式的字符串内容 Returns: Segment 对象列表 Raises: ValueError: 内容为空或格式无效 Example: >>> content = "1\\n00:00:00,000 --> 00:00:05,000\\n第一句\\n\\n" >>> segments = parse_srt(content) >>> len(segments) 1 >>> segments[0].text '第一句' """ # 检查空内容 if not content or not content.strip(): raise ValueError("Empty SRT content") segments = [] # 查找所有 SRT 块 matches = SRT_BLOCK_PATTERN.findall(content) if not matches: raise ValueError("Invalid SRT format: no valid blocks found") for match in matches: try: segment_id = int(match[0]) start_time = parse_srt_time(match[1]) end_time = parse_srt_time(match[2]) # 清理文本:移除前后空白,合并多行为单行 text = ' '.join(match[3].strip().split()) segment = Segment( id=segment_id, start_time=start_time, end_time=end_time, text=text ) segments.append(segment) except (ValueError, IndexError) as e: # 跳过解析失败的块 continue if not segments: raise ValueError("Invalid SRT format: no valid segments parsed") return segments def parse_srt_file(file_path: Path) -> List[Segment]: """从文件解析 SRT 格式 读取文件内容并解析为 Segment 对象列表。 Args: file_path: SRT 文件路径 Returns: Segment 对象列表 Raises: FileNotFoundError: 文件不存在 ValueError: 内容格式无效 Example: >>> from pathlib import Path >>> segments = parse_srt_file(Path("subtitles.srt")) >>> len(segments) 10 """ if not file_path.exists(): raise FileNotFoundError(f"SRT file not found: {file_path}") content = file_path.read_text(encoding='utf-8') return parse_srt(content)