All projects

Slyric

An alarm app that generates and plays a sleep-inducing track

ContractNeuroMomentSep 2024 – Dec 20244 mos

Context

An alarm app built around the sleep window a user sets. I built and shipped the whole thing alone — a Flutter app for iOS and Android, plus the backend.

The core of it was the synthesis: deriving the sleep cycles and stage sequence across that window, then generating inaudible-band entrainment tones and mixing them into an audible track.

A track runs seven hours by default, and the existing Python synthesis took 50 minutes to produce one. Cutting the wait before playback was the problem to solve.

How I solved it

  1. Profiling put the time in ffmpeg subprocess calls and S3 transfers rather than in the synthesis maths
    • the constraint was I/O, not CPU
  2. Moved the generation pipeline to Go (Fiber) to match that, and made generation an async job rather than a blocking request
  3. Bounded ffmpeg concurrency with a process pool
    • unbounded, seven hours of audio contend for resources and get slower
  4. Sized batches against available memory (10–100 segments, under 200MB each) so long tracks never hit memory pressure
  5. Cached segments by frequency and duration so repeated stretches are not recomputed
How one track gets made
  1. Job queueReturns at once, generates behind
  2. Segment synthesisSkipped on a cache hit
  3. Batching10–100, sized to free memory
  4. ffmpeg encodePool-bounded — the stage that was the bottleneck
  5. S3 uploadReturns a signed URL

Result

  • One track (seven hours of audio by default) went from 50 minutes to about 4.5, an 11× cut
Time to generate one track — seven hours of audio
Python50 min
After Goabout 4.5 min

Tech

FlutterPythonFastAPIGoFiberffmpegRedisAWS S3