Skip to content

Build a Typescript/Node worker processing HLS stream files into PCM / PSD #2

@adrmac

Description

@adrmac

Prerequisite: read #6 description
Pairs with #1

Project summary

Build a small TypeScript/Node worker that concatenates HLS segments ( .m3u8 / .ts ) and decodes to PCM. Then compute Power Spectral Density (PSD) / Sound Pressure Level (SPL) and write compact JSON/Parquet features to a shared folder (e.g. Dropbox). Optionally, write spectrogram PNG tiles.

This shares the exact HLS->PCM core process as #1 with a different output.

Immediate use case

Shared steps

  • Resolve [start,end] to a segment list from .m3u8
  • Spawn ffmpeg (child process) to decode HLS to PCM (mono 48 kHz; single pass).

Divergent steps

  • Compute Welch PSD (Hann, ~50% ovrerlap, one-sided density) (reference ambient-sound-analysis repo)
  • Aggregate to bands/SPL per second; write features and a small .features.json describing parameters/bands/units
  • (Optional) render a spectrogram PNG for the clip window

Inputs

  • Single job: { feedSlug, startIso, endIso }
  • Batch: CSV manifest with columns { feedSlug, startIso, endIso }

Outputs

features/<feedSlug>/<YYYY>/<MM>/<DD>/<basename>.psd.parquet   # or .jsonl
features/.../<basename>.features.json
# optional:
spectrograms/<feedSlug>/<...>/<basename>.png

Sidecar (.features.json): Welch params (nfft, hop/overlap, window, scaling), band defs, units, samplerate, channels, calibration tag (if any).

CLI (example)

npm run psd -- \
  --feedSlug orcasound_lab \
  --start 2025-09-12T10:00:00Z \
  --end   2025-09-12T10:05:00Z

Dependencies

  • ffmpeg (system binary in Docker or ffmpeg-static in dev).
  • Node 20, TypeScript.

Frequency bands

  • Pre-filter the saved PSD frames to specific bands to save space. An initial read suggests that raw PSD frames storage would be ~16GB/day/node, while banded PSDs would be ~10 MB/day/node.
  • Standard vessel monitoring bands are 1/3 octaves around 63/125 Hz
  • Store daily/hourly aggregates (Long Term Spectral Average / Spectral Probability Density) instead of raw frames, which work well for detecting site-specific drift and seasonality.
  • Keep a rolling window of raw PSD frames for recent data, for calibrating bands if needed.
  • If older audio files need band calibration, recompute PSDs from the original HLS

Error handling & ops

Acceptance criteria

  • Within a 5-min window, Node band SPL matches a Python reference within ±1–2 dB per band (with matched window/overlap/scaling).
  • Artifacts are written with stable names (hash-based) and re-runnable without duplication.
  • Optional spectrogram renders with expected axes/level range.

Later scope

  • HTTP endpoints (local)
  • Azure container or other cloud service

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    triage

    Status

    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions