Skip to content

Instantly share code, notes, and snippets.

@RF5
Created June 25, 2019 19:01
Show Gist options
  • Save RF5/fd77a35e6e5028c200ebeca82133207e to your computer and use it in GitHub Desktop.
Save RF5/fd77a35e6e5028c200ebeca82133207e to your computer and use it in GitHub Desktop.
Python script to rapidly convert folders of flac audio files to mp3, preserving metadata and cover art
# pip install fastprogress
# pip install pydub
from pydub import AudioSegment
from pydub.utils import mediainfo
from fastprogress import progress_bar
import os
import glob
from pathlib import Path
from concurrent.futures.process import ProcessPoolExecutor
import concurrent
def parallel(func, arr, max_workers):
"""
Call `func` on every element of `arr` in parallel using `max_workers`.
Adapted from fastai. Thanks!
"""
if max_workers<2: _ = [func(o,i) for i,o in enumerate(arr)]
else:
with ProcessPoolExecutor(max_workers=max_workers) as ex:
futures = [ex.submit(func,o,i) for i,o in enumerate(arr)]
for f in progress_bar(concurrent.futures.as_completed(futures), total=len(arr)): pass
def proc_vid(v, i):
video, pth_to, pth = v
mp3_filename = pth_to/video.parent.relative_to(pth)/(video.stem + '.mp3')
os.makedirs(mp3_filename.parent, exist_ok=True)
cover_dir = None
# Try to discover a cover image in the current album's folder
# by looking for generic filenames.
if os.path.isfile(video.parent/'cover.jpg'):
cover_dir = video.parent/'cover.jpg'
elif os.path.isfile(video.parent/'cover.png'):
cover_dir = video.parent/'cover.jpg'
elif os.path.isfile(video.parent/'Cover.jpg'):
cover_dir = video.parent/'Cover.jpg'
elif os.path.isfile(video.parent/'Cover.png'):
cover_dir = video.parent/'Cover.png'
elif os.path.isfile(video.parents[1]/'cover.jpg'):
cover_dir = video.parents[1]/'cover.jpg'
elif os.path.isfile(video.parents[1]/'cover.png'):
cover_dir = video.parents[1]/'cover.jpg'
elif os.path.isfile(video.parents[1]/'Cover.jpg'):
cover_dir = video.parents[1]/'Cover.jpg'
elif os.path.isfile(video.parents[1]/'Cover.png'):
cover_dir = video.parents[1]/'Cover.png'
k = AudioSegment.from_file(video, format='flac')
if cover_dir is not None:
k.export(str(mp3_filename), format='mp3', tags=mediainfo(str(video)).get('TAG', {}), cover=str(cover_dir))
else:
k.export(str(mp3_filename), format='mp3', tags=mediainfo(str(video)).get('TAG', {}))
def convert():
folder_with_albums = './my_mixtape_archives/' # Path with folders of flac files
extension_list = ('**/*.flac',)
dirs = os.listdir(folder_with_albums)
for ost in dirs:
if ost.endswith('-mp3'): continue
print("\nConverting ", ost, '\n')
pth = Path(folder_with_albums)/ost
i = 0
pth_to = Path(pth.name + '-mp3')
os.makedirs(pth_to, exist_ok=True)
for extension in extension_list:
videos = [(f, pth_to, pth) for f in pth.glob(extension)]
if len(videos) > 0:
parallel(proc_vid, videos, max_workers=os.cpu_count())
break
print('\n\n')
if __name__ == "__main__":
convert()
@Pr0x1mo
Copy link

Pr0x1mo commented May 1, 2022

So i tried this, i ran it, it prints to me what flac files its supposedly converting, but then i don't see anything created?

@RF5
Copy link
Author

RF5 commented May 2, 2022

It should appear in the same folder of the flac folder but with an "-mp3" appended to the end of the folder name. For example, if you had an album './my_mixtape_archives/album1/', the converted output should be in './my_mixtape_archives/album1-mp3/'

@Pr0x1mo
Copy link

Pr0x1mo commented May 2, 2022

Yeah for some reason nothing was being created and i thought maybe it was an admin right for creating folders and i tried it on my desktop, c: drive, etc... nothing, but i did change it to this and it worked:

def convert(mp3folder):

dirs = Path(mp3folder).glob('**/*.flac')
for ost in dirs:
    print("\nConverting ", ost, '\n')
    flac_audio = AudioSegment.from_file(ost, "flac")
    flac_audio.export(os.path.splitext(ost)[0] + ".mp3", format="mp3", bitrate="320k", tags=mediainfo(str(ost)).get('TAG', {}))

print('\n\n')

if name == "main":
convert('mp3folder')

maybe if someone else is having trouble they could use that...also, was this written for linux? maybe that's my problem.

@Pr0x1mo
Copy link

Pr0x1mo commented May 2, 2022

Oh yeah, this kept the mp3's in the same folder as the flac... i kept it this way because when i grab folders from itunes it won't grab the flac's anyway so at least it just grabs what i want it to grab being in the same folder.

@RF5
Copy link
Author

RF5 commented May 2, 2022

Ahh glad you came right. This code I tested actually for windows, and how pydub's internals might have also changed in the last three years, so this script probably is slightly out of date. If I were to make a new one for 2022 it would probably use ffmpeg instead of pydub. Glad you came right though :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment