Created
August 20, 2026 04:40
-
-
Save mypapit/37817eab6988fe05b87c64025409a894 to your computer and use it in GitHub Desktop.
A bash script that convert MP3 Songs into Spectrum Video Clips with Songs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # ============================================================================ | |
| # MP3 Rainbow Spectrum Video Generator | |
| # | |
| # Description: | |
| # Generates a 1920x1080 MP4 audio spectrum visualizer with animated | |
| # multicolor frequency bars while reserving the bottom area for lyrics. | |
| # | |
| # Author: | |
| # Mohammad Hafiz bin Ismail | |
| # | |
| # Website: | |
| # https://blog.mypapit.net/2026/08/how-to-generate-audio-spectrum-videos-from-mp3-songs-youtube-ffmpeg.html↗ | |
| # | |
| # Copyright: | |
| # Copyright (c) 2026 Mohammad Hafiz bin Ismail (mypapit.net) | |
| # | |
| # Requirements: | |
| # - Bash 4.x or later | |
| # - FFmpeg with: | |
| # * showfreqs | |
| # * geq | |
| # * alphamerge | |
| # * overlay | |
| # * volume | |
| # * libx264 | |
| # * AAC encoder | |
| # | |
| # Usage: | |
| # ./spectrum.sh song.mp3 | |
| # ./spectrum.sh song1.mp3 song2.mp3 song3.mp3 | |
| # ./spectrum.sh *.mp3 | |
| # | |
| # Output: | |
| # song.mp3 -> song-spectrum.mp4 | |
| # | |
| # Layout: | |
| # | |
| # 1920x1080 | |
| # | |
| # +--------------------------------------+ | |
| # | | | |
| # | | | |
| # | visual/background | | |
| # | | | |
| # | █ ███ █████ ██ ████ █ | | |
| # | ██████████████████████ | | |
| # | spectrum area | | |
| # | | | |
| # |--------------------------------------| | |
| # | | | |
| # | RESERVED FOR LYRICS | | |
| # | | | |
| # +--------------------------------------+ | |
| # | |
| # ============================================================================ | |
| set -u | |
| # --------------------------------------------------------------------------- | |
| # Video configuration | |
| # --------------------------------------------------------------------------- | |
| VIDEO_WIDTH=1920 | |
| VIDEO_HEIGHT=1080 | |
| # Spectrum dimensions. | |
| SPECTRUM_WIDTH=1600 | |
| SPECTRUM_HEIGHT=280 | |
| # Horizontal position. | |
| SPECTRUM_X=160 | |
| # Vertical position. | |
| # | |
| # Spectrum occupies Y=520 through Y=800. | |
| # Therefore approximately 280 pixels remain below it for lyrics. | |
| SPECTRUM_Y=520 | |
| # --------------------------------------------------------------------------- | |
| if ! command -v ffmpeg >/dev/null 2>&1; then | |
| echo "Error: FFmpeg is not installed or not available in PATH." | |
| exit 1 | |
| fi | |
| if [ "$#" -eq 0 ]; then | |
| echo "Usage:" | |
| echo " $0 song1.mp3 [song2.mp3 song3.mp3 ...]" | |
| echo | |
| echo "Example:" | |
| echo " $0 *.mp3" | |
| exit 1 | |
| fi | |
| for input in "$@"; do | |
| if [ ! -f "$input" ]; then | |
| echo "Skipping: file not found: $input" | |
| echo | |
| continue | |
| fi | |
| filename="$(basename -- "$input")" | |
| directory="$(dirname -- "$input")" | |
| basename_no_ext="${filename%.*}" | |
| output="${directory}/${basename_no_ext}-spectrum.mp4" | |
| echo "============================================================" | |
| echo "Processing : $input" | |
| echo "Output : $output" | |
| echo "============================================================" | |
| ffmpeg -y \ | |
| -i "$input" \ | |
| -filter_complex "\ | |
| [0:a]volume=3,\ | |
| showfreqs=\ | |
| s=${SPECTRUM_WIDTH}x${SPECTRUM_HEIGHT}:\ | |
| mode=bar:\ | |
| ascale=sqrt:\ | |
| fscale=log:\ | |
| win_size=2048:\ | |
| overlap=0.75:\ | |
| colors=white:\ | |
| rate=30,\ | |
| format=gray[specmask];\ | |
| color=s=${SPECTRUM_WIDTH}x${SPECTRUM_HEIGHT}:c=black:r=30,\ | |
| format=rgb24,\ | |
| geq=\ | |
| r='255*clip(1.5-abs(6*X/W-3),0,1)':\ | |
| g='255*clip(1.5-abs(6*X/W-2),0,1)':\ | |
| b='255*clip(1.5-abs(6*X/W-4),0,1)'\ | |
| [gradient];\ | |
| [gradient][specmask]alphamerge[colored];\ | |
| color=s=${VIDEO_WIDTH}x${VIDEO_HEIGHT}:c=black:r=30[background];\ | |
| [background][colored]overlay=${SPECTRUM_X}:${SPECTRUM_Y}:shortest=1[v]" \ | |
| -map "[v]" \ | |
| -map 0:a:0 \ | |
| -c:v libx264 \ | |
| -preset medium \ | |
| -crf 18 \ | |
| -pix_fmt yuv420p \ | |
| -c:a aac \ | |
| -b:a 320k \ | |
| -shortest \ | |
| "$output" | |
| status=$? | |
| echo | |
| if [ "$status" -eq 0 ]; then | |
| echo "Completed successfully:" | |
| echo " $output" | |
| else | |
| echo "ERROR: FFmpeg failed while processing:" | |
| echo " $input" | |
| fi | |
| echo | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment