Last active
August 6, 2024 10:18
-
-
Save danstowell/84eff5456ce6b3c4d1c82f29de374790 to your computer and use it in GitHub Desktop.
Python script to enforce a maximum duration on a set of audio files. Long files are trimmed, without altering the sample data. The script can either convert all to FLAC, or preserve exact container type for each file.
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
#!/bin/env python | |
# Script to enforce a maximum duration on a set of audio files. | |
# Long files are trimmed, without altering their file format. | |
# Uses ffmpeg. (So, that needs to be installed on your system). | |
# Tested in Ubuntu Linux v22.04. | |
# Written by Dan Stowell 2024. | |
# CC0: This work has been marked as dedicated to the public domain. | |
import os, glob, subprocess | |
################################################### | |
# User config variables: | |
indir = "wavs_original" | |
outdir = "wavs_trimmed" | |
maxdur = 120 # measured in seconds | |
verbose = True | |
convert_format = True # whether to convert all to FLAC (should achieve smaller filesize without data loss) | |
################################################### | |
totalin = 0 | |
totalout = 0 | |
for inpath in sorted(glob.glob(os.path.join(indir, "*.*"))): | |
filename = os.path.basename(inpath) | |
outpath = os.path.join(outdir, filename) | |
if convert_format: | |
acodec = 'flac' | |
outpath = os.path.splitext(outpath)[0] + ".flac" | |
else: | |
acodec = 'copy' | |
totalin += 1 | |
if verbose: | |
print("======================") | |
print(f"File {filename}:") | |
# First calculate the duration | |
cmd = ["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", inpath] | |
try: | |
result = subprocess.run(cmd, capture_output=True, check=True, text=True) | |
#print(result) | |
filedur = float(result.stdout) | |
except Exception: | |
print(f"WARNING: Unable to read duration of input file: {filename}") | |
if verbose: | |
print(result.stdout) | |
print(result.stderr) | |
continue | |
# This is the main command. We will add more arguments. | |
cmd = ["ffmpeg", "-loglevel", "quiet", "-y", | |
"-i", inpath, "-acodec", acodec] | |
if filedur <= maxdur: | |
# Note that despite "no trim needed", we still use ffmpeg to copy it, | |
# to ensure the file's container is readable, | |
# i.e. all output files will surely be readable at least by ffmpeg. | |
if verbose: | |
print(f"File will be kept full length: {filename}, full dur {filedur}") | |
pass | |
else: | |
if filedur <= maxdur * 3: | |
# choosing the middle segment | |
starttime = (filedur - maxdur) / 2 | |
else: | |
# choosing the segment [maxdur, maxdur * 2] | |
starttime = maxdur | |
if verbose: | |
print(f"File will be trimmed: {filename}, full dur {filedur}, start will be {starttime}") | |
cmd += ["-ss", str(starttime), "-t", str(maxdur)] | |
cmd += [outpath] # the command is finally completed, with the output path | |
if verbose: | |
print(cmd) | |
print(" ".join(cmd)) | |
try: | |
result = subprocess.run(cmd, capture_output=True, check=True, text=True) | |
except Exception: | |
print(f"WARNING: Error creating edited file for: '{filename}'") | |
if verbose: | |
print(result.stdout) | |
print(result.stderr) | |
continue | |
totalout += 1 | |
print(f"Finished. Converted {totalout} out of {totalin} files.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment