progress library
for audio_file in get_audio_files(source): ...
got an acceptable display with
rich
Ok, sure, that's one possibility.
I commend the tqdm package to you. The usual idiom is:
from tqdm import tqdm
for audio_file in tqdm(get_audio_files(source)): ...
and that will show elapsed time for each file (each "iteration").
If you can afford to first gather all filenames into a container, then the idiom would be:
for audio_file in tqdm(list(get_audio_files(source))): ...
That results in a more informative progress bar, because tqdm() knows that we're currently on e.g. file 3 of 20. It also lets tqdm() display an estimate of when all files will be finished.
The docs
explain that there's a bunch of optional parameters,
plus you can call .update() to display details
of each audio track as we're crunching through it.
It can also accommodate fancy needs like two bars,
one for artist and another for the artist's tracks.
The benefit of tqdm() is that it is trivially easy to add to an app, without "really complicating what was previously a very single-purpose function".
pathlib
if not artist_path.is_dir():
I like it!
Thank you for preferring Path over the ancient os.path module.
Also, kudos on using {mypy, pyright} to check your type annotation. Your code offers informative signatures which are easy to read.
tuple
yield track
Consider using yield artist, track,
as that plays nicely with sorting,
and would expose more info for tqdm() to display.
accurate progress
Let's assume that most tracks are about three minutes, with no giant outliers. And we expect that some artists are "prolific", while another might be a "one hit wonder".
If work per artist has high variance,
much higher than work per track,
then you might prefer to operate on a flat list
of (artist, track) tuples.
Otherwise we might wind up with the final artist
representing much more or much less work than average,
which makes it challenging for the bar's "countdown"
to arrive at zero just as we're finishing up all the work.
If you're a stickler for accuracy then you might stat()
each track file to learn its length, and generate
a 3-tuple of (artist, track, num_bytes).
You would have to sum() all the lengths before
starting the top-level for loop, and then .update()
the progress bar with each completed track length.