Skip to content

Mobile: WebKit OOM crash on Load + stuck Preparing audio after reload #234

Description

@thcp

Summary

Two related bugs triggered when pressing Load in the mobile library view, reported by @goermezer in #216.

Bug 1 - WebKit tab crash (root cause)

openTrack() calls createAudioEngine(), which fetches all stems in parallel via res.arrayBuffer() then decodes each with decodeAudioData(). This holds both the compressed MP3 and the decoded PCM in memory simultaneously for all stems at once.

Rough memory for a 5-minute, 4-stem track:

  • Decoded PCM: 5 min x 4 stems x 44100 Hz x 2ch x 4 bytes = ~420 MB
  • Compressed MP3 buffers in flight: ~32 MB

Mobile browser tabs get killed at 256-512 MB on most devices. The desktop player (player.js) already has a MAX_ENGINE_DECODED_BYTES = 1.2e9 guard with a streaming fallback - the mobile engine has no equivalent.

Relevant files:

  • static/js/audioEngine.js lines 43-63 (parallel arrayBuffer() + decodeAudioData())
  • static/mobile/app.js lines 262-278 (openTrack - no memory guard before createAudioEngine)
  • static/js/player.js lines 879-891 (desktop guard, for reference)

Bug 2 - Stuck on "Preparing audio" after reload (symptom)

After WebKit kills and reloads the tab, loadLibrary() auto-selects the first track:

// static/mobile/app.js line 893
if (!state.current && state.tracks.length) state.current = state.tracks[0];

This sets a raw track card into state.current (with loading: false, error: null) but never calls openTrack(), so engineReady stays false. The preparing condition on line 428 evaluates to true indefinitely:

const preparing = !!state.current && !state.current.loading && !state.current.error && !ready;

Pressing Load manually calls openTrack() and clears the state. That is why the workaround works.

Reproduction

  1. Open StemDeck mobile on a phone browser (iOS Safari or Android Chrome)
  2. Open the Library tab, press Load on any track
  3. On longer tracks or older devices: blank white page briefly, page reloads ("This website was reloaded because of a problem" on iOS)
  4. After reload: player shows "Preparing audio..." and never progresses

Proposed fix

  • Bug 1: Add a decoded-size estimate before calling createAudioEngine() in openTrack(). If it exceeds a mobile-appropriate threshold (e.g. 150 MB), fall back to sequential decoding or <audio> element streaming.
  • Bug 2: Remove the auto-select on line 893, or only set state.current when also triggering openTrack().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

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