computePlayableSections (js/editor-audio-cut.js) only builds regions between kept words: regionStart derives from prevKeptEnd, which is null until a kept word exists, so the span from 0 to the first word is never a candidate — and when struck words sit at the head, the region begins at the first struck word rather than at 0, so the lead-in survives regardless. The tail is only examined if (pendingStruck.length > 0), i.e. only when struck words follow the last kept word; plain silence after the final word is never cut, and the last section always runs to duration.
The result is that gap skipping ignores the two gaps most likely to be long: the setting-up before anyone speaks, and the dead air after they finish. This affects playback and media export alike, since both consume getPlayableSections().
Proposal. Treat both edges as ordinary regions — [0, firstKeptWord.start] and [lastKeptWord.end, duration] — subject to the same threshold and the same edge buffer, so a word's onset and tail are never clipped. Two details:
- The tail needs a known duration: when metadata has not loaded,
player.duration is Infinity, and the tail cut must be skipped rather than guessed.
- Untranscribed audio at the edges (intro music, applause, a cold open) has no words and therefore reads as a gap, so it would be removed. This is already true mid-transcript and gap skipping is opt-in and threshold-driven, so it is consistent rather than surprising — but it is likelier at the edges, and worth stating here rather than discovering later.
computePlayableSections(js/editor-audio-cut.js) only builds regions between kept words:regionStartderives fromprevKeptEnd, which is null until a kept word exists, so the span from 0 to the first word is never a candidate — and when struck words sit at the head, the region begins at the first struck word rather than at 0, so the lead-in survives regardless. The tail is only examinedif (pendingStruck.length > 0), i.e. only when struck words follow the last kept word; plain silence after the final word is never cut, and the last section always runs toduration.The result is that gap skipping ignores the two gaps most likely to be long: the setting-up before anyone speaks, and the dead air after they finish. This affects playback and media export alike, since both consume
getPlayableSections().Proposal. Treat both edges as ordinary regions —
[0, firstKeptWord.start]and[lastKeptWord.end, duration]— subject to the same threshold and the same edge buffer, so a word's onset and tail are never clipped. Two details:player.durationisInfinity, and the tail cut must be skipped rather than guessed.