FFmpeg can draw a waveform or a spectrogram (a picture that shows the strength of each frequency as colour) from an audio file, as an image or as a video, with no other tool. Use it when you upload a podcast episode to YouTube, post a music clip on social media or need a waveform thumbnail. There are three kinds of filter; pick one by what you want.
| You want | Filter | Output |
|---|---|---|
| A static waveform of the whole file | showwavespic |
one PNG |
| A waveform that moves with playback | showwaves |
video |
| Frequency content, still / moving | showspectrumpic / showspectrum |
PNG / video |
| Frequency bars (equaliser look) | showfreqs |
video |
Static waveform (showwavespic)
ffmpeg -i input.mp3 -filter_complex "showwavespic=s=1920x480" -frames:v 1 waveform.png
The whole track is drawn in one image. -frames:v 1 means “output one frame”. showwavespic outputs only one frame anyway, so you get the same image without it. The background is transparent (RGBA, a pixel format that stores transparency).
Colour and size
ffmpeg -i input.mp3 -filter_complex "showwavespic=s=1920x480:colors=#00d4aa" -frames:v 1 waveform.png
colors takes a hex colour code or a colour name (white, red, …). To draw the two channels of a stereo file one above the other in different colours, add split_channels=1 and list the colours separated by |.
ffmpeg -i input.mp3 -filter_complex "showwavespic=s=1920x480:split_channels=1:colors=#00d4aa|#ff6b6b" -frames:v 1 waveform.png
Adding a background colour
When a transparent background is a problem (for a social-media image, for example), make a background with the color source, which generates a plain colour picture, and put the waveform on it with overlay.
ffmpeg -i input.mp3 -filter_complex "color=c=#0f1117:s=1920x480[bg];[0:a]showwavespic=s=1920x480:colors=#00d4aa[fg];[bg][fg]overlay=format=auto" -frames:v 1 waveform.png
Appearance options
| Option | Values | Effect |
|---|---|---|
scale |
lin (default) / log / sqrt / cbrt |
Amplitude scale. Quiet sound such as speech is easier to see with sqrt or log |
draw |
scale (default) / full |
How the colour is applied. scale paints areas where channels overlap more strongly; full paints everything in the given colour. The shape of the waveform does not change |
filter |
average (default) / peak |
When several samples fall on one pixel, use their average or their peak |
ffmpeg -i input.mp3 -filter_complex "showwavespic=s=1920x480:draw=full" -frames:v 1 waveform.png
Animated waveform video (showwaves)
ffmpeg -i input.mp3 -filter_complex "[0:a]showwaves=s=1280x720:mode=cline:rate=30:colors=#00d4aa,format=yuv420p[v]" -map "[v]" -map 0:a -c:v libx264 -c:a aac -shortest output.mp4
s=1280x720— output resolutionmode=cline— filled in, the same above and below the centre line. The other modes arepoint,lineandp2p(points joined by lines)rate=30— video frame rate (default 25)format=yuv420p— showwaves outputs RGBA; converting to yuv420p lets the H.264 video play in most players-shortest— end the video when the audio ends
You need -filter_complex instead of -vf because this filter takes audio in and puts video out.
With a background colour
showwaves also has a transparent background, so add a background the same way as for the still image. Give the color background the same frame rate with r=30.
ffmpeg -i input.mp3 -filter_complex "color=c=#0f1117:s=1280x720:r=30[bg];[0:a]showwaves=s=1280x720:mode=cline:rate=30:colors=#00d4aa[w];[bg][w]overlay=format=auto[v]" -map "[v]" -map 0:a -c:v libx264 -pix_fmt yuv420p -c:a aac -shortest output.mp4
Waveform over cover art (podcast layout)
-loop 1 repeats a still image to make a video, and a thin waveform strip goes along the bottom. This layout is often used for publishing podcasts and music.
ffmpeg -loop 1 -i cover.png -i input.mp3 -filter_complex "[0:v]scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2[bg];[1:a]showwaves=s=1280x200:mode=cline:rate=30:colors=#00d4aa[w];[bg][w]overlay=0:520:format=auto[v]" -map "[v]" -map 1:a -c:v libx264 -pix_fmt yuv420p -c:a aac -shortest output.mp4
scale=...:force_original_aspect_ratio=decrease,pad=... is the usual way to fit an image inside 1280×720 without stretching it and fill the margins with black. overlay=0:520 puts the 200-pixel-tall waveform at the bottom of the frame (y = 520–720).
Spectrogram (showspectrumpic / showspectrum)
A spectrogram shows time along the x-axis, frequency up the y-axis and strength as colour. You can see noise bands at a glance, and whether high frequencies are there or cut off (the 16 kHz cut-off in an MP3, for example), so it is also useful for checking audio quality.
ffmpeg -i input.mp3 -filter_complex "showspectrumpic=s=1920x480" -frames:v 1 spectrum.png
By default the image has a legend with axes and scale marks. Turn it off with legend=0 when you want a clean picture. Set the colour scheme with color (the showspectrumpic default is intensity; rainbow and others are also available).
ffmpeg -i input.mp3 -filter_complex "showspectrumpic=s=1920x480:legend=0:color=intensity" -frames:v 1 spectrum.png
For video, use showspectrum. With slide=scroll, the picture moves from right to left.
ffmpeg -i input.mp3 -filter_complex "[0:a]showspectrum=s=1280x720:mode=combined:color=intensity:slide=scroll[v]" -map "[v]" -map 0:a -c:v libx264 -pix_fmt yuv420p -c:a aac -shortest output.mp4
Frequency bars (showfreqs)
A display like a graphic equaliser, with one bar for each frequency band.
ffmpeg -i input.mp3 -filter_complex "[0:a]showfreqs=s=1280x720:mode=bar:colors=#00d4aa[v]" -map "[v]" -map 0:a -c:v libx264 -pix_fmt yuv420p -c:a aac -shortest output.mp4
showfreqs also has a rate option, and the default is 25 fps. Add rate=30 for 30 fps.
Measured: render time and file size
These are the processing time and output size of each filter on a 3-minute (180 s) stereo MP3. The source is pink noise (a kind of random noise) made with anoisesrc=color=pink:d=180:r=44100, turned into stereo with -ac 2 and saved as a 192 kb/s MP3. Noise is the worst case for waveform detail, so real music and speech give smaller files. The commands are the ones above with -preset veryfast added (-crf 23 is the default). Test machine: i9-14900KF, FFmpeg 8.1. Measured 2026-09-24.
| Output | Time | Size |
|---|---|---|
showwavespic 1920×480 PNG |
0.25 s | 11 KB |
showspectrumpic 1920×480 PNG |
0.40 s | 1.4 MB |
showwaves cline 1280×720 / 30 fps / 3 min |
18.4 s | 148.4 MB |
showwaves cline 1920×1080 / 30 fps / 3 min |
21.3 s | 161.0 MB |
showspectrum 1280×720 / 3 min |
5.7 s | 13.4 MB |
showfreqs bar 1280×720 / 3 min |
17.6 s | 35.8 MB |
The table shows two things.
showwavesvideo compresses badly with H.264. Thin lines move across the whole frame in every frame, so motion prediction (saving space by storing only what changed since the previous frame) barely works. The 3-minute video came out at 148.4 MB (about 6.6 Mbps), while the spectrogram video of the same audio is 13.4 MB. At the same 1280×720,mode=pointbrought it down to 71.2 MB, a video of only a 200-pixel strip to 80.7 MB, and-crf 28to 95.8 MB (mode=line: 92.0 MB). The filledclinemode gives the largest file.- 720p and 1080p are close in size (148.4 MB and 161.0 MB). With 2.25 times the pixels, the file grew by less than 10%.
FAQ
The output is all black / no waveform visible
showwaves and showwavespic output a transparent (RGBA) background. Players and image viewers that cannot show transparency display it as black. Add a background with color and overlay as shown above. For quiet recordings, scale=sqrt or scale=log makes the waveform easier to see.
I want one waveform for a stereo file
By default, showwavespic draws the channels on top of each other (split_channels=0). For a single waveform, put aformat=channel_layouts=mono in front of it to mix the audio down to mono first.
The waveform video has no sound
-map 0:a is missing. Once you use any -map, FFmpeg stops choosing streams automatically. So after -map "[v]" for the video, you also need -map 0:a for the audio.
Related tool
The Waveform video tool generates a showwaves-style video from an audio file in your browser.
Related articles
- Extract audio — pull just the audio out of a video
- Measure volume (volumedetect) — check levels before drawing
- Loudness normalisation — even out levels before publishing
- Create GIFs — for a short animated waveform GIF