DEV Community

SleepTrace
SleepTrace

Posted on

How to process 8 hours of audio on an iPhone without draining the battery

How to process 8 hours of audio on an iPhone without draining the battery

An iPhone on a nightstand recording all night sounds impossible from a battery standpoint. A naive AVAudioEngine setup recording 48 kHz stereo for eight hours would torch the battery and the CPU. Yet SleepTrace does exactly this routinely and consistently comes back above 20% battery. The trick is not a clever algorithm — it is a ruthless pipeline architecture.

Here is the field-tested stack that actually runs overnight on device.

Rule 1: never record at full fidelity all night

You do not need 48 kHz to detect a snore. The discriminative information for breathing, snoring, and grinding lives comfortably below 16 kHz. The pipeline:

  1. Input at hardware native (AVAudioSession shared model, no re-render), but immediately downmix to mono.
  2. Resample to 12.8 kHz in a fixed-size ring buffer. This preserves enough to detect snoring (roughly 200–1800 Hz with harmonics) and cuts the per-sample cost dramatically.
  3. Discard the raw PCM immediately after the FFT/window is emitted. Keep only the feature vector in memory.

Rule 2: batch, do not stream continuously

Continuous audio capture with a real-time callback keeps the CPU warm all night. Instead:

  • Capture in 2-second windows, 50% overlap.
  • Run each window through a lightweight feature extractor (spectral flux + zero-crossing + band energy).
  • Sleep the process between windows using a background task assertion.

This yields a bursty CPU profile: ~250ms of work every 2 seconds, then sleep. Battery impact is negligible.

Rule 3: do the ML classification in bursts

The model itself is small (sub-10MB CoreML), but running it every window still costs. The actual architecture:

  • Feature vectors are written to a ring buffer.
  • Every fifth window, the ring is evaluated as a sequence with a temporal smoothing pass.
  • Results are written to a compact log: timestamps + classification + confidence.

This is where the snore/apnea detection detail lives — the acoustic feature engineering is straightforward; the trick is not running it continuously.

Rule 4: guard the background task correctly

// request a background task that expires gracefully
let task = UIApplication.shared.beginBackgroundTask(withName: "audio-processing") {
    // flush buffer, end cleanly
    processor.flush()
}
Enter fullscreen mode Exit fullscreen mode

Without this, iOS suspends the process within ~30 seconds of the screen locking. With it, the pipeline runs undisturbed for the full night.

Rule 5: verify, then forget the raw audio

Only the classification log (a few hundred kilobytes) survives the night. The raw ring buffers are overwritten the next morning. On-device only, always.

The whole pipeline fits under 50MB of RAM and uses roughly 10–14% of a single night's battery on modern iPhones. The constraint that solved it was not faster hardware — it was treating raw audio as ephemeral by design.

Top comments (0)