FFMPEG COMMAND

Generate a waveform image with FFmpeg

showwavespic draws the whole file into a single picture. The commands below produce a transparent PNG, a two-colour stereo version, a dark solid background and a spectrogram, each checked with ffprobe.

Verified with FFmpeg 9.0.1 on 26 August 2026. Search intent: ffmpeg waveform image.

the command
ffmpeg -i input.mp3 -filter_complex "showwavespic=s=1280x240:colors=#21B4CE" -frames:v 1 waveform.png

Reads the audio, draws its amplitude over time into a 1280x240 image and writes one PNG. The background is transparent (the output pixel format is rgba), so the waveform can sit on any page.

Flags, explained

showwavespic=s=1280x240
Output size. Each column summarises the samples that fall into it, so width sets the time resolution.
colors=#21B4CE
Trace colour, hex or named. Several values separated by | are used per channel.
split_channels=1
Draw each channel in its own band instead of overlapping them.
scale=sqrt
Amplitude scale: lin (default), log, sqrt or cbrt. Non-linear scales make quiet audio visible.
draw=full:filter=peak
Fill the shape and use peak values per column rather than averages.
-frames:v 1
Write a single image. showwavespic emits one frame anyway; the flag makes the intent explicit.
-filter_complex
Required because the filter turns audio into video; -af cannot change the media type.

Variants

One colour per channel

shell
ffmpeg -i input.mp3 -filter_complex "showwavespic=s=1280x240:colors=#21B4CE|#E0489B:split_channels=1" -frames:v 1 waveform.png

split_channels stacks the left and right channels; colors takes a | separated list, one per channel.

Solid dark background

shell
ffmpeg -i input.mp3 -filter_complex "color=c=#17181C:s=1280x240[bg];[0:a]showwavespic=s=1280x240:colors=#F2C93B[w];[bg][w]overlay=format=auto,format=rgb24" -frames:v 1 waveform.png

Generates a flat colour canvas and overlays the waveform on it; format=rgb24 drops the alpha channel, which you need before saving as JPEG.

From a video, mono, square-root scale

shell
ffmpeg -i input.mp4 -filter_complex "[0:a]aformat=channel_layouts=mono,showwavespic=s=1280x240:colors=white:scale=sqrt" -frames:v 1 waveform.png

Works on the audio track of a video. Mixing to mono gives one trace; scale=sqrt lifts quiet passages so speech does not look flat.

Peaks instead of averages

shell
ffmpeg -i input.mp3 -filter_complex "showwavespic=s=1280x240:colors=#21B4CE:draw=full:filter=peak" -frames:v 1 waveform.png

filter=peak keeps the loudest sample of each column, draw=full fills the shape. Closer to what audio editors show.

Spectrogram instead of a waveform

shell
ffmpeg -i input.mp3 -filter_complex "showspectrumpic=s=1280x480:legend=0" -frames:v 1 spectrogram.png

Frequency over time as a heat map, 1280x480 rgb24. legend=0 removes the axis labels.

Pitfalls we hit

  • The default background is transparent (rgba). Some viewers render that as black, and JPEG cannot store it: overlay on a colour and convert to rgb24 first.
  • Steady tones draw as a flat band; the test tone at -16 dBFS filled a thin stripe. Real speech or music shows the envelope you expect.
  • Linear scale hides quiet material. Podcasts normalised to -16 LUFS look small at scale=lin; use sqrt or log.
  • Very long files are downsampled to the image width: a 2 h recording in 1280 columns averages about 5.6 s per pixel. Increase the width or trim the input.
  • -af showwavespic fails because the filter outputs video; use -filter_complex or -lavfi.

How we verified it

Run with FFmpeg 9.0.1 on 26 August 2026 against a 12 s 48 kHz MP3 and a 12 s H.264/AAC video. Primary command: PNG 1280x240 rgba, 1,946 bytes. split_channels: 1280x240 rgba. Dark background variant: 1280x240 rgb24. Video input, mono, sqrt: 1280x240 rgba. draw=full:filter=peak: 1280x240 rgba. showspectrumpic: 1280x480 rgb24, 43,595 bytes. The same command without -frames:v 1 produced the same single PNG.

The same edit as a typed operation

generate_audio_waveform takes a width, a height and a colour, accepts audio or video input, and returns a transparent PNG through a signed URL. No filter graph to assemble and no pixel format to remember.

MCP tool: generate_audio_waveformPOST /api/v1/tools/audio-waveform
request body
{
  "inputs": [{ "id": "main", "url": "https://example.com/podcast.mp3" }],
  "options": { "width": 1280, "height": 240, "color": "#C4FF4C" }
}

FAQ

Is the waveform image transparent?

Yes by default: showwavespic writes rgba with a transparent background. Overlay it on a colour source and convert to rgb24 when you need an opaque image or a JPEG.

Can I draw the waveform of a video file?

Yes. Reference the audio stream with [0:a] in -filter_complex, as in the video variant; the picture is ignored.

Why does my waveform look flat?

Either the audio is quiet on a linear scale or it is a steady tone. Use scale=sqrt or scale=log, and check the file with ebur128 to see its actual level.

How do I get a spectrogram instead?

Replace showwavespic with showspectrumpic, which maps frequency over time to colour. The variant above renders a 1280x480 image without axis labels.

Related commands

All FFmpeg commands