在Banshee批量出口/嵌入专辑封面

我在Banshee有一个结构合理的音乐库。 我以前只使用文件夹多年,所以我一直很擅长维护严格的文件系统。 我说这不是为了吹嘘(毕竟这确实浪费了我很多时间)但是要解释我的终结游戏应该是可能的。

直到Banshee,我从来没有真正对专辑艺术有任何用处,所以当我开始使用它时,我用它的Album Art Finder(辛苦地)浏览了所有8000多张专辑。 我的理解是,Banshee将这些文件放在一个缓存目录中,并附加了一个无意义的名称。

我最近搬进了Squeezebox的世界。 它真棒,但我在查看现有专辑封面时遇到了问题,因为Banshee将其锁定在自己的目录中,而不是将其放在“正确”的位置。

所以我正在寻找两种解决方案中的一种,将Banshee的数据库解析为:

  1. 首选:将艺术文件复制为/artist/album/cover.jpg服务器将理解这一点)。
  2. 将艺术嵌入到每个MP3 / FLAC / OGG /等中(这需要所有格式支持blob元数据)

编辑:刚刚找到~/.cache/media-art所有艺术~/.cache/media-art ,其名称如album-f952aa94b80de0b31b8979d70d5605e2.jpg ,我怀疑。

如果有一个很好的方式将“ f952aa94b80de0b31b8979d70d5605e2 ”与艺术家联系起来,那就是我真正想要的。

基于Oli脚本中的MD5查找(谢谢!),我编写了一个Python脚本,使用eyeD3模块查找MP3,从Banshee的缓存中查找专辑图片,并将图稿嵌入到MP3中。 它会跳过已嵌入图稿的所有文件。

它并不完美,但它可以处理大约90%的MP3,你可以使用EasyTag手动处理任何exception。 目前,脚本期望MP3是目标目录(音乐根/艺术家/专辑)的两个目录级别。 该脚本在完成报告后会打印报告,突出显示无法处理的文件或无法找到图稿的文件。

显然你需要安装Python和eyeD3模块才能使用它:

 #! /usr/bin/env python import os, sys, glob, eyeD3, hashlib CACHE_FILE_PREFIX = os.getenv("HOME") + "/.cache/media-art/album-" def embedAlbumArt(dir = "."): artworkNotFoundFiles = [] errorEmbeddingFiles = [] noMetadataFiles = [] mp3s = findMP3Files(dir) for mp3 in mp3s: print "Processing %s" % mp3 tag = eyeD3.Tag() hasMetadata = tag.link(mp3) if not hasMetadata: print "No Metadata - skipping." noMetadataFiles.append(mp3) continue if hasEmbeddedArtwork(tag): print "Artwork already embedded - skipping." continue artworkFilename = findAlbumArtworkFile(tag) if not artworkFilename: print "Couldn't find artwork file - skipping." artworkNotFoundFiles.append(mp3) continue print "Found artwork file: %s" % (artworkFilename) wasEmbedded = embedArtwork(tag, artworkFilename) if wasEmbedded: print "Done.\n" else: print "Failed to embed.\n" errorEmbeddingFiles.append(mp3) if artworkNotFoundFiles: print "\nArtwork not found for:\n" print "\n".join(artworkNotFoundFiles) if errorEmbeddingFiles: print "\nError embedding artwork in:\n" print "\n".join(errorEmbeddingFiles) if noMetadataFiles: print "\nNo Metadata found for files:\n" print "\n".join(noMetadataFiles) def findMP3Files(dir = "."): pattern = "/".join([dir, "*/*", "*.mp3"]) mp3s = glob.glob(pattern) mp3s.sort() return mp3s def hasEmbeddedArtwork(tag): return len(tag.getImages()) def findAlbumArtworkFile(tag): key = "%s\t%s" % (tag.getArtist(), tag.getAlbum()) md5 = getMD5Hash(key) filename = CACHE_FILE_PREFIX + md5 + ".jpg" if os.path.exists(filename): return filename else: return 0 def getMD5Hash(string): string = string.encode("utf-8") md5 = hashlib.md5() md5.update(string) return md5.hexdigest() def embedArtwork(tag, artworkFilename): tag.addImage(eyeD3.ImageFrame.FRONT_COVER, artworkFilename) success = 0 try: success = tag.update() except: success = 0 return success if __name__ == "__main__": if len(sys.argv) == 1: print "Usage: %s path" % (sys.argv[0]) else: embedAlbumArt(sys.argv[1]) 

我写了这个跟随Banshee所做的小脚本( 与正确的规格略有不同)。

简而言之,这将循环我的音乐目录,并根据艺术家和专辑(来自目录名称)形成一个散列,查找具有该散列的文件,如果存在,则将其复制到专辑的目录中。 简单。

 #!/bin/bash TPATH="/home/oli/.cache/media-art/" cd /media/ned/music/ for f in *; do cd "$f" for al in *; do THUMB="${TPATH}album-$(echo -ne "$f\t$al" | md5sum | cut -b1-32).jpg" if [ -e $THUMB ]; then cp $THUMB ./cover.jpg echo "/media/ned/music/$f/$al/cover.jpg" >> ~/coverlog fi done cd .. done 

~/coverlog的回~/coverlog就是捕获文件被复制到的位置(如果出现问题,你需要删除所写的所有封面文件。

为了确保我找到了所有专辑,我需要在散列之前将字符串规范化为NFKD。 我在python中解决了它:

 def strip_accents(s): return unicodedata.normalize('NFKD', s) 

我的整个脚本基于alphaloop的解决方案,但我切换到mutagen也处理flac和m4a:

 def getArtistAlbum(musicfile): """ return artist and album strings of a music file """ import mutagen # key of stored information per file extension keys={'flac': ('artist','album'), 'mp3': ('TPE2','TALB'), 'm4a': ('\xa9ART','\xa9alb')} # read the tag tag = mutagen.File(musicfile) # get extension of musicfile ext = os.path.splitext(musicfile)[1][1:] try: return tag[keys[ext][0]][0], tag[keys[ext][1]][0] except KeyError: return None,None 

我已经使用了alphaloop的脚本,它工作正常,但它只适用于MP3,我的音乐库主要是FLAC和OGG,所以我编写了一个小的Java命令行工具来迁移所有封面,无论文件类型如何。

你可以在这里找到它: BansheeArtworkWriter

在我的2.7k文件音乐库中大约花了11分钟,它迁移了所有的封面,按照GitHub自述文件中的说明操作,任何人都可以轻松运行它。

希望它可以帮助别人。