HomeCategoriesAll Tags

Creating Song Mashup Using Python Script

Often we need a small portion of a song or combine small portions of various songs into a single file. And not just songs but any audio in general. So here's a way to simply do it using python.

YouTube is a great source of videos and music, but sometimes you may want to download the audio from a YouTube video and extract a specific portion of it. For example, you may want to create a mashup of your favorite songs, or use a sound clip from a video in your own project. In this blog, I will show you how to do this using some simple tools and Python code.

Step 1: Download Audio from YouTube

Here we will use yt-dlp library to download youtube video as audio in mp3 format of best available quality. pip install yt-dlp

def download_audio(videoUrl, outputPath):
    ydl_opts = {
        'format': 'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '320',
        }],
        'outtmpl': outputPath,
        'embedthumbnail': True,
    }

    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        ydl.download(videoUrl)

Step 2: Extract Specific Portions of Audio

Here we will use Pydub library to trim/crop our full length audio and extract only the required portion from it. pip install pydub

def extract_audio_segment(inputPath, outputPath, start_time, end_time):
    audio = AudioSegment.from_file(inputPath, format='mp3')
    segment = audio[start_time * 1000 : end_time * 1000] # Multiply by 1000 as it is in milliseconds
    segment.export(outputPath, format='mp3')

Step 3: Merge All Extracted Portions into a Single MP3 File

def merge_audio_segments(audio_files, output_file):
    combined_audio = AudioSegment.empty()

    for audio_file in audio_files:
        segment = AudioSegment.from_file(os.path.join(trimmedFilesFolder, audio_file), format='mp3')
        combined_audio += segment

    combined_audio.export(output_file, format='mp3')

That's all the steps required and for executing it all we need is to create a json and pass the url of youtube song that we need and it's start and end time to extract that portion from it.

So here is the complete code where we specify the requirements as input and get the final output.

outputPath = "C:/Users/ayush/Videos" # Path where we want to store the final mashup audio file
finalMergedFilePath = "C:/Users/ayush/Videos/mashup.mp3" # file Name
# Json formatted list of youtube songs along with there start and end time that we want to extract
youtubeUrls = [{"url": "https://youtu.be/udra3Mfw2oo", "startTime": 4, "endTime": 9},
  {"url": "https://youtu.be/x7bNx0VbFKs", "startTime": 8, "endTime": 18}
]

import yt_dlp
from pydub import AudioSegment
import os
import shutil

fullFilesFolder = os.path.join(outputPath, "temp-full")
trimmedFilesFolder = os.path.join(outputPath, "temp-trimmed")

os.mkdir(fullFilesFolder)
os.mkdir(trimmedFilesFolder)

def download_audio(videoUrl, outputPath):
    ydl_opts = {
        'format': 'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '320',
        }],
        'outtmpl': outputPath,
        'embedthumbnail': True,
    }

    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        ydl.download(videoUrl)

def extract_audio_segment(inputPath, outputPath, start_time, end_time):
    audio = AudioSegment.from_file(inputPath, format='mp3')
    segment = audio[start_time * 1000 : end_time * 1000] # Multiply by 1000 as it is in milliseconds
    segment.export(outputPath, format='mp3')

def merge_audio_segments(audio_files, output_file):
    combined_audio = AudioSegment.empty()

    for audio_file in audio_files:
        segment = AudioSegment.from_file(os.path.join(trimmedFilesFolder, audio_file), format='mp3')
        combined_audio += segment

    combined_audio.export(output_file, format='mp3')

# Main execution
# Downloading full youtube video as audio and extracting required part of it
for i in range(len(youtubeUrls)):
    download_audio(youtubeUrls[i]['url'], os.path.join(fullFilesFolder, str(i)))
    extract_audio_segment(os.path.join(fullFilesFolder, str(i)+'.mp3'), os.path.join(trimmedFilesFolder, str(i)+'.mp3'), youtubeUrls[i]['startTime'], youtubeUrls[i]['endTime'])

allTrimmedfiles = os.listdir(trimmedFilesFolder)
merge_audio_segments(allTrimmedfiles, finalMergedFilePath)

# Remove the temp files stored during processing
shutil.rmtree(fullFilesFolder)
shutil.rmtree(trimmedFilesFolder)

Hope this was helpful and easy to follow along.

Thanks!!

- Ayush 🙂