| 1 | import sys |
| 2 | import tempfile |
| 3 | import unittest |
| 4 | from pathlib import Path |
| 5 | |
| 6 | # 测试文件直接运行时,也能从仓库根目录导入 app 包。 |
| 7 | sys.path.insert(0, str(Path(__file__).parent.parent.parent)) |
| 8 | |
| 9 | from app.services import subtitle |
| 10 | |
| 11 | |
| 12 | class TestSubtitleService(unittest.TestCase): |
| 13 | def test_correct_ignores_markdown_separator_lines(self): |
| 14 | """ |
| 15 | Whisper fallback 校正阶段也必须忽略 `---` 这类不可发声脚本行。 |
| 16 | |
| 17 | 如果这里继续保留 Markdown 分隔符,`correct()` 会认为脚本行数多于 |
| 18 | 字幕行数,并补出 `00:00:00,000 --> 00:00:00,000`,剪辑软件会把 |
| 19 | 生成的 SRT 判定为不可导入。 |
| 20 | """ |
| 21 | original_srt = ( |
| 22 | "1\n" |
| 23 | "00:00:00,100 --> 00:00:01,000\n" |
| 24 | "第一段\n\n" |
| 25 | "2\n" |
| 26 | "00:00:01,100 --> 00:00:02,000\n" |
| 27 | "第二段\n\n" |
| 28 | ) |
| 29 | |
| 30 | with tempfile.TemporaryDirectory() as tmp_dir: |
| 31 | subtitle_file = Path(tmp_dir) / "subtitle.srt" |
| 32 | subtitle_file.write_text(original_srt, encoding="utf-8") |
| 33 | |
| 34 | subtitle.correct( |
| 35 | subtitle_file=str(subtitle_file), |
| 36 | video_script="第一段\n---\n第二段", |
| 37 | ) |
| 38 | |
| 39 | corrected_srt = subtitle_file.read_text(encoding="utf-8") |
| 40 | |
| 41 | self.assertIn("第一段", corrected_srt) |
| 42 | self.assertIn("第二段", corrected_srt) |
| 43 | self.assertNotIn("---", corrected_srt) |
| 44 | self.assertNotIn("00:00:00,000 --> 00:00:00,000", corrected_srt) |
| 45 | |
| 46 | def test_file_to_subtitles_keeps_last_block_without_trailing_newline(self): |
| 47 | """ |
| 48 | The final subtitle must be parsed even when the SRT file does not end |
| 49 | with a trailing blank line. Many tools omit it, and previously the last |
| 50 | block was silently dropped because only a blank line flushed a block. |
| 51 | """ |
| 52 | srt_without_trailing_blank = ( |
| 53 | "1\n" |
| 54 | "00:00:00,000 --> 00:00:01,000\n" |
| 55 | "Hello\n\n" |
| 56 | "2\n" |
| 57 | "00:00:01,000 --> 00:00:02,000\n" |
| 58 | "World" |
| 59 | ) |
| 60 | |
| 61 | with tempfile.TemporaryDirectory() as tmp_dir: |
| 62 | subtitle_file = Path(tmp_dir) / "subtitle.srt" |
| 63 | subtitle_file.write_text(srt_without_trailing_blank, encoding="utf-8") |
| 64 | |
| 65 | items = subtitle.file_to_subtitles(str(subtitle_file)) |
| 66 | |
| 67 | self.assertEqual(len(items), 2) |
| 68 | self.assertEqual(items[0][2], "Hello") |
| 69 | self.assertEqual(items[1][2], "World") |
| 70 | |
| 71 | def test_file_to_subtitles_parses_blocks_with_trailing_newline(self): |
| 72 | """A normal SRT ending in a blank line still parses all blocks.""" |
| 73 | srt_with_trailing_blank = ( |
| 74 | "1\n" |
| 75 | "00:00:00,000 --> 00:00:01,000\n" |
| 76 | "Hello\n\n" |
| 77 | "2\n" |
| 78 | "00:00:01,000 --> 00:00:02,000\n" |
| 79 | "World\n\n" |
| 80 | ) |
| 81 | |
| 82 | with tempfile.TemporaryDirectory() as tmp_dir: |
| 83 | subtitle_file = Path(tmp_dir) / "subtitle.srt" |
| 84 | subtitle_file.write_text(srt_with_trailing_blank, encoding="utf-8") |
| 85 | |
| 86 | items = subtitle.file_to_subtitles(str(subtitle_file)) |
| 87 | |
| 88 | self.assertEqual([item[2] for item in items], ["Hello", "World"]) |
| 89 | |
| 90 | |
| 91 | if __name__ == "__main__": |
| 92 | unittest.main() |
| 93 |