Adding sound wave overlays to videos and pictures using FFMPEG
Tags: ffmpeg, videoediting, cli, tips
Published: 2023-08-31 11:05:18

---
title: Adding sound wave overlays to videos and pictures using FFMPEG
published: true
description: A quick tutorial how to use FFMPEG on the command line to create videos with sound wave overlays
tags: ffmpeg, videoediting, cli, tips
canonical_url: https://christianheilmann.com/2023/08/31/adding-sound-wave-overlays-to-videos-and-pictures-using-ffmpeg/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kw9udrne9gj88h686ckc.gif
# Use a ratio of 100:42 for best results.
# published_at: 2023-08-23 19:22 +0000
---

In order to fix a broken video where the camera stopped recording, I wanted to replace the part with a video with a sound wave overlay. There are many services for that, and it is also a feature of video editing software. But I am stingy and a geek, so I wanted to use [FFMPEG](https://ffmpeg.org/) on the command line instead. This also allows for batch processing.

> Note: I didn't embed the videos in this post but GIFs instead. The real videos play the video and audio and the sound wave moves accordingly.

Let's say this is our original video:

![Video of me talking about public speaking](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ihmswy69i0nabkjqvx15.gif)

This is what it looked like in the end:

![The same video with a sound wave on top of it](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kw9udrne9gj88h686ckc.gif)

Here's the command I used to create the above version:

```bash
ffmpeg -i Understandable.mp4 \
 -filter_complex "[0:a]showwaves=colors=0xff1646@0.3\
 :scale=sqrt:mode=cline,format=yuva420p[v];\
 [v]scale=1280:400[bg];\
 [v][bg]overlay=(W-w)/2:H-h[outv]"\
  -map "[outv]" -map 0:a -c:v libx264 -c:a copy \
  waveform-sqrt-cline.mp4
```

OK, let's unwrap this: 

* `Understandable.mp4` is the input file
* `0xff1646@0.3` is the hexadecimal colour of the waves I want to create. The `@0.3` is the opacity, 30%.
* The first `scale` is how the bars should be resized to stay in a certain range. I found squareroot to look the best. Other options are available in the [documentation](https://ffmpeg.org/ffmpeg-filters.html#showwaves)
* `mode` is what soundwave you want. This version, `cline` is a centered, filled line. Other options are `point`, `line` and `p2p`.
* `scale` is the size of the generated video of the wave, in this case 1280x400 pixels (as the video is 1280x1080)
* The `overlay` defines where on the background video the wave should appear. In this case centred in the horizontal direction and on the bottom of the video. 
* `waveform-sqrt-cline.mp4` is the name of the final video.

## Change location of the sound wave

You can also center the sound wave in both directions using `overlay=(W-w)/2:(H-h)/2`: 

```bash
ffmpeg -i Understandable.mp4 \
 -filter_complex "[0:a]showwaves=colors=0xff1646@0.3\
 :scale=sqrt:mode=cline,format=yuva420p[v];\
 [v]scale=1280:400[bg];\
 [v][bg]overlay=(W-w)/2:(H-h)/2[outv]"\
  -map "[outv]" -map 0:a -c:v libx264 -c:a copy \
  waveform-sqrt-cline-centered.mp4
```

And the result looks like this:

![Video showing the sound wave in the vertical center](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/amke4lpmxyolfytl0hei.gif)

## Other sound wave styles

And you can change the output type to line and change the colour: 

```bash
ffmpeg -i Understandable.mp4 \
 -filter_complex "[0:a]showwaves=colors=0xffffff@0.5\
 :scale=sqrt:mode=line,format=yuva420p[v];\
 [v]scale=1280:400[bg];\
 [v][bg]overlay=(W-w)/2:H-h[outv]"\
  -map "[outv]" -map 0:a -c:v libx264 -c:a copy \
  waveform-sqrt-line.mp4
```

![Video showing the sound wave as lines](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v9ptu824socsezet98ao.gif)

This is what the point to point mode looks like:

```bash
ffmpeg -i Understandable.mp4 \
 -filter_complex "[0:a]showwaves=colors=0xffffff\    
 :scale=sqrt:mode=p2p,format=yuva420p[v];\ 
 [v]scale=1280:400[bg];\
 [v][bg]overlay=(W-w)/2:H-h[outv]"\
  -map "[outv]" -map 0:a -c:v libx264 -c:a copy \
 waveform-sqrt-p2p.mp4 
```

![Video with point to point line](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3fja6cy8zmjstftqz1sx.gif)

## Adding a sound wave to a static image

If you only want the audio from a video and use a background image instead, this is what to use. This creates a 400x400 pixel video with the image as the background and the sound wave on top:

```bash
ffmpeg -i Understandable.mp4  -i chris.jpg\
 -filter_complex "[0:a]showwaves=colors=0xff1646@0.3\
 :scale=sqrt:mode=cline,format=yuva420p[v];\
 [1:v]scale=400:400[bg];\
 [bg][v]overlay=(W-w)/2:(H-h)/2[outv]"\
  -map "[outv]" -map 0:a -c:v libx264 -c:a copy \
  static-image.mp4
```

![Soundwave on top of a static image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idqd0h8ke1m4r94r6ku5.gif)

## FFMPEG is amazing

Granted, the syntax of FFMPEG is pretty nuts, but it is also super powerful. Want to know for example how I created the GIFs of this post? 

First, I resized all the MP4s in the folder to 1/3 of their size and saved them as small*:

```bash
for f in *.mp4 ; \
do ffmpeg -i "$f" -vf scale=w=iw/3:h=ih/3 "small-$f" ;\
done             
```

Then I took those and created gifs 

```bash
for f in small-*.mp4 ; \
do ffmpeg -i "$f" -sws_dither ed -ss 5 -t 1 "e-$f.gif" ; \
done      
```

In English: Get all small-*.mp4s in the current folder, and create a GIF from second 5 of the video, one second long, using error diffusion. 

Automate all the things!

![Soundwave from transformers pressing a button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35n4tg5x2dfbeeodga44.gif)