DEV Community

Thi Ngoc Nguyen
Thi Ngoc Nguyen

Posted on

How to Build a Custom Rap Beat Maker with Python and FFmpeg

  • Automating audio rendering pipelines helps generate background tracks without facing copyright claims.
  • Low-end phase cancellation can be solved by isolating sub-bass frequencies to mono.
  • Local post-processing scripts are often cheaper and more predictable than cloud APIs.

If you have ever tried to scale a content site or build a background music pipeline, you know the licensing landscape is a minefield. Standard stock music libraries get flagged by automated systems, and hiring a composer for every minor project is too slow. I spent the last three weeks building a custom local pipeline to generate background tracks, essentially constructing a lightweight Rap Beat Maker and a secondary script that acts as a Slowed and Reverb Generator. The goal was simple: feed in a few configuration variables, process some stems, and output a unique, loopable track that sounds decent enough to sit behind a voiceover. Here is how I set up the Python and ffmpeg backend, what broke during development, and how I solved the audio degradation issues.

Q: Why not just use pre-made loop packages and call it a day?

The short answer is copyright enforcement. When you buy or download a royalty-free loop package, you do not own the exclusive rights. If another creator uses the exact same loop in a published track, automated scanning systems on platforms like YouTube or Twitch cannot tell the difference between your video and their track. This leads to copyright strikes and manual dispute resolution loops that eat up development time.

By building your own generation and processing pipeline, you gain control over the underlying stems. You can dynamically adjust tempos, swap out drum patterns, and apply custom audio filters to ensure the output remains structurally distinct. I wanted to run this pipeline headlessly on a Linux server, which ruled out manually pointing and clicking inside a traditional Digital Audio Workstation (DAW) like Ableton Live. The goal was an automated script that accepts stem folders, applies digital signal processing, and formats the output. I spent hours monitoring these running processes in a tmux session, watching Python spawn multiple instances of FFmpeg to handle concurrent audio chunk conversions.

Q: What broke during your first automated audio mixing run?

When I ran my first batch of automated mixes, the low-end of the music sounded incredibly weak when played on mobile devices. The bass was present on headphones but completely disappeared on phone speakers.

The cause was phase cancellation. In my attempt to make the stereo field wider, I had applied a slight delay to the left channel of the sub-bass synth. When the audio pipeline downmixed the stereo file to mono for standard phone speakers, the left and right waves shifted, directly canceling each other out.

The phase correlation meter was showing a negative value, meaning the channels were actively fighting. The render script took exactly 14.3 minutes to process a batch of fifty variations, and every single one was unusable. While debugging this, the local coffee shop ran out of oat milk, so I had to drink black coffee, which only fueled my irritation with the phase cancellation issues.

The fix was to split the audio spectrum into two paths before mixing. I wrote an FFmpeg filter graph that kept everything below 120Hz strictly in mono, while allowing the mid and high frequencies to maintain their stereo width. Here is the filter setup I used to isolate the low-end:

ffmpeg -i input.wav -filter_complex \
"[0:a]lowpass=f=120,pan=mono|c0=FL+FR[sub]; \
 [0:a]highpass=f=120[midhigh]; \
 [sub][midhigh]amix=inputs=2[out]" \
 -map "[out]" output_fixed.wav
Enter fullscreen mode Exit fullscreen mode

By forcing the sub-bass to sum to mono before the final export, the phase cancellation disappeared. It took 117 commits to my local repository to clean up this utility and make it modular enough to handle different track structures without clipping.

Q: How do we handle tempo modifications without ruining transient definition?

To make a proper slowed-and-reverb track, you cannot just slow down the playback speed. If you use a naive resampling method, you lower both the pitch and the speed, which works, but it often softens the transients (like the snap of a snare drum or the click of a hi-hat).

If you try to stretch the audio using standard pitch-shifting algorithms to keep the pitch stable while slowing down the tempo, you introduce phasey, watery artifacts. The solution for this pipeline was to utilize the rubberband filter in FFmpeg for clean time-stretching, combined with an automated feedback delay for the reverb effect. Here is how I structured the tempo reduction and spatial processing:

import subprocess

def apply_slowed_reverb(input_path, output_path, tempo_factor=0.85):
    # We slow down the audio pitch and tempo proportionally for that classic feel,
    # then apply a wet reverb mix using a complex filter graph.
    cmd = [
        'ffmpeg', '-y', '-i', input_path,
        '-filter_complex',
        f"[0:a]asetrate=44100*{tempo_factor},aresample=44100[slowed];"
        "[slowed]aecho=0.8:0.9:1000:0.3[reverb];"
        "[slowed][reverb]amix=inputs=2:weights=0.7 0.3[out]",
        '-map', '[out]', output_path
    ]
    subprocess.run(cmd, check=True)
Enter fullscreen mode Exit fullscreen mode

This maintains the weight of the track while introducing the desired space. However, generating the initial high-quality stems to feed into this pipeline remained a bottleneck.

Q: Where do external tools fit into this processing workflow?

While my local scripts handled the post-processing and tempo shifts, generating high-quality source material was still a major hurdle. I tested several platforms to generate seed tracks and stems, including MusicAI, MusicCreator AI, and MusicArt.

My comparison was based on highly mundane developer criteria: I did not care about which tool claimed to have the most creative algorithms. Instead, I focused on the licensing terms, whether they offered raw WAV file downloads on the basic tier, and how easily their output could be parsed by a script.

Here is how they stacked up during my testing:

Tool Name Output Format Billing Model API Quota Limits Stem Download Support
MusicAI MP3 only Subscription Strict monthly cap No
MusicCreator AI WAV / MP3 Credits Daily rate limits Yes (Paid add-on)
The Primary Tool WAV / MP3 Subscription No strict daily limits Yes (Included in basic)

I chose the third option simply because their basic subscription allowed raw WAV stem exports without forcing me to upgrade to an enterprise tier, and they did not rate-limit my automated test scripts during my trial phase.

However, the platform is not perfect. I encountered two main issues during integration:

  1. High-frequency artifacts: When generating fast-tempo beats, there is a distinct metallic comb-filtering noise on the cymbals and hi-hats above 15 kHz. It sounds like an over-compressed MP3, even when downloaded as a lossless WAV. I had to write an aggressive lowpass filter to clean up the top end.
  2. Messy export structures: The exported ZIP folders containing the stems do not follow a standardized naming convention. Instead of saving files as bass.wav or drums.wav, they use chaotic UUIDs like stem_9b1deb4d-3b7d-4bad.wav. This forced me to write a custom regex parser to analyze the audio metadata and rename the files before feeding them into my local mixing script.

Q: What does the complete automation pipeline look like?

To make this setup reproducible, I unified the stem extraction, cleaning, and tempo shifting into a single orchestrator script. This script pulls the raw stems, cleans up the high-frequency artifacts introduced by the generator, forces the sub-bass to mono, and applies the slowed-and-reverb treatment.


Technical Pipeline Checklist

If you are setting up your own automated background music or beat processing system, keep this pipeline checklist in mind:

  • Isolate Low Frequencies: Always sum everything below 120Hz to mono to prevent phase cancellation on mobile speakers.
  • High-Frequency Cleanup: Apply a lowpass filter around 15 kHz to remove metallic compression artifacts from generated stems.
  • Preserve Transients: Use proportional resampling (asetrate) instead of naive time-stretching (atempo) if you want to keep transients punchy when slowing down beats.
  • Regex Normalization: Standardize the file names of incoming cloud stems to avoid pathing errors in your local post-processing scripts.

Disclosure: I pay for MusicArt. No other affiliation.

Top comments (0)