def get_artist_from_id3(id3): album_artist_names=id3.getall('TPE2') album_artist_names2=id3.getall('TPE1') lead_artist = '' contributing_artist = '' # import pdb; pdb.set_trace(); try: lead_artist = album_artist_names[0].text except: pass if lead_artist: return lead_artist[0].encode('ascii','ignore') try: contributing_artist = album_artist_names2[0].text except: pass if contributing_artist: return contributing_artist[0].encode('ascii','ignore') else: return ''
def get_artist_from_id3(id3): album_artist_names = id3.getall('TPE2') album_artist_names2 = id3.getall('TPE1') lead_artist = '' contributing_artist = '' # import pdb; pdb.set_trace(); try: lead_artist = album_artist_names[0].text except: pass if lead_artist: return lead_artist[0].encode('ascii', 'ignore') try: contributing_artist = album_artist_names2[0].text except: pass if contributing_artist: return contributing_artist[0].encode('ascii', 'ignore') else: return ''
def read_from_id3(id3): """ Reads replaygain/mp3gain headers from ID3v2 tag. :param id3: `mutagen.id3.ID3` to read :rtype: dictionary """ rg = {} tags = [] for t in _stringtags: tags.append(t.lower()) tags.append(t.upper()) for tagname in tags: matches = id3.getall('TXXX:' + tagname) if len(matches) > 0: rg[tagname.upper()] = matches[0].text[0] tags = [] for t in _floattags: tags.append(t.lower()) tags.append(t.upper()) for tagname in _floattags: matches = id3.getall('TXXX:' + tagname) if len(matches) > 0: rg[tagname.upper()] = float(matches[0].text[0].split(' ' )[0]) return rg
def test_update_to_v23_on_load(self): self.audio.add(TSOT(text=["Ha"], encoding=3)) self.audio.save() # update_to_v23 called id3 = ID3(self.filename, v2_version=3) self.assertFalse(id3.getall("TSOT")) # update_to_v23 not called id3 = ID3(self.filename, v2_version=3, translate=False) self.assertTrue(id3.getall("TSOT"))
def test_update_to_v23_on_load(self): audio = ID3(self.filename) audio.add(TSOT(text=["Ha"], encoding=3)) audio.save() # update_to_v23 called id3 = ID3(self.filename, v2_version=3) self.assertFalse(id3.getall("TSOT")) # update_to_v23 not called id3 = ID3(self.filename, v2_version=3, translate=False) self.assertTrue(id3.getall("TSOT"))
def test_text_duplicate_frame_different_encoding(self): id3 = ID3Tags() frame = TPE2(encoding=Encoding.LATIN1, text=[u"foo"]) id3._add(frame, False) assert id3.getall("TPE2")[0].encoding == Encoding.LATIN1 frame = TPE2(encoding=Encoding.LATIN1, text=[u"bar"]) id3._add(frame, False) assert id3.getall("TPE2")[0].encoding == Encoding.LATIN1 frame = TPE2(encoding=Encoding.UTF8, text=[u"baz\u0400"]) id3._add(frame, False) assert id3.getall("TPE2")[0].encoding == Encoding.UTF8 frames = id3.getall("TPE2") assert len(frames) == 1 assert len(frames[0].text) == 3
def found_embedded(self, file): try: id3 = mutagen.id3.ID3(file) if 'APIC:' in id3: #print id3 found = self.save(id3.getall('APIC:')[0].data) else: print "MP3 file without art embedded" found = False except mutagen.id3.ID3NoHeaderError: try: flac = mutagen.flac.FLAC(file) found= self.save(flac.pictures[0].data) except: #mutagen.flac.FLACNoHeaderError: try: mp4 = mutagen.mp4.MP4(file) if 'covr' in mp4: print mp4 found= self.save(mp4['covr'][0]) else: print "M4A file without art embedded" found = False except Exception, e: print "No embedded artwork found in mp3, flac or mp4 %s" % str(e) found = False
def get_file_info(mp3: pathlib.Path): info = {'name': mp3.name} audio = mutagen.mp3.MP3(str(mp3)) info['duration'] = duration_string(int(audio.info.length)) info['size'] = mp3.stat().st_size id3 = mutagen.id3.ID3(str(mp3)) info['title'] = id3.getall('TIT2')[0][0] return info
def test_unknown_chap(self): # add ctoc id3 = ID3(self.filename) id3.add(CTOC(element_id="foo", flags=3, child_element_ids=["ch0"], sub_frames=[TIT2(encoding=3, text=["bla"])])) id3.save() # pretend we don't know ctoc and save id3 = ID3(self.filename, known_frames={"CTOC": CTOC}) ctoc = id3.getall("CTOC")[0] self.assertFalse(ctoc.sub_frames) self.assertTrue(ctoc.sub_frames.unknown_frames) id3.save() # make sure we wrote all sub frames back id3 = ID3(self.filename) self.assertEqual( id3.getall("CTOC")[0].sub_frames.getall("TIT2")[0].text, ["bla"])
def test_chap_subframes(self): id3 = ID3() id3.version = (2, 3) id3.add(CHAP(element_id="foo", start_time=0, end_time=0, start_offset=0, end_offset=0, sub_frames=[TYER(encoding=0, text="2006")])) id3.update_to_v24() chap = id3.getall("CHAP:foo")[0] self.assertEqual(chap.sub_frames.getall("TDRC")[0], u"2006")
def test_ctoc_subframes(self): id3 = ID3() id3.version = (2, 3) id3.add(CTOC(sub_frames=[TYER(encoding=0, text="2006")])) id3.update_to_v24() ctoc = id3.getall("CTOC")[0] self.assertEqual(ctoc.sub_frames.getall("TDRC")[0], u"2006") self.assertFalse(ctoc.sub_frames.getall("TYER")) id3.update_to_v23() self.assertEqual(ctoc.sub_frames.getall("TYER")[0], u"2006")
def test_PIC_in_23(self): filename = get_temp_empty(".mp3") try: with open(filename, "wb") as h: # contains a bad upgraded frame, 2.3 structure with 2.2 name. # PIC was upgraded to APIC, but mime was not h.write(b"ID3\x03\x00\x00\x00\x00\x08\x00PIC\x00\x00\x00" b"\x00\x0b\x00\x00\x00JPG\x00\x03foo\x00\x42" b"\x00" * 100) id3 = ID3(filename) self.assertEqual(id3.version, (2, 3, 0)) self.assertTrue(id3.getall("APIC")) frame = id3.getall("APIC")[0] self.assertEqual(frame.mime, "image/jpeg") self.assertEqual(frame.data, b"\x42") self.assertEqual(frame.type, 3) self.assertEqual(frame.desc, "foo") finally: os.remove(filename)
def get_rating(id3): ratings = id3.getall('POPM') if ratings: rating = ratings[0].rating if rating == 255: return 5 elif rating < 255 and rating >= 196: return 4 elif rating < 196 and rating >= 128: return 3 return 0
def test_chap_subframes(self): id3 = ID3() id3.version = (2, 3) id3.add(CHAP(element_id="foo", start_time=0, end_time=0, start_offset=0, end_offset=0, sub_frames=[TYER(encoding=0, text="2006")])) id3.update_to_v24() chap = id3.getall("CHAP:foo")[0] self.assertEqual(chap.sub_frames.getall("TDRC")[0], u"2006") self.assertFalse(chap.sub_frames.getall("TYER")) id3.update_to_v23() self.assertEqual(chap.sub_frames.getall("TYER")[0], u"2006")
def file_tags_extract(path): import mutagen.id3 import mutagen.flac import mutagen.mp4 global G_COVER_FILE dir_www = "/data/data/pl.sviete.dom/files/home/AIS/www/" dir_name = os.path.basename(os.path.dirname(path)).replace(" ", "") ret_path = "/local/" + dir_name + "_cover.jpg" f_length = 0 # file info try: fi = mutagen.File(path) f_length = str(fi.info.length) except Exception as e: _LOGGER.error("Error " + str(e)) if G_COVER_FILE == dir_www + dir_name + "_cover.jpg": return ret_path, f_length # remove all .jpg jpgs = os.listdir(dir_www) for jpg in jpgs: if jpg.endswith("_cover.jpg"): os.remove(os.path.join(dir_www, jpg)) # generate the cover G_COVER_FILE = dir_www + dir_name + "_cover.jpg" try: id3 = mutagen.id3.ID3(path) open(G_COVER_FILE, "wb").write(id3.getall("APIC")[0].data) except mutagen.id3.ID3NoHeaderError: try: flac = mutagen.flac.FLAC(path) open(G_COVER_FILE, "wb").write(flac.pictures[0].data) except mutagen.flac.FLACNoHeaderError: try: mp4 = mutagen.mp4.MP4(path) open(G_COVER_FILE, "wb").write(mp4["covr"][0]) except Exception as e: _LOGGER.error("Error " + str(e)) return ret_path, f_length
#!/usr/bin/env python import sys import mutagen.id3 import mutagen.flac import mutagen.mp4 try: id3 = mutagen.id3.ID3(sys.argv[1]) open('/home/barosl/test.jpg', 'wb').write(id3.getall('APIC')[0].data) except mutagen.id3.ID3NoHeaderError: try: flac = mutagen.flac.FLAC(sys.argv[1]) open('/home/barosl/test.jpg', 'wb').write(flac.pictures[0].data) except mutagen.flac.FLACNoHeaderError: mp4 = mutagen.mp4.MP4(sys.argv[1]) open('/home/barosl/test.jpg', 'wb').write(mp4['covr'][0])
def _set_thumbnail(self, file, user_name): """ Generate thumbnail """ # Generate thumbnail for image get_summary_id_sql = "SELECT id,type,nas_path FROM summary WHERE nickname=\"" get_summary_id_sql += file get_summary_id_sql += "\";" self._send_sql_cmd(get_summary_id_sql) if self._cursor.rowcount > 0: result = self._cursor.fetchall() for row in result: # row[1] = user summary_id = row[0] file_type = row[1] nas_path = row[2] self._database.commit() if file_type == 'image': ######## face classify self.face_classify(nas_path, file, user_name) full_path = os.path.join(nas_path, file) image = Image.open(full_path) # prevent rotation try: hasOrientation = False for orientation in ExifTags.TAGS.keys(): if ExifTags.TAGS[orientation] == 'Orientation': hasOrientation = True break if hasOrientation: try: exif = image._getexif() except Exception: exif = None if exif: if exif[orientation] == 3: image = image.rotate(180, expand=True) elif exif[orientation] == 6: image = image.rotate(270, expand=True) elif exif[orientation] == 8: image = image.rotate(90, expand=True) except (AttributeError, KeyError, IndexError): # cases: image don't have getexif pass image.thumbnail((256, 256)) save_str = self._thumbnail_path + "/" save_str += user_name # check dir if not os.path.isdir(save_str): os.mkdir(save_str) save_str += "/" save_str += str(summary_id) save_str += ".jpg" image.save(save_str) image.close() if file_type == 'video': full_path = os.path.join(nas_path, file) tmp_file_path = nas_path + '/' tmp_file_path += 'video_tmp.jpg' video_thumbnail_cmd = 'ffmpeg -i ' video_thumbnail_cmd += full_path video_thumbnail_cmd += ' -ss 00:00:00 -vframes 1 ' video_thumbnail_cmd += tmp_file_path p2 = subprocess.Popen([video_thumbnail_cmd, '-p'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # make sure generate while self._check_img_ready(tmp_file_path): pass # do nothing image = Image.open(tmp_file_path) image.thumbnail((256, 256)) save_str = self._thumbnail_path + "/" save_str += user_name # check dir if not os.path.isdir(save_str): os.mkdir(save_str) save_str += "/" save_str += str(summary_id) save_str += ".jpg" image.save(save_str) # delete tmp img try: os.remove(tmp_file_path) except: pass if file_type == 'music': full_path = os.path.join(nas_path, file) save_str = self._thumbnail_path + "/" save_str += user_name # check dir if not os.path.isdir(save_str): os.mkdir(save_str) save_str += "/" save_str += str(summary_id) save_str += ".jpg" no_cover_flag = 0 try: id3 = mutagen.id3.ID3(full_path) open(save_str, 'wb').write(id3.getall('APIC')[0].data) except mutagen.id3.ID3NoHeaderError: try: flac = mutagen.flac.FLAC(full_path) open(save_str, 'wb').write(flac.pictures[0].data) except mutagen.flac.FLACNoHeaderError: try: mp4 = mutagen.mp4.MP4(full_path) open(save_str, 'wb').write(mp4['covr'][0]) except: no_cover_flag = 1 if no_cover_flag == 1: # copy image = Image.open('database/album_art_empty.png') save_str = self._thumbnail_path + "/" save_str += user_name # check dir if not os.path.isdir(save_str): os.mkdir(save_str) save_str += "/" save_str += str(summary_id) save_str += ".jpg" image.save(save_str) # delete tmp img try: os.remove(tmp_file_path) except: pass else: pass
#!/usr/bin/env python import sys import mutagen.id3 import mutagen.flac import mutagen.mp4 try: id3 = mutagen.id3.ID3(sys.argv[1]) open('/home/barosl/test.jpg', 'wb').write(id3.getall('APIC')[0].data) except mutagen.id3.ID3NoHeaderError: try: flac = mutagen.flac.FLAC(sys.argv[1]) open('/home/barosl/test.jpg', 'wb').write(flac.pictures[0].data) except mutagen.flac.FLACNoHeaderError: mp4 = mutagen.mp4.MP4(sys.argv[1]) open('/home/barosl/test.jpg','wb').write(mp4['covr'][0])
def test_lnk(self): id3 = ID3() id3.version = (2, 2) id3.add(LNK(frameid="PIC", url="http://foo.bar")) id3.update_to_v24() self.assertTrue(id3.getall("LINK"))
def test_time_dropped(self): id3 = ID3() id3.version = (2, 3) id3.add(TIME(encoding=0, text=["1155"])) id3.update_to_v24() self.assertFalse(id3.getall("TIME"))
def add_to_id3(rg, id3): """ Adds/updates replaygain/mp3gain headers in ID3v2 tag, returns the number of updated tags. :param id3: `mutagen.id3.ID3` to read :rtype: int """ old_rg = read_from_id3(id3) updated = 0 # for tagname in _floattags + _stringtags: # id3.delall('TXXX:' + tagname) for tagname in rg.keys(): if tagname not in old_rg or old_rg[tagname] != rg[tagname] \ or len(id3.getall('TXXX:' + tagname.lower())): updated += 1 id3.delall('TXXX:' + tagname.upper()) id3.delall('TXXX:' + tagname.lower()) frame = mutagen.id3.Frames['TXXX'](encoding=3, desc=tagname, text=str(rg[tagname])) id3.loaded_frame(frame) for tagname in old_rg.keys(): if tagname not in rg.keys(): updated += 1 id3.delall('TXXX:' + tagname.upper()) id3.delall('TXXX:' + tagname.lower()) for tagname in _stringtags + _floattags: matches = id3.getall('TXXX:' + tagname.lower()) if len(matches) > 0: updated += 1 id3.delall('TXXX:' + tagname.lower()) frame = mutagen.id3.Frames['TXXX'](encoding=3, desc=tagname, text=matches[0].text) id3.loaded_frame(frame) rva2_tags = id3.getall('RVA2') for gtype in ['album', 'track']: gain_tag = 'REPLAYGAIN_' + gtype.upper() + '_GAIN' peak_tag = 'REPLAYGAIN_' + gtype.upper() + '_PEAK' if gain_tag in rg: rva2 = None for r in rva2_tags: if r.desc == gtype and r.channel == 1: rva2 = r try: rva2_tags.remove(r) except: pass break if not rva2: rva2 = mutagen.id3.Frames['RVA2'](channel=1, desc=gtype) peak = None gain = float(rg[gain_tag]) if peak_tag in rg: peak = float(rg[peak_tag]) rva2.gain = gain rva2.peak = peak rva2_tags.append(rva2) id3.delall('RVA2') for r in rva2_tags: id3.loaded_frame(r) return updated
def test_rvad_dropped(self): id3 = ID3() id3.version = (2, 3) id3.add(RVAD()) id3.update_to_v24() self.assertFalse(id3.getall("RVAD"))
def encode_to_png(data, cover=None, font=None): data_size = len(data) header_s = struct.pack('<i', data_size) new_data = header_s + data + '\0'*(-len(data) % 3) px_cnt = ((len(new_data) + 2) / 3) * 2 w = int(math.sqrt(px_cnt)) w += -w % 2 h = (px_cnt + w - 1) / w img = Image.new('RGBA', (w, h)) buf = img.load() try: fp = tempfile.NamedTemporaryFile(delete=False) fp.write(data) fp.close() if not cover: id3 = mutagen.id3.ID3(fp.name) cover_data = id3.getall('APIC')[0].data cover = Image.open(StringIO(cover_data)) lyrics_data = os.popen('./alsong-lyrics %s' % fp.name).read() finally: try: os.remove(fp.name) except OSError: pass new_cover = cover.resize((w, h), Image.BILINEAR) new_cover_buf = new_cover.load() if lyrics_data and font: font_h = 30 draw = ImageDraw.Draw(new_cover) font_o = ImageFont.truetype(font, font_h) spaced = True x, y = 50, 50 for line in lyrics_data.decode('utf-8', 'replace').splitlines(): try: line = line[line.index(']')+1:].strip() if not line: raise RuntimeError spaced = False except: if spaced: continue spaced = True line = '' draw.text((x, y), line, font=font_o, fill='#0000ff') y += font_h + font_h/2 if y + font_h > h: x = 50 + w/2 y = 50 data_pos = 0 for j in xrange(h): for i in xrange(w): if i % 2 == 0: if i == 0 and j == 0: px = tuple(ord(x) for x in new_data[data_pos:data_pos+4]) data_pos += 4 else: px = new_cover_buf[i, j] else: px = tuple(ord(x) for x in new_data[data_pos:data_pos+3]+'\xFF') data_pos += 3 if len(px) == 1: px = (0, 0, 0, 0) else: assert len(px) == 4 buf[i, j] = px out = StringIO() img.save(out, format='PNG') return out.getvalue()
def website_get(id3, key): urls = [frame.url for frame in id3.getall("WOAR")] if urls: return urls else: raise EasyID3KeyError(key)
def peakgain_list(id3, key): keys = [] for frame in id3.getall("RVA2"): keys.append("replaygain_%s_gain" % frame.desc) keys.append("replaygain_%s_peak" % frame.desc) return keys
def encode_to_png(data, cover=None, font=None): data_size = len(data) header_s = struct.pack('<i', data_size) new_data = header_s + data + '\0' * (-len(data) % 3) px_cnt = ((len(new_data) + 2) / 3) * 2 w = int(math.sqrt(px_cnt)) w += -w % 2 h = (px_cnt + w - 1) / w img = Image.new('RGBA', (w, h)) buf = img.load() try: fp = tempfile.NamedTemporaryFile(delete=False) fp.write(data) fp.close() if not cover: id3 = mutagen.id3.ID3(fp.name) cover_data = id3.getall('APIC')[0].data cover = Image.open(StringIO(cover_data)) lyrics_data = os.popen('./alsong-lyrics %s' % fp.name).read() finally: try: os.remove(fp.name) except OSError: pass new_cover = cover.resize((w, h), Image.BILINEAR) new_cover_buf = new_cover.load() if lyrics_data and font: font_h = 30 draw = ImageDraw.Draw(new_cover) font_o = ImageFont.truetype(font, font_h) spaced = True x, y = 50, 50 for line in lyrics_data.decode('utf-8', 'replace').splitlines(): try: line = line[line.index(']') + 1:].strip() if not line: raise RuntimeError spaced = False except: if spaced: continue spaced = True line = '' draw.text((x, y), line, font=font_o, fill='#0000ff') y += font_h + font_h / 2 if y + font_h > h: x = 50 + w / 2 y = 50 data_pos = 0 for j in xrange(h): for i in xrange(w): if i % 2 == 0: if i == 0 and j == 0: px = tuple(ord(x) for x in new_data[data_pos:data_pos + 4]) data_pos += 4 else: px = new_cover_buf[i, j] else: px = tuple( ord(x) for x in new_data[data_pos:data_pos + 3] + '\xFF') data_pos += 3 if len(px) == 1: px = (0, 0, 0, 0) else: assert len(px) == 4 buf[i, j] = px out = StringIO() img.save(out, format='PNG') return out.getvalue()
def url_frame_get(frameid, id3, key): urls = [frame.url for frame in id3.getall(frameid)] if urls: return urls else: raise EasyID3KeyError(key)