WaveformData class final Visualizer and analysis

Mono min, max and RMS amplitude envelope of the audio currently loaded.

Emitted on PlayerStream.waveform for the loaded track. The track is mixed down to mono and binned into a fixed ~2000-entry envelope. A local file is decoded in the background: partial envelopes (decoding true) come first, then the final one. An HTTP file that plays from its start is decoded the same way from mpv's cache as it downloads. Other network sources grow with playback (unfilled bins in filled), and a live stream is a sliding window of up to 131072 bins.

Bin i spans the time slice [start + i / bins * duration, start + (i + 1) / bins * duration). min and max hold the lowest and highest sample value seen in each bin, range [-1.0, +1.0], and rms the root mean square of the bin. On loud, heavily limited masters the peaks sit near full scale for most of the track, so drawing rms as the body of the waveform, with the peaks as a lighter outline, keeps the sections readable.

For a normal (known-length) track start is zero and duration is the whole track, so bins map onto [0, duration]. For a live stream (live == true) there is no total length: the envelope is a sliding window kept in lockstep with the demuxer's seekable cache, so start is the absolute media time of bin 0 (the oldest still-cached moment) and duration is the span currently held (it grows while you listen and only drops its oldest bins once the demuxer evicts that audio from its back-buffer). The newest bin is "now". Map bins with start and duration in absolute media time and you can scrub anywhere the cache still covers.

Example: paint a bar per bin:

player.stream.waveform.listen((wave) {
  if (wave == null) return;
  for (var i = 0; i < wave.bins; i++) {
    final yMin = wave.min[i] * canvasHeight / 2;
    final yMax = wave.max[i] * canvasHeight / 2;
    // draw bar i from yMin to yMax …
  }
});

Constructors

WaveformData({required Duration duration, required Float32List min, required Float32List max, required Uint8List filled, Float32List? rms, Duration start = Duration.zero, bool live = false, bool decoding = false, int? coverageBins, int? totalBins})
Creates a waveform. Used internally by the waveform pipeline.
const

Properties

bins → int
Number of bins. Convenience accessor: equal to min.length.
no setter
coverageBins → int?
Number of bins decoded ("sealed") so far, across all worker regions, or null when not decoding. Together with totalBins this is the decode progress; see decodeFraction.
final
decodeFraction → double?
Decode progress in [0, 1] while decoding, or null when it is not known (not decoding, or the engine did not report bin counts). Drives a determinate progress indicator; a null value means show an indeterminate one.
no setter
decoding → bool
True while the analyzer is still decoding the file: this envelope is a partial snapshot that grows on every poll until the final one arrives (a last emission with decoding == false). Set while a file is decoded apart from playback: a local file, or a remote one read from mpv's cache as it downloads or opened a second time. When a pass from the cache hands over to a second open, the coverage starts again from 0. The bins are safe to draw: filled == 1 marks the regions decoded so far (a local file is decoded in several regions in parallel, so coverage is not strictly left-to-right); 0 bins render as a baseline. Use decodeFraction for a progress indicator. Never set for an envelope that grows from playback, nor together with live.
final
duration → Duration
Duration the bin axis spans. For a normal track this is the whole track; for a live window it's the span currently held (see start).
final
end → Duration
Absolute media time at the end of the bin axis (start + duration).
no setter
filled → Uint8List
Per-bin coverage flag (one byte per bin, length matches min): 1 for a bin that has real data, 0 for one not yet covered.
final
hashCode → int
The hash code for this object.
no setterinherited
live → bool
True for a live stream of unknown total length: the envelope is a sliding window anchored to the demuxer cache rather than a fixed [0, duration] track axis (see the class docs and start). A renderer places the playhead at the true playback position (it does NOT pin to "now" or auto-follow the newest bin) and allows scrubbing only within [start, start + duration].
final
max → Float32List
Per-bin maximum sample value, range [-1.0, +1.0].
final
min → Float32List
Per-bin minimum sample value, range [-1.0, +1.0]. Length matches max.
final
rms → Float32List?
Per-bin RMS of the mono signal, range [0.0, 1.0], same length as min. It follows the loudness of each bin even where the peaks stay flat at full scale. null when mpv does not report it.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
start → Duration
Absolute media time of bin 0. Zero for a normal track; for a live rolling window it's the oldest still-cached moment, so bins sit at their true media time and seeks land where they're drawn.
final
totalBins → int?
Total bins on the full axis during a decoding pass (the emitted arrays hold the full axis, with filled marking the decoded part), or null when not decoding.
final

Methods

noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited