จาก ThaiLinuxCafe: แก้ไข ID3Tags ใน mp3 ให้ใช้กับ Amarok 1.4 และ Noatun
ใช้แปลงไฟล์ mp3 จากการเข้ารหัสแบบ cp874 มาเป็นยูนิโค๊ด utf8
ตัวโปรแกรมจะแปลงชื่อไฟล์และ ID3 Tags ในไฟล์
ถ้าจะนำไปใช้ โปรดใช้ด้วยความระมัดระวัง
เพราะไม่ได้เขียนฟังก์ชั่นการเตือนไว้ด้วยครับ
ตั้งชื่อไฟล์ว่า d.tags2utf8
$ sudo touch /usr/local/bin/d.tags2utf8
$ sudo chmod 755 /usr/local/bin/d.tags2utf8
$ sudo vi /usr/local/bin/d.tags2utf8
#!/usr/bin/env python """ Convert ID3 Tags from CP874 to UTF8 and auto rename file recursive into subdirectory. Coding from Khun pong_th's article at: http://www.thailinuxhosting.com/yabbse/index.php?board=6;action=display;threadid=9429 """ # 49-11-18 ADD ID3V1 CONVERSION import os # GLOBAL VARIABLE skel=".mp3" decodec="cp874" encodec="utf8" def d_passcheck_invalid_char(string): if string=="": return False i=0 for ch in ['\x00','\xff']: i=i+1 if ch in string: print "%d CH IN STRING %s" % (i,string) return False # # return True def d_convert(string): string=string.split('\00')[0] # TRIM '\x00' CHARACTER if d_passcheck_invalid_char(string): return string.decode(decodec).encode(encodec) else: return string # def d_rename2utf8(dir,strname): """Convert coding from TIS-620 to UTF-8.""" for i in strname: if i>'\x7f': # CHECK FOR UTF STRING if i=='\xe0': return strname newstr=d_convert(strname) print "rename file: %s -> %s" % (strname,newstr) os.rename(dir+os.sep+strname, dir+os.sep+newstr) return newstr # # return strname def d_getID3V1data(fstream): """Get old tags format From: http://www.faqs.org/docs/diveintopython/fileinfo_files.html""" # ID3V1 format (from:http://www.id3.org/id3v2-00.txt) # Field Length Offsets # Tag 3 0-2 # Songname 30 3-32 # Artist 30 33-62 # Album 30 63-92 # Year 4 93-96 # Comment 30 97-126 # Genre 1 127 fstream.seek(-128,2) tags=fstream.read(128) fstream.seek(0) return [tags[3:32],tags[33:62],tags[63:92],tags[93:96],tags[97:126],tags[127]] def d_write_eachtags(fstream,tagstitle,tagsdata): fstream.write(tagstitle+'\x00\x00\x00') fstream.write(chr(len(tagsdata)+1)+'\x00\x00\x03') fstream.write(tagsdata) return def d_change_tags2utf8(filename): """Change ID3 Tags content from cp874 to utf8""" fstream=open(filename,"r+b") ispass=False if fstream.read(3)=="ID3": # READ ID3 TAGS DATA fstream.read(6) nbyte=ord(fstream.read(1)) ltags=[] ctagsname=fstream.read(4) while ctagsname in ["TIT2","TPE1","TALB"]: fstream.read(3) ntagsbyte=ord(fstream.read(1)) fstream.read(3) ctagscontent=fstream.read(ntagsbyte-1) ltags.append([ctagsname,ntagsbyte,ctagscontent]) ctagsname=fstream.read(4) # # CONVERT TO utf8 nnewbyte=0 for eachtags in ltags: if not '\xe0' in eachtags[2]: eachtags[2]=d_convert(eachtags[2]) if not ispass: ispass=True # else: print "File %s already in utf8 format." % (filename) fstream.close() return False # eachtags[1]=len(eachtags[2]) nnewbyte=nnewbyte+4+3+3+eachtags[1]+1 # # WRITE BACK CONVERTED DATA fstream.seek(9) fstream.write(chr(nnewbyte)) for eachtags in ltags: d_write_eachtags(fstream,eachtags[0],eachtags[2]) # if nnewbyte<nbyte: for i in range(nbyte-nnewbyte): fstream.write('\x00') # # if ispass: print "Id3 Tags: file %s converted" % (filename) # else: # CHECK FOR ID3V1 fstream.seek(0) wholefile=fstream.read(-1) if 'TAG' in wholefile: ltags=d_getID3V1data(fstream) nnewbyte=0 for i in range(len(ltags)): ltags[i]=d_convert(ltags[i]) if d_passcheck_invalid_char(ltags[i]): nnewbyte=nnewbyte+len(ltags[i])+4+3 # # fstream.close() fstream=open(filename,"w") fstream.write('ID3'+'\x04\x00\x00\x00\x00\x08') fstream.write(chr(nnewbyte)) # Songname 30 3-32 :TIT2 # Artist 30 33-62 :TPE1 # Album 30 63-92 :TALB # Year 4 93-96 :TDOR # Comment 30 97-126 :COMM # Genre 1 127 :---- print ltags[0] if d_passcheck_invalid_char(ltags[0]): d_write_eachtags(fstream,'TIT2',ltags[0]) if d_passcheck_invalid_char(ltags[1]): d_write_eachtags(fstream,'TPE1',ltags[1]) if d_passcheck_invalid_char(ltags[2]): d_write_eachtags(fstream,'TALB',ltags[2]) if d_passcheck_invalid_char(ltags[3]): d_write_eachtags(fstream,'TDOR',ltags[3]) if d_passcheck_invalid_char(ltags[4]): d_write_eachtags(fstream,'COMM',ltags[4]) # DISCARD Genre TAGS for i in range(1016): fstream.write('\x00') # fstream.write(wholefile) else: print "ID3 Tags not found in %s" % (filename) # # fstream.close() def process_dir(dir): """Process all files in the folder""" for f in os.listdir(dir): file = dir + os.sep + f if os.path.isdir(file): print "Enter directory %s" % (file) process_dir(file) print "---exit directory %s" % (file) # if f[-4:]==skel: # DO CONVERT FILENAME file=d_rename2utf8(dir,file) # DO CHANGE ID3 TAGS d_change_tags2utf8(file) # # return def main(): """main routine""" process_dir('.') return if __name__=='__main__': main()