Adding sound wave overlays to videos and pictures using FFMPEG
source link: https://christianheilmann.com/2023/08/31/adding-sound-wave-overlays-to-videos-and-pictures-using-ffmpeg/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Adding sound wave overlays to videos and pictures using FFMPEG
Thursday, August 31st, 2023 at 12:09 pm
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 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:
This is what it looked like in the end:
Here’s the command I used to create the above version:
ffmpeg -i Understandable.mp4 \ -filter_complex "[0:a][email protected]\ :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
- `[email protected]` 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
- `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 1280×400 pixels (as the video is 1280×1080)
- 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`:
ffmpeg -i Understandable.mp4 \ -filter_complex "[0:a][email protected]\ :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:
Other sound wave styles
And you can change the output type to line and change the colour:
ffmpeg -i Understandable.mp4 \ -filter_complex "[0:a][email protected]\ :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 |
This is what the point to point mode looks like:
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 |
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 400×400 pixel video with the image as the background and the sound wave on top:
ffmpeg -i Understandable.mp4 -i chris.jpg\ -filter_complex "[0:a][email protected]\ :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 |
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*:
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
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!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK