Created
January 3, 2021 17:46
-
-
Save don-code/9dac1bd06ac797876fa9fa6cf49be821 to your computer and use it in GitHub Desktop.
Sync FLAC music library to dumb MP3 players.
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
#!/usr/bin/env ruby | |
# This script syncs music to an MP3 player that only plays MP3s, according to | |
# the following rules: | |
# | |
# 1. Always copy files using a scheme that makes it easy to navigate based on folders: | |
# $ARTIST/$ALBUM/$TRACK.mp3 | |
# 2. If the destination track already exists as an MP3, do nothing. | |
# 3. If the source track is an MP3, copy it without any processing. | |
# 4. If the source track is a FLAC, transcode it to MP3 and copy the MP3. | |
# | |
# Adjust MUSIC_SOURCE and MUSIC_TARGET to meet your needs. | |
# | |
# The "MP3 player" this script was intended for is actually a car head unit with | |
# a rudimentary folder browser. | |
require 'fileutils' | |
MUSIC_SOURCE = '/home/don/Music' | |
MUSIC_TARGET = '/run/media/don/USB DISK' | |
def sync_directory(artist, album = nil) | |
puts "Artist: #{artist} | Album: #{album}" | |
source_dir = build_path(MUSIC_SOURCE, '/', artist, album) | |
target_dir = build_path(MUSIC_TARGET, ' - ', artist, album) | |
songs_to_sync = Dir.children(source_dir).select do |child| | |
is_music = false | |
%w(flac mp3 m4a mp4 wma).each do |type| | |
if child.end_with?(type) | |
is_music = true | |
break | |
end | |
end | |
is_music | |
end | |
Dir.mkdir(target_dir) if !Dir.exist?(target_dir) && songs_to_sync.count > 0 | |
songs_to_sync.each do |song_to_sync| | |
full_path = "#{source_dir}/#{song_to_sync}" | |
sync_file(full_path, target_dir) | |
end | |
end | |
def sync_file(source_file, target_dir) | |
if source_file.end_with?('mp3') # pass through | |
return if File.exist?("#{target_dir}/#{File.basename(source_file)}") | |
puts "Copying MP3: #{source_file}" | |
FileUtils.cp(source_file, target_dir) | |
else # transcode | |
dest_file = "#{target_dir}/#{File.basename(source_file).gsub(File.extname(source_file), '.mp3')}" | |
return if File.exist?(dest_file) | |
puts "Transcoding: #{source_file}" | |
`ffmpeg -i "#{source_file}" -b:a 320k "#{dest_file}"` | |
end | |
end | |
def build_path(location, join, artist, album = nil) | |
path = "#{location}/#{artist}" | |
path += "#{join}#{album}" if album | |
path | |
end | |
def subdirectories(path) | |
Dir.children(path).select { |x| File.directory?("#{path}/#{x}") } | |
end | |
artists = subdirectories(MUSIC_SOURCE) | |
artists.each do |artist| | |
sync_directory(artist) | |
albums = subdirectories("#{MUSIC_SOURCE}/#{artist}") | |
albums.each do |album| | |
sync_directory(artist, album) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment