From 92fce4e1264bb7f785e6da04272552a22bd5d8cc Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 20 Jun 2026 18:47:07 +0000 Subject: [PATCH] Fix speaker ID regex and page break/line spacing in transcript DOCX --- scraibe/email_sender.py | 42 ++++++++++++++++++++++++++++++----------- scraibe/tasks.py | 7 ++++--- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/scraibe/email_sender.py b/scraibe/email_sender.py index 81df5e3..a8c8d48 100644 --- a/scraibe/email_sender.py +++ b/scraibe/email_sender.py @@ -457,7 +457,7 @@ def create_transcript_docx(text: str, filename: str, summary_text: str = ""): """ 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 = [] current_page = [] line_count = 0 @@ -485,7 +485,7 @@ def create_transcript_docx(text: str, filename: str, summary_text: str = ""): if 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: if line_count == 30: 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 for page_idx, page_lines in enumerate(prepared_pages): - # Insert page break between pages - if page_idx > 0: + # Write each line with its number (1-30) + 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.paragraph_format.page_break_before = True + # Ensure it’s empty and doesn’t 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() for child in list(pPr): tag = child.tag.split("}")[-1] if "}" in child.tag else child.tag if tag in ("tabs", "spacing", "ind"): pPr.remove(child) - page_break = OxmlElement("w:pageBreak") - page_break.set("{http://schemas.openxmlformats.org/wordprocessingml/2006/main}val", "1") - pPr.append(page_break) - - # Write each line with its number (1-29) - for line_num, line_text in enumerate(page_lines, start=1): - _add_transcript_paragraph(doc, line_text, line_number=line_num) + spacing = OxmlElement("w:spacing") + _set_element_attr(spacing, "before", "0") + _set_element_attr(spacing, "after", "0") + _set_element_attr(spacing, "line", "240") + _set_element_attr(spacing, "lineRule", "auto") + pPr.append(spacing) # Step 5: If summary_text provided, append it with a hard page break if summary_text and summary_text.strip(): diff --git a/scraibe/tasks.py b/scraibe/tasks.py index 1030d8c..f0826c5 100644 --- a/scraibe/tasks.py +++ b/scraibe/tasks.py @@ -322,8 +322,8 @@ def _apply_speaker_map(transcript_text: str, segments: list, speaker_map: dict) # Replace in transcript lines def replace_in_line(line: str) -> str: - # Pattern: timestamp bracket + speaker label + colon - # More flexible: allow any non-empty label before the colon + # Match: [MM:SS] or [HH:MM:SS] then speaker label then colon + # Use a lazy match for the label up to the first colon def repl(m): prefix = m.group(1) # e.g. "[00:12] " 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) return f"{prefix}{new_label}: " return re.sub( - r"(\[\d+:\d+(?::\d+)?\]\s*)([^\]]+?):\s*", + r"(\[\d+:\d+(?::\d+)?\]\s*)(.+?):\s*", repl, line, + count=1, ) updated_transcript = "\n".join(