I recently decided I wanted to synchronize some of my music with my Nexus One. I quickly discovered that the Nexus One didn't support WMA audio files. I also discovered there weren't any out-of-the-box solutions for syncing audio files and playlists with the flexibility I required.
So I decided to write my own between two World Cup matches. I felt the script might be useful to other people and I couldn't find a suitable place to put it. So I am dumping it here.You will need the following software installed to use this script.
All my music files are currently in WMA format. This will change in the future but until then the script converts the files into MP3 using FFmpeg. This can be changed if you need by adjusting the function "convert_file".
Copy and paste the code below into a file called syncplayer.py. You may need to edit some of the settings at the top of the file. If you have Python files correctly associated on your PC then you should be able to double-click the file and the sync will run whilst displaying a log on the console.
Enjoy!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | """ SyncPlayer.py - A Python script for synchronizing music files between Foobar2000 and an MP3 device. Copyright (C) 2010 Blair Sutton This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http: licenses="" www.gnu.org="">. """ ######################## #### SETTINGS BELOW #### ######################## # this is an array of foobar2000 playlist names you want synched # playlists = [ "NexusOne" , "Driving Music" ] # this is the path to your android/mp3 player music folder once mounted. # the converted files will be placed here. # destination_root = r "f:\Music" # this is the path to your android/mp3 player playlist folder. m3u files will # place here. # playlist_root = r "f:\Music\Playlists" # this is your target conversion format. # destination_ext = ".mp3" # this is how many path levels including your source audio file are synced to the # device. i.e. artist/album/audio file # path_depth = 3 # change these paths to reflect where your converters are installed # ffmpeg_path = r "C:\Program Files\FFmpeg-0.6-svn-23607\bin\ffmpeg.exe" #################### #### CODE BELOW #### #################### tag_list = [ "Author" , "Title" , "UserRating" , "UserServiceRating" , "WM/AlbumArtist" , "WM/AlbumTitle" , "WM/Category" , "WM/Composer" , "WM/Conductor" , "WM/ContentDistributor" , "WM/ContentGroupDescription" , "WM/EncodingTime" , "WM/Genre" , "WM/GenreID" , "WM/InitialKey" , "WM/Language" , "WM/Lyrics" , "WM/MCDI" , "WM/MediaClassPrimaryID" , "WM/MediaClassSecondaryID" , "WM/Mood" , "WM/ParentalRating" , "WM/Period" , "WM/ProtectionType" , "WM/Provider" , "WM/ProviderRating" , "WM/ProviderStyle" , "WM/Publisher" , "WM/SubscriptionContentID" , "WM/SubTitle" , "WM/TrackNumber" , "WM/UniqueFileIdentifier" , "WM/WMCollectionGroupID" , "WM/WMCollectionID" , "WM/WMContentID" , "WM/Writer" , "WM/Year" ] from win32com.client.gencache import EnsureDispatch from os.path import basename, splitext, exists from os import sep, makedirs from subprocess import call from urlparse import urlparse from logging import StreamHandler, Formatter, DEBUG, INFO, getLogger log = getLogger( "Foobar.MP3PlayerSync" ) log.setLevel(DEBUG) lh = StreamHandler() lh.setFormatter(Formatter( "%(levelname)s|%(asctime)s|%(filename)s:%(lineno)d|%(message)s" )) log.addHandler(lh) log.info( "Connecting to foobar2000 COM server..." ) prog_id = "Foobar2000.Application.0.7" fb2k = EnsureDispatch(prog_id) def main(): fb2k_playlists = [ i for i in fb2k.Playlists if i.Name in playlists ] if fb2k_playlists: for pl in fb2k_playlists: sync_playlist(pl) log.info( "Completed Sync" ) def sync_playlist(sync_playlist): log.info( "Syncing playlist '%s'..." % sync_playlist.Name) tracks = sync_playlist.GetTracks() m3u_lines = [ "#EXTM3U" ] for t in tracks: m3u_lines.append(t.FormatTitle( "#EXTINF:%length_seconds%, %artist% - %title%" )) source_path = urlparse(t.Path).netloc m3u_lines.append(sync_file(source_path)) create_m3u(sync_playlist.Name, m3u_lines) def sync_file(source_path): parts_all = source_path.split(sep) parts = parts_all[ - path_depth:] filenameext = parts[path_depth - 1 ] (filename, ext) = splitext(filenameext) parts_new_path = [destination_root] parts_new_path.extend(parts[ 0 :path_depth - 1 ]) destination_folder = sep.join(parts_new_path) parts_new_path.append(filename + destination_ext) destination_path = sep.join(parts_new_path) if not exists(destination_folder): log.info( "Creating folder: '%s'..." % destination_folder) makedirs(destination_folder) if not exists(destination_path): convert_file(source_path, destination_path) return destination_path # For my purposes I needed to convert my WMA files (without DRM!) to MP3 so # my Nexus could understand them. You could skip this bit if your source and # destination codecs are the same on your devices. # def convert_file(input_file, output_file): log.info( "Synching: '%s' -> '%s'" % (input_file, output_file)) command = """"%s" -i "%s" -ac 2 -ar 22050 -ab 192k "%s" """ % (ffmpeg_path, input_file, output_file) log.debug( "Converter command line: '%s'" % command) try : retcode = call(command, shell = False ) except OSError, e: log.critical( "Converter execution failed: " , e) log.info( "Copying media tags over.." ) wmp = EnsureDispatch( "WMPlayer.OCX" ) if_m = wmp.newMedia(input_file) of_m = wmp.newMedia(output_file) for tag in tag_list: if not of_m.isReadOnlyItem(tag) and if_m.getItemInfo(tag) ! = "": of_m.setItemInfo(tag, if_m.getItemInfo(tag)) def create_m3u(playlist_name, m3u_lines): if not exists(playlist_root): log.info( "Creating folder: '%s'..." % playlist_root) makedirs(playlist_root) m3u_path = "%s\\%s.m3u" % (playlist_root, playlist_name) log.info( "Creating m3u playlist: '%s'..." % m3u_path) f = open (m3u_path, "w+" ) f.write( "\n" .join(m3u_lines)) f.close() if __name__ = = "__main__" : main() < / http:> |
Comments
Quite amazed that such a thing doesn't exist yet so I'll give your script a go...
Cheers!
http://pastebin.com/9aseWXSQ
Requirements will be same as above with a few additional things such as neroaacenc etc. all should be specified in the global variables.
Convert command used to process images is part of ImageMagick (http://www.google.co.nz/url?sa=t&rct=j&q=imagemagik&source=web&cd=1&ved=0CDQQFjAA&url=http%3A%2F%2Fwww.imagemagick.org%2F&ei=sf8LT-6bN8m1iQeQsYzzBQ&usg=AFQjCNEj86ZXrN6Iqx9rZ73Ad4L4ypmDtQ&sig2=5Jlv2oYmHzmw-iroj2nlrg) which should be in your path if installed correctly.
The specific changes I made were:
Changed script to take no action when expected files already existed. Also will create output filenames based on artist and track metadata. Not tested with path_depth set to anything other than 1.
Changed ffmpeg command to pipe through to neroaac to make m4a files rather than mp3s.
From artist and album info download album art with AlbumArtDownloader automatically if albumart file does not exist already. Use convert command to strip EXIF data and re-size to max resolution of 720px (Galaxy Nexus).
Found WMPlayer.OCX was unreliable to write metadata to m4a files, so using neroaactag to set metadata and albumart data in m4a file.
Obviously specific parameters can be edited in the commands called e.g -q6 can be lowered in neroaac command if lower bitrates are desired.
All provided as is where is, but is useful for me.