1

我正在尝试为 Plex 编辑 LastFM 音乐插件,以使其与音乐视频一起使用。我几乎在那里,有很多谷歌搜索和一些问题,但我坚持艺术家似乎聚集在一起的事实。

我的视频采用“艺术家 - Title.ext”格式,我已将其设置为元数据标题,但它似乎仍然分组。

即使我在将视频分组后拆分为 Plex,它们都具有第一个视频的名称。

我不确定这是否是正确的地方,但这里是代码。如果有人可以提供帮助,将不胜感激。

    import lastfm, re, time, os, urllib

GOOGLE_JSON = 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&userip=%s&rsz=large&q=%s+site:last.fm+inurl:music'

def Start():
  HTTP.CacheTime = CACHE_1WEEK

def GetPublicIP():
  return HTTP.Request('http://plexapp.com/ip.php').content.strip()

def GetGoogleArtist(artist):
  try:
    url = GOOGLE_JSON % (GetPublicIP(), String.Quote(artist.encode('utf-8'), usePlus=True))
    jsonObj = JSON.ObjectFromURL(url, headers={'Referer' : 'http://www.plexapp.com'}, sleep=0.5)
    if jsonObj['responseData'] != None:
      jsonObj = jsonObj['responseData']['results']
      if len(jsonObj) > 0:
        result = jsonObj[0]
        url = result['unescapedUrl'].replace('+','%20')
        return re.findall('/music/([^/]+)', url)[0]
  except:
    pass

  return None

def CallWithRetries(fun, *args):
  tries = 10
  while tries > 0:
    try:
      return fun(*args)
    except:
      tries = tries - 1
      if tries > 0:
        Log('Call failed, retrying')
        time.sleep(2)
      else:
        raise

class LastFmAgent(Agent.Movies, Agent.Artist):
  name = 'Music Video'
  languages = [Locale.Language.English, Locale.Language.Korean]

  def safe_strip(self, ss):
    """
      This method strips the diacritic marks from a string, but if it's too extreme (i.e. would remove everything,
      as is the case with some foreign text), then don't perform the strip.
    """
    s = String.StripDiacritics(ss)
    if len(s.strip()) == 0:
      return ss
    return s

  def search(self, results, media, lang):

    path = media.filename
    path = urllib.unquote(path)
    filename = os.path.splitext(os.path.basename(path))[0]
    Log(filename)
    artist = filename.split(' - ')[0]
    artist = artist.lower()
    Log(artist)


    Log("Search for artist")
    CallWithRetries(self.findArtists, lang, results, media, artist)

    Log("If the artist starts with 'The', try stripping.")
    if artist.startswith('the '):
      try: CallWithRetries(self.findArtists, lang, results, media, artist[4:])
      except: pass

    Log("If the artist has an '&', try with 'and'.")
    if artist.find(' & ') != -1:
      try: CallWithRetries(self.findArtists, lang, results, media, artist.replace(' & ', ' and '))
      except: pass

    Log("If the artist has an 'and', try with '&'.")
    if artist.find(' and ') != -1:
      try: CallWithRetries(self.findArtists, lang, results, media, artist.replace(' and ', ' & '))
      except: pass

    try: highest_score = max([x.score for x in results])
    except: highest_score = 0

    if len(results) == 0 or highest_score < 85:
      artist_id = GetGoogleArtist(artist)
      google_artist = CallWithRetries(lastfm.ArtistInfo, artist_id)
      if google_artist:
        (url, name, image, listeners) = google_artist
        Log("Google said 'you should try %s' (ID: %s)." % (name, artist_id))
        if listeners > 250:
          results.Append(MetadataSearchResult(id=artist_id, name=name, thumb=image, lang=lang, score = 100-Util.LevenshteinDistance(name.lower(), artist.lower())))

    Log("Finally, de-dupe the results.")
    toWhack = []
    resultMap = {}
    for result in results:
      if not resultMap.has_key(result.id):
        resultMap[result.id] = True
      else:
        toWhack.append(result)
    for dupe in toWhack:
      results.Remove(dupe)

  def findArtists(self, lang, results, media, artist):
    score = 90
    for r in lastfm.SearchArtists(artist,limit=5)[0]:
      id = r[0]
      Log(id)

      # Skip artists without many listeners, they're probanly wrong.
      if r[3] < 1000 and id.find('+noredirect') == -1:
        Log("Skipping %s with only %d listeners." % (r[1], r[3]))
        continue

      if id.find('+noredirect') == -1:
        id = r[1]
        dist = Util.LevenshteinDistance(r[1].lower(), artist.lower())
        albumBonus = self.bonusArtistMatchUsingAlbums(media, artistID=id, maxBonus=5)
        id = String.Quote(id.encode('utf-8'))
        Log('artist: ' + artist + ' albumBonus: ' + str(albumBonus))
        Log('Artist result: ' + r[1] + ' id: ' + id + ' score: ' + str(score) + ' thumb: ' + str(r[2]))
        results.Append(MetadataSearchResult(id = id.replace('%2B','%20'), name = r[1], thumb = r[2], lang  = lang, score = score + albumBonus - dist))
      else:
        # Get a correction.
        Log('Getting correction to artist.')
        correctArtists = lastfm.CorrectedArtists(artist)
        for result in correctArtists:
          id = String.Quote(result[0].encode('utf-8'))
          dist = Util.LevenshteinDistance(result[0].lower(), artist.lower())
          results.Append(MetadataSearchResult(id = id.replace('%2B','%20'), name = result[0], lang  = lang, score = score - dist + 5))

      score = score - 2

  def bonusArtistMatchUsingAlbums(self, media, artistID, maxBonus=5):
    Log('bonusArtistMatchUsingAlbums')
    lastFM_artistAlbums = []
    for album in lastfm.ArtistAlbums(artistID):
      (name, artist, thumb, url) = album
      lastFM_artistAlbums.append(name.lower())
    if len(lastFM_artistAlbums) == 0: return 0 #no last.fm albums for the artist, so abort!
    bonus = 0
    for a in media.children:
      album = a.title.lower()
      for lfa in lastFM_artistAlbums:
        score = Util.LevenshteinDistance(lfa, album)
        #Log(lfa, album, score)
        if score <= 2: #pretty solid match
          bonus += 1
          if bonus == maxBonus: break
      if bonus == 0 and album[-1:] == ')': #if we got nothing, let's try again without anything in paranthesis [e.g.'limited edition'] 
        album = album[:album.rfind('(')].strip()
        for lfa in lastFM_artistAlbums:
          score = Util.LevenshteinDistance(lfa, album)
          #Log(lfa, album, score)
          if score <= 2: #pretty solid match
            bonus += 1
            if bonus == maxBonus: break
    return bonus

  def update(self, metadata, media, lang):
    artist = CallWithRetries(XML.ElementFromURL, lastfm.ARTIST_INFO % String.Quote(String.Unquote(metadata.id), True))[0]
    summary = artist.xpath('//bio/content')[0]
    metadata.title = String.Unquote(artist.xpath('//artist/name')[0].text, True)
    Log(metadata.title)
    filename = media.items[0].parts[0].file.decode('utf-8')
    cleanname = os.path.splitext(os.path.basename(filename))[0]
    Log(cleanname)
    metadata.title = cleanname
    Log(metadata.title)
    Log("QWERTY")
    if summary.text:
      metadata.summary = decodeXml(re.sub(r'<[^<>]+>', '', summary.text))
    try:
      url = artist.xpath('//artist/image[@size="mega"]//text()')[0]
      if url not in metadata.posters:
        metadata.posters[url] = Proxy.Media(HTTP.Request(url))
    except:
      pass     
    metadata.genres.clear()
    for genre in artist.xpath('//artist/tags/tag/name'):
      metadata.genres.add(genre.text.capitalize())

def decodeXml(text):
  trans = [('&amp;','&'),('&quot;','"'),('&lt;','<'),('&gt;','>'),('&apos;','\''),('\n ','\n')]
  for src, dst in trans:
    text = text.replace(src, dst)
  return text      
4

0 回答 0