Announcement

Collapse
No announcement yet.

Batch creation of "m3u" (music playlists) across many folders

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Batch creation of "m3u" (music playlists) across many folders

    This is more of a discussion than a call for help. However, I never pass up good advice! If you can suggest improvements to my script, please do! Also, there's a "To-Do" list near the end so if you have ideas/answers it would be greatly appreciated.

    The motivation: I noticed many of my music collection folders did not have ".m3u" files in them. Further digging revealed many folders where file names had changed but the m3u file was not updated so it was (at least partially) invalid. I searched for an easy way to update/create these en masse, but could find no suitable options. I normally listen to my music via Plex so the m3u files aren't really necessary (which is why I hadn't noticed the deficiencies) but when I'm on my PC it's great to be able to just click on an m3u file and launch an entire album with Amarok.

    So I set out on "batching" this task.

    Some things that made this task easier in my specific case:
    • My collection is entirely made up of FLAC and MP3 files only. If I get some music in another format like OPUS or WAV I convert them before posting them in my collection.
    • My collection follows a strict folder and file naming structure the Plex requires.
    • All my music is on my media server and mounted on my computer at "/shared/Music/".
    • I took an existing ".m3u" file from one album, made sure it launched Amarok as desired, then duplicated it's format.
    Some things that were a little difficult:
    • Manipulating the artist, album, and song names to separate them and combine them in the proper formats.
    • Acting on multiple file formats in one go.
    • Figuring out how to get the song length.
    Here's a snippet from an existing file created by K3b:
    Code:
    #EXTM3U
    #EXTINF:250,Red Hot Chili Peppers - The Getaway
    01 - The Getaway.flac
    #EXTINF:302,Red Hot Chili Peppers - Dark Necessities
    02 - Dark Necessities.flac
    #EXTINF:200,Red Hot Chili Peppers - We Turn Red
    03 - We Turn Red.flac
    and here's one from a file my script created:
    Code:
    #EXTM3U
    #EXTINF:173,311 - Down
    01 - Down.flac
    #EXTINF:187,311 - Random
    02 - Random.flac
    #EXTINF:204,311 - Jackolantern’s Weather
    03 - Jackolantern’s Weather.flac​
    A perfect pattern match!

    For those unfamiliar with these files;
    • The header - #EXTM3U - indicates the m3u content format is the "extended" version and contains more info than a basic playlist.
    • Each line beginning with #EXTINF is some song info. Here, I used only length in seconds, album artist, and song title.
    • Each line following the #EXTINF lines contains the actual filename to be played. The full file path is only necessary if the m3u file is not in the same directory as the audio files.
    What this script actually does is pretty well described in the file comments:
    1. Creates a list of folders that contain MP3 or FLAC files
    2. Create the M3U file with header in each folder
    3. Calculates each song length to nearest second
    4. Creates a list of songs (mp3 or flac) in the M3U file
    5. Outputs progress to the console so the user can see the activity ​
    What the script does NOT do (yet), i.e. The "To-Do" list:
    1. Have a simple GUI instead of console use only.
    2. Allow inputting of a single folder or group of folders rather than the whole collection.
    3. Allow an option to use the full path name in the m3u file.
    4. Preserve an existing m3u file or offer the option to replace (or not) existing m3u files.
    5. Detect a file change in a folder and/or skip folders that have an existing m3u file that is newer than the folder contents.
    Additionally, I would like to create a Dolphin Service menu that would activate this script (or something similar) within a selected folder. I think this would be really useful when one is updating a music collection.

    As well as the To-Do's I would also love to hear suggestions on shortening the code or making it more efficient.

    Building the array of files and folders takes considerable time because of the "sort -u" action I used to grab folder names and paths. By "considerable time" it's about 16 seconds after launch before the first file creation is started. My system is fairly powerful, but the files are being accessed via NFS file sharing and are stored on a NAS platter drive. My collection is also quite large.

    Here's the entire script with comments
    Code:
    #!/bin/bash
    # set script variables
    HEADER='#EXTM3U'
    LINE='#EXTINF:'
    MUSICPATH='/shared/Music'
    
    # Allow spaces in folder and file names
    IFS=$'\t\n'
    
    # create array of folders containing music file types
    declare -a FOLDERS=(`find "$MUSICPATH" \( -name "*.mp3" -o -name "*.flac" \) -printf "%h\n" | sort -u`)
    
    # start loop for each folder
    for DIR in "${FOLDERS[@]}"; do
    
    # create inital .m3u file
    M3UFILE=`echo -n $DIR;echo $DIR | awk -F'/' '{ print "/"$5".m3u" }'`
    
    # add first line to file
    printf '%s\n' $HEADER > $M3UFILE
    
    # console progress output
    echo "Processing "$DIR"... "
    
    # get list of music files in the folder
    readarray -d '' FILES < <(find "${DIR}" \( -name "*.mp3" -o -name "*.flac" \) -print0 | sort -z)
    
    # start loop for each file
    for FILE in "${FILES[@]}"; do
    
    # get file length and round to nearest second
    DURATION=(`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $FILE`)
    ROUNDED=$(printf "%.0f\n" $DURATION)
    
    # get album artists name
    ARTIST=`echo $FILE | awk -F'/' '{ print $4" - "}'`
    
    ## get album and file names
    # song name with extension
    SONGFILE=`echo $FILE | awk -F'/' '{ print $NF}'`
    
    # song name without extension for label
    SONG2=`echo $SONGFILE | awk -F' - ' '{ print $2}'`
    SONGTITLE=`echo "${SONG2%.*}"`
    
    # put file info and file name in m3u file
    printf '%s\n' $LINE$ROUNDED,$ARTIST$SONGTITLE >> $M3UFILE
    printf '%s\n' $SONGFILE >> $M3UFILE
    
    # console progress output
    echo -ne $SONGFILE\\r
    
    # loop to next file
    done
    
    #loop to next folder
    done
    
    # done
    echo "Complete"
    exit
    ​
    Last edited by oshunluvr; Today, 08:51 AM.

    Please Read Me

Users Viewing This Topic

Collapse

There are 0 users viewing this topic.

Working...
X