Skip to content

Struck-word removal ignores the Entire/Edited media choice #605

Closed

Description

@maboa

Exported text drops struck words regardless of which media it is shipped with. When Entire media is chosen the original AV file is exported untouched — it still speaks every struck word — while the transcript and captions beside it have those words deleted. The text then describes audio that is not what plays.

The rule this should follow: the text must match the media that ships with it.

  • Entire media — the original AV file, untouched. Nothing is cut. Struck words are still audible, so they are ordinary words for export: they belong in the transcript and the captions.
  • Edited media — gap removal and word removal are applied. The media is cut, the transcript and captions are re-timed to suit, and struck words are genuinely absent.

Measured

Striking a word with the toolbar control, then taking each export:

media shipped struck words in the text verdict
Export Media → Entire media original, untouched removed wrong
Export Media → Edited media cut and re-timed removed correct
Interactive Transcript modal original (linked by name) kept correct
download-html original context kept correct
download-vtt / download-srt / download-vtt-words original context kept correct
saved project (.hyperaudio, working copy) — kept, struck: true correct

Cause

media-export.js already gets the mode right when computing the timeline:

const sections = edited ? editedSections(duration) : [{ start: 0, end: duration }];

With Entire media, sections spans the whole timeline, so mapTime is an identity and no re-timing happens — correct. But buildRetimedTranscriptHtml deleted struck spans before it consulted sections at all, and that deletion was not conditioned on edited. So the removal ignored the choice the user made.

Fix

dropStruck is threaded through the four builders — buildRetimedTranscriptHtml, genRetimedCaptions, buildInteractiveExportHtml, buildCaptionChunks — and every call site passes edited. That covers the interactive transcript, the sidecar captions, the burned-in captions and the flattened project container. Retiming needs no flag: Entire media already passes whole-timeline sections.

The exported page's copy button follows from this and needed no mode of its own. It used to filter struck words itself; it no longer does, because the document already reflects the choice — an Edited-media export contains no struck words to copy, and an Entire-media export shows them. Copying what is shown is right in both cases, and a filter there could only disagree with the page.

Do not touch the save

Striking is reversible working state: it travels in the save with struck: true and becomes final only in an export. Verified correct and unchanged.

serializeTranscriptHtml is shared across export paths — putting any of this inside it would look tidy and would put the removal one refactor from the save path. buildRetimedTranscriptHtml is the safe shape: clone the transcript, act on the clone, leave the live DOM alone.

Correction to an earlier revision of this issue

An earlier version listed the standalone caption downloads (download-vtt, download-srt, download-vtt-words) as a second fix site, on the grounds that they excluded struck words. That was wrong: the reading came from a stale href, populated before the strike. Once regenerated they contain struck words like everything else, and were already correct. There is one fix site, not two.

Also worth doing

Say what Entire media means where it is chosen — see #608 — and consider confirming before an export that ships an uncut file (#610).

Activity

  1. changed the title [-]Exported transcripts leak struck words to anyone who selects the text by hand[/-] [+]Interactive transcript exports contain struck words; the VTT beside them does not[/+] on Aug 30, 2026
  2. changed the title [-]Interactive transcript exports contain struck words; the VTT beside them does not[/-] [+]Struck-word removal ignores the Entire/Edited media choice[/+] on Aug 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions