Skip to content

Instantly share code, notes, and snippets.

@Vincent-Stragier
Created December 15, 2022 15:48
Show Gist options
  • Save Vincent-Stragier/cf35f50238cdb2618ff82da3b9678e26 to your computer and use it in GitHub Desktop.
Save Vincent-Stragier/cf35f50238cdb2618ff82da3b9678e26 to your computer and use it in GitHub Desktop.
A pydub based Python script used to merged fractions of audio segments.
import argparse
import os
import mimetypes
# You need to:
# python -m pip install pydub tqdm
# And to install ffmpeg
# https://github.com/jiaaro/pydub
# https://github.com/jiaaro/pydub/blob/master/API.markdown
from pydub import AudioSegment
from tqdm import tqdm
PYDUB_DEBUG = False
if PYDUB_DEBUG:
import logging
l = logging.getLogger("pydub.converter")
l.setLevel(logging.DEBUG)
l.addHandler(logging.StreamHandler())
def ensure_path(path: str) -> None:
"""Ensure that the specified path exist."""
if not os.path.isdir(path):
os.makedirs(path)
def safe_mime_guess(path: str) -> list:
"""Always return a iterable when trying to guess the MIME type."""
guess = mimetypes.guess_type(path)[0]
return guess if guess is not None else []
if __name__ == '__main__':
# TODO:
# Add argparse to select input directories or files
parser = argparse.ArgumentParser(
prog='Presets variations merger',
description='This script cut fragments of specified files and merge them in a unique file',
epilog='')
parser.add_argument(
'input', help='A directory of audio files or a list of audio files to merge together', nargs='+')
parser.add_argument(
'-o', '--output', help='The output file', required=True, type=str)
parser.add_argument(
'-f', '--format', help='The format of the output file (by default it is a mp3 file)', default='mp3', )
args = parser.parse_args()
# Create outputs folder tree if it does not exist
output_file = os.path.abspath(args.output)
ensure_path(os.path.dirname(output_file))
# Create the list of input files
input_files = args.input
if len(input_files) == 1:
path = os.path.abspath(input_files[0])
input_files = tuple(os.path.join(path, file) for file in os.listdir(
path) if 'audio' in safe_mime_guess(file))
else:
old_files = input_files
input_files = tuple(
file for file in input_files if 'audio' in safe_mime_guess(file))
if len(old_files) > len(input_files):
print('One or more files have been dropped since their MIME type is not "audio/[...]"')
if len(input_files) < 2:
print(f'Not enough valid input files have been provided:\n{input_files[0]}')
# Import audio files
audio_segments = {file: AudioSegment.from_file(
file, mimetypes.guess_type(file)[1]) for file in input_files}
file_format = args.format
# It is not assumed that each steps is the same
# size thus we will get a fraction of each steps
number_of_steps = len(input_files)
merged_audio = AudioSegment.empty()
index = 0
print('Concatenate audio segments')
for filename, segment in tqdm(audio_segments.items()):
subsegment_length = len(segment)//number_of_steps
indexes = (subsegment_length * index, subsegment_length * (index + 1))
index += 1
if index == number_of_steps:
indexes = (indexes[0], -1)
merged_audio += segment[indexes[0]:indexes[1]]
print('Save result to file')
with open(output_file, 'wb') as file:
merged_audio.export(file, format=file_format)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment