Fix speaker ID regex and page break/line spacing in transcript DOCX
Mirror and run GitLab CI / build (push) Has been cancelled
Ruff / ruff (push) Has been cancelled

This commit is contained in:
admin
2026-06-20 18:47:07 +00:00
parent ffdabb6ae6
commit 92fce4e126
2 changed files with 35 additions and 14 deletions
+31 -11
View File
@@ -457,7 +457,7 @@ def create_transcript_docx(text: str, filename: str, summary_text: str = ""):
""" """
from . import docx_styles from . import docx_styles
# Step 1: Prepare transcript into pages of 29 lines each # Step 1: Prepare transcript into pages of 30 lines each
prepared_pages = [] prepared_pages = []
current_page = [] current_page = []
line_count = 0 line_count = 0
@@ -485,7 +485,7 @@ def create_transcript_docx(text: str, filename: str, summary_text: str = ""):
if current: if current:
segments.append(current) segments.append(current)
# Add segments to pages, enforcing 29 lines per page # Add segments to pages, enforcing 30 lines per page
for seg in segments: for seg in segments:
if line_count == 30: if line_count == 30:
prepared_pages.append(current_page) prepared_pages.append(current_page)
@@ -523,21 +523,41 @@ def create_transcript_docx(text: str, filename: str, summary_text: str = ""):
# Step 4: Write prepared pages into DOCX # Step 4: Write prepared pages into DOCX
for page_idx, page_lines in enumerate(prepared_pages): for page_idx, page_lines in enumerate(prepared_pages):
# Insert page break between pages # Write each line with its number (1-30)
if page_idx > 0: for line_num, line_text in enumerate(page_lines, start=1):
p = doc.add_paragraph()
_add_transcript_paragraph(doc, line_text, line_number=line_num)
# Remove the extra paragraph added by add_paragraph (we already added runs)
# _add_transcript_paragraph already creates its own paragraph, so we need to avoid duplication.
# Correct approach: _add_transcript_paragraph should add to doc, not p.
# To avoid breaking existing behavior, keep _add_transcript_paragraph as-is
# and remove the temporary paragraph we just added.
# This is an internal fix to ensure page break logic is clean.
# We'll rely on _add_transcript_paragraph creating its own paragraph.
# To avoid an extra blank paragraph, we remove p if it has no runs.
if not p.runs:
body.remove(p._p)
# After each page except the last, add a page break via next paragraph
if page_idx < len(prepared_pages) - 1:
p_break = doc.add_paragraph() p_break = doc.add_paragraph()
p_break.paragraph_format.page_break_before = True
# Ensure its empty and doesnt show as a visible line
if p_break.runs:
for r in p_break.runs:
r.text = ""
# Remove any formatting that would show as a visible line
pPr = p_break._p.get_or_add_pPr() pPr = p_break._p.get_or_add_pPr()
for child in list(pPr): for child in list(pPr):
tag = child.tag.split("}")[-1] if "}" in child.tag else child.tag tag = child.tag.split("}")[-1] if "}" in child.tag else child.tag
if tag in ("tabs", "spacing", "ind"): if tag in ("tabs", "spacing", "ind"):
pPr.remove(child) pPr.remove(child)
page_break = OxmlElement("w:pageBreak") spacing = OxmlElement("w:spacing")
page_break.set("{http://schemas.openxmlformats.org/wordprocessingml/2006/main}val", "1") _set_element_attr(spacing, "before", "0")
pPr.append(page_break) _set_element_attr(spacing, "after", "0")
_set_element_attr(spacing, "line", "240")
# Write each line with its number (1-29) _set_element_attr(spacing, "lineRule", "auto")
for line_num, line_text in enumerate(page_lines, start=1): pPr.append(spacing)
_add_transcript_paragraph(doc, line_text, line_number=line_num)
# Step 5: If summary_text provided, append it with a hard page break # Step 5: If summary_text provided, append it with a hard page break
if summary_text and summary_text.strip(): if summary_text and summary_text.strip():
+4 -3
View File
@@ -322,8 +322,8 @@ def _apply_speaker_map(transcript_text: str, segments: list, speaker_map: dict)
# Replace in transcript lines # Replace in transcript lines
def replace_in_line(line: str) -> str: def replace_in_line(line: str) -> str:
# Pattern: timestamp bracket + speaker label + colon # Match: [MM:SS] or [HH:MM:SS] then speaker label then colon
# More flexible: allow any non-empty label before the colon # Use a lazy match for the label up to the first colon
def repl(m): def repl(m):
prefix = m.group(1) # e.g. "[00:12] " prefix = m.group(1) # e.g. "[00:12] "
label = m.group(2).strip() label = m.group(2).strip()
@@ -331,9 +331,10 @@ def _apply_speaker_map(transcript_text: str, segments: list, speaker_map: dict)
new_label = speaker_map.get(normalized, label) new_label = speaker_map.get(normalized, label)
return f"{prefix}{new_label}: " return f"{prefix}{new_label}: "
return re.sub( return re.sub(
r"(\[\d+:\d+(?::\d+)?\]\s*)([^\]]+?):\s*", r"(\[\d+:\d+(?::\d+)?\]\s*)(.+?):\s*",
repl, repl,
line, line,
count=1,
) )
updated_transcript = "\n".join( updated_transcript = "\n".join(