Because bars evoke audio, this shows up a lot around playback or speech recognition, but it communicates the same "still working" as any other indeterminate loader here. If there's a countable value — recognized text length, recording duration — showing that as text alongside is more useful.
Every bar shares the same scaleY keyframe (growing from 0.3× to 1× and back), with animation-delay spaced evenly across bars so the motion appears to travel from one end to the other. All bars sharing one duration is what separates this from equalizer-loader below, where each bar runs its own duration.
Prefer a skeleton for a long wait covering most of the screen, and consider skipping it entirely under 200ms. Give the wrapper role="status" and aria-live="polite", and hide the bars with aria-hidden="true" since they're decorative. Under prefers-reduced-motion, shrink the wave's amplitude or replace it with bars at a fixed height.