mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 13:40:27 +02:00
171 lines
5.7 KiB
Python
171 lines
5.7 KiB
Python
from __future__ import annotations
|
|
|
|
import zipfile
|
|
|
|
from abogen.epub3.exporter import build_epub3_package
|
|
from abogen.text_extractor import ExtractedChapter, ExtractionResult
|
|
|
|
|
|
def _make_sample_extraction() -> ExtractionResult:
|
|
return ExtractionResult(
|
|
chapters=[
|
|
ExtractedChapter(title="Chapter 1", text="Hello world."),
|
|
ExtractedChapter(title="Chapter 2", text="Another passage."),
|
|
],
|
|
metadata={"title": "Sample Book", "artist": "Test Author", "language": "en"},
|
|
)
|
|
|
|
|
|
def test_build_epub3_package_creates_expected_structure(tmp_path) -> None:
|
|
extraction = _make_sample_extraction()
|
|
chunks = [
|
|
{
|
|
"id": "chap0000_p0000",
|
|
"chapter_index": 0,
|
|
"chunk_index": 0,
|
|
"text": "Hello world.",
|
|
"speaker_id": "narrator",
|
|
},
|
|
{
|
|
"id": "chap0001_p0000",
|
|
"chapter_index": 1,
|
|
"chunk_index": 0,
|
|
"text": "Another passage.",
|
|
"speaker_id": "narrator",
|
|
},
|
|
]
|
|
chunk_markers = [
|
|
{"id": "chap0000_p0000", "chapter_index": 0, "chunk_index": 0, "start": 0.0, "end": 1.2},
|
|
{"id": "chap0001_p0000", "chapter_index": 1, "chunk_index": 0, "start": 1.2, "end": 2.4},
|
|
]
|
|
chapter_markers = [
|
|
{"index": 1, "title": "Chapter 1", "start": 0.0, "end": 1.2},
|
|
{"index": 2, "title": "Chapter 2", "start": 1.2, "end": 2.4},
|
|
]
|
|
metadata_tags = {"title": "Sample Book", "artist": "Test Author", "language": "en"}
|
|
|
|
audio_path = tmp_path / "sample.mp3"
|
|
audio_path.write_bytes(b"ID3 test audio")
|
|
|
|
output_path = tmp_path / "output.epub"
|
|
result_path = build_epub3_package(
|
|
output_path=output_path,
|
|
book_id="job-123",
|
|
extraction=extraction,
|
|
metadata_tags=metadata_tags,
|
|
chapter_markers=chapter_markers,
|
|
chunk_markers=chunk_markers,
|
|
chunks=chunks,
|
|
audio_path=audio_path,
|
|
speaker_mode="single",
|
|
)
|
|
|
|
assert result_path == output_path
|
|
assert output_path.exists()
|
|
|
|
with zipfile.ZipFile(output_path) as archive:
|
|
names = set(archive.namelist())
|
|
assert "mimetype" in names
|
|
assert archive.read("mimetype") == b"application/epub+zip"
|
|
assert "META-INF/container.xml" in names
|
|
assert "OEBPS/content.opf" in names
|
|
assert "OEBPS/nav.xhtml" in names
|
|
assert "OEBPS/audio/sample.mp3" in names
|
|
chapter_doc = archive.read("OEBPS/text/chapter_0001.xhtml").decode("utf-8")
|
|
assert "Hello world." in chapter_doc
|
|
smil_doc = archive.read("OEBPS/smil/chapter_0001.smil").decode("utf-8")
|
|
assert "clipBegin=\"00:00:00.000\"" in smil_doc
|
|
opf_doc = archive.read("OEBPS/content.opf").decode("utf-8")
|
|
assert "media-overlay" in opf_doc
|
|
assert "media:duration" in opf_doc
|
|
assert "abogen:speakerMode" in opf_doc
|
|
|
|
|
|
def test_build_epub3_package_handles_missing_markers(tmp_path) -> None:
|
|
extraction = _make_sample_extraction()
|
|
metadata_tags = {"title": "Sample Book", "artist": "Test Author", "language": "en"}
|
|
audio_path = tmp_path / "audio.mp3"
|
|
audio_path.write_bytes(b"ID3 audio")
|
|
output_path = tmp_path / "output.epub"
|
|
|
|
result_path = build_epub3_package(
|
|
output_path=output_path,
|
|
book_id="job-456",
|
|
extraction=extraction,
|
|
metadata_tags=metadata_tags,
|
|
chapter_markers=[],
|
|
chunk_markers=[],
|
|
chunks=[],
|
|
audio_path=audio_path,
|
|
speaker_mode="single",
|
|
)
|
|
|
|
with zipfile.ZipFile(result_path) as archive:
|
|
nav_doc = archive.read("OEBPS/nav.xhtml").decode("utf-8")
|
|
assert "Chapter 1" in nav_doc
|
|
chapter_doc = archive.read("OEBPS/text/chapter_0001.xhtml").decode("utf-8")
|
|
assert "Hello world." in chapter_doc
|
|
|
|
|
|
def test_epub3_preserves_original_whitespace(tmp_path) -> None:
|
|
extraction = ExtractionResult(
|
|
chapters=[
|
|
ExtractedChapter(
|
|
title="Intro",
|
|
text="Line one with double spaces.\nSecond line\n\nThird paragraph.",
|
|
)
|
|
],
|
|
metadata={"title": "Sample", "artist": "Author", "language": "en"},
|
|
)
|
|
|
|
chunks = [
|
|
{
|
|
"id": "chap0000_p0000",
|
|
"chapter_index": 0,
|
|
"chunk_index": 0,
|
|
"text": "Line one with double spaces.",
|
|
"speaker_id": "narrator",
|
|
},
|
|
{
|
|
"id": "chap0000_p0001",
|
|
"chapter_index": 0,
|
|
"chunk_index": 1,
|
|
"text": "Second line",
|
|
"speaker_id": "narrator",
|
|
},
|
|
{
|
|
"id": "chap0000_p0002",
|
|
"chapter_index": 0,
|
|
"chunk_index": 2,
|
|
"text": "Third paragraph.",
|
|
"speaker_id": "narrator",
|
|
},
|
|
]
|
|
|
|
chunk_markers = [
|
|
{"id": chunk["id"], "chapter_index": 0, "chunk_index": chunk["chunk_index"], "start": None, "end": None}
|
|
for chunk in chunks
|
|
]
|
|
|
|
metadata_tags = {"title": "Sample", "artist": "Author", "language": "en"}
|
|
audio_path = tmp_path / "audio.mp3"
|
|
audio_path.write_bytes(b"ID3 audio")
|
|
output_path = tmp_path / "output.epub"
|
|
|
|
build_epub3_package(
|
|
output_path=output_path,
|
|
book_id="job-whitespace",
|
|
extraction=extraction,
|
|
metadata_tags=metadata_tags,
|
|
chapter_markers=[],
|
|
chunk_markers=chunk_markers,
|
|
chunks=chunks,
|
|
audio_path=audio_path,
|
|
speaker_mode="single",
|
|
)
|
|
|
|
with zipfile.ZipFile(output_path) as archive:
|
|
chapter_doc = archive.read("OEBPS/text/chapter_0001.xhtml").decode("utf-8")
|
|
assert "Line one with double spaces." in chapter_doc
|
|
normalized = chapter_doc.replace(" ", "")
|
|
assert "Second line\n\nThird paragraph." in normalized |