Created
December 15, 2022 15:48
-
-
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.
This file contains 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
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