5 Scraper for embedded lyrics
8 import sys, os, re, chardet
9 import xml.dom.minidom
as xml
10 from optparse
import OptionParser
11 from common
import utilities
13 __author__ =
"Paul Harrison and ronin"
14 __title__ =
"EmbeddedLyrics"
15 __description__ =
"Search tracks tag for embedded lyrics"
18 __syncronized__ =
True
27 utilities.log(debug,
"%s: trying %s" % (__title__,
"lyrics embed with Lyrics3/Lyrics3V2 format"))
30 f.seek(-128-9, os.SEEK_END)
32 if (buf !=
"LYRICS200" and buf !=
"LYRICSEND"):
33 f.seek(-9, os.SEEK_END)
35 if (buf ==
"LYRICSEND"):
36 """ Find Lyrics3v1 """
37 f.seek(-5100-9-11, os.SEEK_CUR)
40 start = buf.find(
"LYRICSBEGIN")
41 elif (buf ==
"LYRICS200"):
42 """ Find Lyrics3v2 """
43 f.seek(-9-6, os.SEEK_CUR)
45 f.seek(-size-6, os.SEEK_CUR)
47 if(buf ==
"LYRICSBEGIN"):
52 length = int(buf[3:8])
53 content = buf[8:8+length]
64 pos += string[pos:].
find(
'\x00\x00') + 1
68 return string.find(
'\x00')
71 mins =
"0%s" % int(ms/1000/60)
72 sec =
"0%s" % int((ms/1000)%60)
73 msec =
"0%s" % int((ms%1000)/10)
74 timestamp =
"[%s:%s.%s]" % (mins[-2:],sec[-2:],msec[-2:])
83 utilities.log(
True,
"Failed to import taglib. This grabber requires "
84 "pytaglib TagLib bindings for Python. "
85 "https://github.com/supermihi/pytaglib")
89 utilities.log(debug,
"%s: trying to open %s" % (__title__, filename))
90 f = taglib.File(filename)
94 if tag.startswith(
'LYRICS'):
104 utilities.log(debug,
"%s: trying %s" % (__title__,
"lyrics embed with ID3v2 format"))
110 utilities.log(debug,
"%s: trying %s" % (__title__,
"lyrics embed with Flac format"))
116 utilities.log(debug,
"%s: trying %s" % (__title__,
"lyrics embed with MP4 format"))
125 utilities.log(debug,
"%s: searching lyrics for %s - %s - %s" % (__title__, lyrics.artist, lyrics.album, lyrics.title))
127 filename = lyrics.filename
129 ext = os.path.splitext(filename)[1].lower()
139 enc = chardet.detect(lry)
140 lyrics.lyrics = lry.decode(enc[
'encoding'])
159 utilities.log(
True,
"Failed to import taglib. This grabber requires "
160 "pytaglib ? TagLib bindings for Python. "
161 "https://github.com/supermihi/pytaglib")
165 lyrics = utilities.Lyrics()
166 lyrics.source = __title__
167 lyrics.syncronized = __syncronized__
168 lyrics.artist =
'Robb Benson'
169 lyrics.album =
'Demo Tracks'
170 lyrics.title =
'Lone Rock'
171 lyrics.filename = os.path.dirname(os.path.abspath(__file__)) +
'/examples/taglyrics.mp3'
173 found = fetcher.get_lyrics(lyrics)
176 utilities.log(
True,
"Everything appears in order.")
180 utilities.log(
True,
"The lyrics for the test search failed!")
184 from lxml
import etree
185 xml = etree.XML(
u'<lyrics></lyrics>')
186 etree.SubElement(xml,
"artist").text = lyrics.artist
187 etree.SubElement(xml,
"album").text = lyrics.album
188 etree.SubElement(xml,
"title").text = lyrics.title
189 etree.SubElement(xml,
"syncronized").text =
'True' if __syncronized__
else 'False'
190 etree.SubElement(xml,
"grabber").text = lyrics.source
192 lines = lyrics.lyrics.splitlines()
194 etree.SubElement(xml,
"lyric").text = line
196 utilities.log(
True, utilities.convert_etree(etree.tostring(xml, encoding=
'UTF-8',
197 pretty_print=
True, xml_declaration=
True)))
201 from lxml
import etree
202 version = etree.XML(
u'<grabber></grabber>')
203 etree.SubElement(version,
"name").text = __title__
204 etree.SubElement(version,
"author").text = __author__
205 etree.SubElement(version,
"command").text =
'embedlrc.py'
206 etree.SubElement(version,
"type").text =
'lyrics'
207 etree.SubElement(version,
"description").text = __description__
208 etree.SubElement(version,
"version").text = __version__
209 etree.SubElement(version,
"priority").text = __priority__
210 etree.SubElement(version,
"syncronized").text =
'True' if __syncronized__
else 'False'
212 utilities.log(
True, utilities.convert_etree(etree.tostring(version, encoding=
'UTF-8',
213 pretty_print=
True, xml_declaration=
True)))
219 parser = OptionParser()
221 parser.add_option(
'-v',
"--version", action=
"store_true", default=
False,
222 dest=
"version", help=
"Display version and author")
223 parser.add_option(
'-t',
"--test", action=
"store_true", default=
False,
224 dest=
"test", help=
"Perform self-test for dependencies.")
225 parser.add_option(
'-s',
"--search", action=
"store_true", default=
False,
226 dest=
"search", help=
"Search for lyrics.")
227 parser.add_option(
'-a',
"--artist", metavar=
"ARTIST", default=
None,
228 dest=
"artist", help=
"Artist of track.")
229 parser.add_option(
'-b',
"--album", metavar=
"ALBUM", default=
None,
230 dest=
"album", help=
"Album of track.")
231 parser.add_option(
'-n',
"--title", metavar=
"TITLE", default=
None,
232 dest=
"title", help=
"Title of track.")
233 parser.add_option(
'-f',
"--filename", metavar=
"FILENAME", default=
None,
234 dest=
"filename", help=
"Filename of track.")
235 parser.add_option(
'-d',
'--debug', action=
"store_true", default=
False,
236 dest=
"debug", help=(
"Show debug messages"))
238 opts, args = parser.parse_args()
240 lyrics = utilities.Lyrics()
241 lyrics.source = __title__
242 lyrics.syncronized = __syncronized__
254 lyrics.artist = opts.artist
256 lyrics.album = opts.album
258 lyrics.title = opts.title
260 lyrics.filename = opts.filename
263 if fetcher.get_lyrics(lyrics):
267 utilities.log(
True,
"No lyrics found for this track")
270 if __name__ ==
'__main__':