mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 13:40:27 +02:00
feat: Add original text preservation in chunking and export processes
This commit is contained in:
@@ -148,6 +148,7 @@ def chunk_text(
|
|||||||
voice_formula=voice_formula,
|
voice_formula=voice_formula,
|
||||||
).as_dict()
|
).as_dict()
|
||||||
payload["normalized_text"] = _normalize_chunk_text(paragraph)
|
payload["normalized_text"] = _normalize_chunk_text(paragraph)
|
||||||
|
payload["original_text"] = paragraph
|
||||||
chunks.append(payload)
|
chunks.append(payload)
|
||||||
_attach_display_text(text, chunks)
|
_attach_display_text(text, chunks)
|
||||||
return chunks
|
return chunks
|
||||||
@@ -177,6 +178,7 @@ def chunk_text(
|
|||||||
).as_dict()
|
).as_dict()
|
||||||
payload["normalized_text"] = _normalize_chunk_text(raw_sentence)
|
payload["normalized_text"] = _normalize_chunk_text(raw_sentence)
|
||||||
payload["display_text"] = raw_sentence
|
payload["display_text"] = raw_sentence
|
||||||
|
payload["original_text"] = raw_sentence
|
||||||
chunks.append(payload)
|
chunks.append(payload)
|
||||||
sentence_index += 1
|
sentence_index += 1
|
||||||
|
|
||||||
@@ -221,9 +223,11 @@ def _attach_display_text(source: str, chunks: List[Dict[str, object]]) -> None:
|
|||||||
match = _search_source_span(source, candidate, 0)
|
match = _search_source_span(source, candidate, 0)
|
||||||
if match is None:
|
if match is None:
|
||||||
chunk.setdefault("display_text", candidate)
|
chunk.setdefault("display_text", candidate)
|
||||||
|
chunk.setdefault("original_text", chunk.get("display_text") or candidate)
|
||||||
continue
|
continue
|
||||||
start, end = match
|
start, end = match
|
||||||
chunk["display_text"] = source[start:end]
|
chunk["display_text"] = source[start:end]
|
||||||
|
chunk["original_text"] = source[start:end]
|
||||||
cursor = end
|
cursor = end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ class EPUB3PackageBuilder:
|
|||||||
voice = marker.get("voice")
|
voice = marker.get("voice")
|
||||||
else:
|
else:
|
||||||
display_text = chunk_entry.get("display_text")
|
display_text = chunk_entry.get("display_text")
|
||||||
text = str(display_text or chunk_entry.get("text") or "")
|
text = str(chunk_entry.get("text") or "")
|
||||||
speaker_id = str(chunk_entry.get("speaker_id") or marker.get("speaker_id") or "narrator")
|
speaker_id = str(chunk_entry.get("speaker_id") or marker.get("speaker_id") or "narrator")
|
||||||
voice = chunk_entry.get("voice") or chunk_entry.get("resolved_voice") or marker.get("voice")
|
voice = chunk_entry.get("voice") or chunk_entry.get("resolved_voice") or marker.get("voice")
|
||||||
level = chunk_entry.get("level") or None
|
level = chunk_entry.get("level") or None
|
||||||
@@ -261,11 +261,15 @@ class EPUB3PackageBuilder:
|
|||||||
group_id = _derive_group_id(raw_group_key, level)
|
group_id = _derive_group_id(raw_group_key, level)
|
||||||
normalized_group_id = _normalize_chunk_id(group_id) if group_id else None
|
normalized_group_id = _normalize_chunk_id(group_id) if group_id else None
|
||||||
|
|
||||||
|
original_text = None
|
||||||
|
if chunk_entry is not None:
|
||||||
|
original_text = chunk_entry.get("original_text") or chunk_entry.get("display_text")
|
||||||
|
|
||||||
overlays.append(
|
overlays.append(
|
||||||
ChunkOverlay(
|
ChunkOverlay(
|
||||||
id=normalized_id,
|
id=normalized_id,
|
||||||
text=text or self.extraction.chapters[chapter_index].text,
|
text=text or self.extraction.chapters[chapter_index].text,
|
||||||
original_text=None,
|
original_text=str(original_text) if original_text is not None else None,
|
||||||
start=_safe_float(marker.get("start")),
|
start=_safe_float(marker.get("start")),
|
||||||
end=_safe_float(marker.get("end")),
|
end=_safe_float(marker.get("end")),
|
||||||
speaker_id=speaker_id,
|
speaker_id=speaker_id,
|
||||||
@@ -747,6 +751,10 @@ def _restore_original_chunk_text(chapter_text: str, overlays: List[ChunkOverlay]
|
|||||||
|
|
||||||
cursor = 0
|
cursor = 0
|
||||||
for chunk in overlays:
|
for chunk in overlays:
|
||||||
|
if chunk.original_text is not None:
|
||||||
|
prepared = _prepare_display_text(chunk.original_text)
|
||||||
|
chunk.text = prepared
|
||||||
|
continue
|
||||||
candidate = chunk.text or ""
|
candidate = chunk.text or ""
|
||||||
if not candidate:
|
if not candidate:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -1122,6 +1122,10 @@ class ConversionService:
|
|||||||
if normalized_value is not None:
|
if normalized_value is not None:
|
||||||
chunk["normalized_text"] = str(normalized_value)
|
chunk["normalized_text"] = str(normalized_value)
|
||||||
|
|
||||||
|
for text_key in ("display_text", "original_text"):
|
||||||
|
if text_key in entry and entry[text_key] is not None:
|
||||||
|
chunk[text_key] = str(entry[text_key])
|
||||||
|
|
||||||
speaker_value = entry.get("speaker_id", entry.get("speaker"))
|
speaker_value = entry.get("speaker_id", entry.get("speaker"))
|
||||||
chunk["speaker_id"] = str(speaker_value) if speaker_value else "narrator"
|
chunk["speaker_id"] = str(speaker_value) if speaker_value else "narrator"
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ def test_chunk_text_merges_title_abbreviations() -> None:
|
|||||||
assert "Doctor" in normalized_value
|
assert "Doctor" in normalized_value
|
||||||
display_value = str(chunk.get("display_text") or "")
|
display_value = str(chunk.get("display_text") or "")
|
||||||
assert display_value.startswith("Dr.")
|
assert display_value.startswith("Dr.")
|
||||||
|
original_value = str(chunk.get("original_text") or "")
|
||||||
|
assert original_value.startswith("Dr.")
|
||||||
|
|
||||||
|
|
||||||
def test_chunk_text_display_preserves_whitespace() -> None:
|
def test_chunk_text_display_preserves_whitespace() -> None:
|
||||||
@@ -77,3 +79,5 @@ def test_chunk_text_display_preserves_whitespace() -> None:
|
|||||||
assert first_display.endswith("\n\n")
|
assert first_display.endswith("\n\n")
|
||||||
second_display = str(chunks[1].get("display_text") or "")
|
second_display = str(chunks[1].get("display_text") or "")
|
||||||
assert second_display == "Third paragraph."
|
assert second_display == "Third paragraph."
|
||||||
|
first_original = str(chunks[0].get("original_text") or "")
|
||||||
|
assert first_original.endswith("\n\n")
|
||||||
|
|||||||
Reference in New Issue
Block a user