Skip to content

~1ms busy-poll loop after the playhead passes the last timed word (and on null data-m mid-transcript) #263

Description

@maboa

Summary

(As of v2.6.2.) The next-tick interval derives from the next word's data-m (hyperaudio-lite.js:928-933):

let interval = 0;
if (this.wordArr[index]) {
  interval = this.wordArr[index].n.getAttribute('data-m') - this.currentTime * 1000;
}
this.timer = setTimeout(() => this.checkPlayHead(), interval + 1);

Once currentTime passes the final word, index === wordArr.length, wordArr[index] is undefined, so interval stays 0 and the loop re-arms every 1 ms (browser-clamped to ~4 ms after nesting depth 5 → ~250 wakeups/s, each an async getTime() promise plus an O(log n) binary search).

Failure scenario

Transcript ends before the audio (trailing music, untranscribed Q&A): ten minutes of outro ≈ 150k timer wakeups — sustained CPU/battery drain, silent. Also, getAttribute('data-m') returning null (attribute removed by an edit) coerces the subtraction to a negative interval → the same tight loop mid-transcript.

Fix

When wordArr[index] is missing, or the computed interval is ≤ 0 / NaN, fall back to a sane poll interval (e.g. 250 ms).

Found reviewing the copy vendored in hyperaudio-lite-editor / GliderMac (2026-07-11).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions