Skip to content

Instantly share code, notes, and snippets.

@philopon
Created December 24, 2013 17:39
Show Gist options
  • Save philopon/8116068 to your computer and use it in GitHub Desktop.
Save philopon/8116068 to your computer and use it in GitHub Desktop.
ローカルの音楽ファイルのアートワークをGoogle Play Musicに設定するやつ
#!/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()
@philopon
Copy link
Author

とりあえずmp3(ID3タグ)、m4a(Mpeg4タグ)だけ対応
アルバムアーティスト、アーティスト、タイトル、トラック名から設定されているものでマッチングする

  1. 依存パッケージ入れる
    $ pip install mutagen pathlib gmusicapi
  2. 設定書き換える
    MUSIC_DIR, GOOGLE_ID, GOOGLE_PASSWORDを書き換える
  3. データベース作成
    $ python playCoverUpload.py CREATEDB
  4. アップロード
    $ python playCoverUpload.py UPLOAD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment