Created
December 24, 2013 17:39
-
-
Save philopon/8116068 to your computer and use it in GitHub Desktop.
ローカルの音楽ファイルのアートワークをGoogle Play Musicに設定するやつ
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 python | |
# coding: UTF-8 | |
MUSIC_DIR = "/Full/Path/To/Music" | |
GOOGLE_ID = '[email protected]' | |
GOOGLE_PASSWORD = 'password' | |
class PictureData(object): | |
def __init__(self, album_artist, artist, album, title, data): | |
self.album_artist = album_artist | |
self.artist = artist | |
self.album = album | |
self.title = title | |
self.data = data | |
def __str__(self): | |
return ((self.album_artist or u"") + | |
u"/" + (self.artist or u"") + | |
u" - " + (self.album or u"") + | |
u" - " + (self.title or u"")).encode('utf-8') | |
def tuple(self): | |
return (self.album_artist, self.artist, self.album, self.title, self.data) | |
def query(self): | |
ret = [] | |
if self.album_artist: ret.append(self.album_artist) | |
if self.artist: ret.append(self.artist) | |
if self.album: ret.append(self.album) | |
if self.title: ret.append(self.title) | |
return tuple(ret) | |
def where(self): | |
ret = [] | |
if self.album_artist: ret.append("album_artist = ?") | |
if self.artist: ret.append("artist = ?") | |
if self.album: ret.append("album = ?") | |
if self.title: ret.append("title = ?") | |
return " AND ".join(ret) | |
def get_picture(path): | |
import mutagen.mp3 | |
import mutagen.mp4 | |
if path.suffix == ".mp3": | |
id3 = mutagen.mp3.MP3(str(path.absolute())) | |
cover = id3.get("APIC:") | |
if cover: | |
album_artist = id3.get('TPE2').text | |
artist = id3.get('TPE1').text | |
album = id3.get('TALB').text | |
title = id3.get('TIT2').text | |
cover_data = buffer(cover.data) | |
if album_artist: album_artist = album_artist[0] | |
if artist: artist = artist[0] | |
if album: album = album[0] | |
if title: title = title[0] | |
return PictureData(album_artist, artist, album, title, cover_data) | |
elif path.suffix == ".m4a": | |
mp4 = mutagen.mp4.MP4(str(path.absolute())) | |
cover = mp4.get("covr") | |
if cover: | |
album_artist = mp4.get('aART') | |
artist = mp4.get('\xa9ART') | |
album = mp4.get('\xa9alb') | |
title = mp4.get('\xa9nam') | |
cover_data = buffer(cover[0]) | |
if album_artist: album_artist = album_artist[0] | |
if artist: artist = artist[0] | |
if album: album = album[0] | |
if title: title = title[0] | |
return PictureData(album_artist, artist, album, title, cover_data) | |
return None | |
def create_database(conn): | |
import sqlite3 | |
cur = conn.cursor() | |
cur.execute("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='albums';") | |
if cur.fetchone()[0] == 0: | |
conn.execute("""CREATE TABLE albums | |
( album_artist TEXT | |
, artist TEXT | |
, album TEXT | |
, title TEXT | |
, data BLOB NOT NULL);""") | |
conn.execute("CREATE INDEX all_index ON albums(album_artist,artist,album,title)") | |
conn.execute("CREATE INDEX artist_index ON albums( artist,album,title)") | |
conn.commit() | |
cur.close() | |
def insert_album_art(conn, data): | |
import sqlite3 | |
cur = conn.cursor() | |
cur.execute("SELECT count(*) FROM albums WHERE " + data.where() + " LIMIT 1", data.query()) | |
ex = cur.fetchone() | |
cur.close() | |
if ex[0] == 0: | |
conn.execute("INSERT INTO albums VALUES (?,?,?,?,?);", data.tuple()) | |
conn.commit() | |
def insert_album_arts(conn, glob): | |
for p in glob: | |
if p.is_file(): | |
pic = get_picture(p) | |
if not pic: | |
print "NoCover:", p | |
else: insert_album_art(conn, pic) | |
if __name__ == '__main__': | |
from pathlib import * | |
import sqlite3 | |
import sys | |
def show_help(): | |
print sys.argv[0], "COMMAND" | |
print " COMMAND:" | |
print " CREATEDB" | |
print " UPLOAD" | |
if len(sys.argv) <= 1: show_help(); sys.exit(1) | |
dbfile = Path(sys.argv[0]).parent.joinpath("cover.db").absolute() | |
conn = sqlite3.connect(str(dbfile)) | |
if sys.argv[1] == "CREATEDB": | |
create_database(conn) | |
path = Path(MUSIC_DIR) | |
insert_album_arts(conn, path.rglob('*')) | |
conn.close() | |
elif sys.argv[1] == "UPLOAD": | |
from gmusicapi import Webclient | |
api = Webclient() | |
api.login(GOOGLE_ID, GOOGLE_PASSWORD) | |
for song in api.get_all_songs(): | |
if not 'albumArtUrl' in song: | |
cur = conn.cursor() | |
song = PictureData(song['albumArtist'] or None, song['artist'] or None, | |
song['album'] or None, song['title'] or None, song['id']) | |
cur.execute("SELECT data FROM albums WHERE " + song.where(), song.query()) | |
data = cur.fetchone(); cur.close() | |
if not data: | |
print "NoCover:", str(song) | |
continue | |
import tempfile | |
with tempfile.NamedTemporaryFile() as tmp: | |
tmp.write(data[0]) | |
tmp.flush() | |
api.upload_album_art(song.data, tmp.name) | |
print "Uploaded:", song | |
else: | |
show_help() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
とりあえずmp3(ID3タグ)、m4a(Mpeg4タグ)だけ対応
アルバムアーティスト、アーティスト、タイトル、トラック名から設定されているものでマッチングする
$ pip install mutagen pathlib gmusicapi
MUSIC_DIR, GOOGLE_ID, GOOGLE_PASSWORDを書き換える
$ python playCoverUpload.py CREATEDB
$ python playCoverUpload.py UPLOAD