media: rather than preserving the UTF-8 BOM, just discard it
- ID
cefb712- date
2026-07-17 21:26:15+00:00- author
Alex Chan <alex@alexwlchan.net>- parent
108ddb5- message
media: rather than preserving the UTF-8 BOM, just discard it- changed files
4 files, 40 additions, 10 deletions
Changed files
CHANGELOG.md (6148) → CHANGELOG.md (6291)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1e39f3..701f066 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# CHANGELOG
+## v47 - 2026-07-17
+
+Fix a bug in the byte order mark handling in v47.
+Rather than preserving the UTF-8 byte order mark, discard it entirely.
+
## v46 - 2026-07-16
Change the `browser` fixture to be session-scoped, so the browser only needs to be started once per test suite.
src/chives/__init__.py (391) → src/chives/__init__.py (391)
diff --git a/src/chives/__init__.py b/src/chives/__init__.py
index eec5a4d..fe49ddd 100644
--- a/src/chives/__init__.py
+++ b/src/chives/__init__.py
@@ -11,4 +11,4 @@ I share across multiple sites.
"""
-__version__ = "46"
+__version__ = "47"
src/chives/media.py (12113) → src/chives/media.py (11912)
diff --git a/src/chives/media.py b/src/chives/media.py
index 015ae55..8a58113 100644
--- a/src/chives/media.py
+++ b/src/chives/media.py
@@ -427,7 +427,7 @@ def convert_srt_to_vtt(srt_path: Path) -> Path:
f"convert_srt_to_vtt can only take .srt files, got {srt_path!r}"
)
- with open(srt_path) as srt_file:
+ with open(srt_path, encoding="utf-8-sig") as srt_file:
srt_lines = srt_file.readlines()
if len(srt_lines) == 0:
@@ -436,13 +436,7 @@ def convert_srt_to_vtt(srt_path: Path) -> Path:
vtt_path = srt_path.with_suffix(".vtt")
assert vtt_path != srt_path, vtt_path
- with open(vtt_path, "w") as vtt_file:
- # Check for a byte order mark in the first line; if so, preserve
- # it in the converted VTT file.
- if srt_lines[0].startswith("\ufeff"):
- vtt_file.write("\ufeff")
- srt_lines[0] = srt_lines[0][1:]
-
+ with open(vtt_path, "w", encoding="utf-8") as vtt_file:
# Write the required WEBVTT header and blank line
vtt_file.write("WEBVTT\n\n")
tests/test_media.py (17704) → tests/test_media.py (18739)
diff --git a/tests/test_media.py b/tests/test_media.py
index 5109adb..88b6e9c 100644
--- a/tests/test_media.py
+++ b/tests/test_media.py
@@ -492,7 +492,7 @@ class TestConvertSrtToVtt:
assert not srt_path.exists()
assert vtt_path.read_text() == (
- "\ufeffWEBVTT\n"
+ "WEBVTT\n"
"\n"
"00:00:01.001 --> 00:00:10.010\n"
"Somebody said the first thing\n"
@@ -501,6 +501,37 @@ class TestConvertSrtToVtt:
"Somebody else said the second thing\n"
)
+ def test_converting_srt_with_bom_on_later_number(self, tmp_path: Path) -> None:
+ """
+ If an SRT file starts with a byte order mark but the caption
+ number doesn't start at 1, the BOM is removed.
+ """
+ srt_path = tmp_path / "captions_with_bom.en.srt"
+ srt_path.write_text(
+ "\ufeff2\n"
+ "00:00:02,002 --> 00:00:20,020\n"
+ "Who said the first thing?\n"
+ "\n"
+ "3\n"
+ "00:03:00,003 --> 00:30:00,030\n"
+ "A ghost said the first thing\n"
+ )
+
+ vtt_path = convert_srt_to_vtt(srt_path)
+ assert vtt_path == (tmp_path / "captions_with_bom.en.vtt")
+ assert vtt_path.exists()
+ assert not srt_path.exists()
+
+ assert vtt_path.read_text() == (
+ "WEBVTT\n"
+ "\n"
+ "00:00:02.002 --> 00:00:20.020\n"
+ "Who said the first thing?\n"
+ "\n"
+ "00:03:00.003 --> 00:30:00.030\n"
+ "A ghost said the first thing\n"
+ )
+
def test_convert_empty_file_is_error(self, tmp_path: Path) -> None:
"""
Converting an empty file is an error.