📜 ⬆️ ⬇️

Thanks for the HTML5 File API or read the ID3 tag and fill out the form without loading an MP3 file.

HTML5 Powered with Offline & Storage
With the advent of HTML5, we have many new and interesting features. Allowing you to create even better applications.

For example, File API. Accessing client files is quite handy. For example, we can fill out a form using information from a file selected by the user:

Let's practice reading ID3 tags from MP3 tracks.

First outline the form


<!DOCTYPE html> <html lang="en" dir="ltr"> <head > <title>HTML5 File API</title> <meta charset="utf-8"> <style> input {width:300px;} form div {margin-bottom:5px;} </style> </head> <body> <form id="meta"> <div><input type="file" id="files" name="file"></div> <div><input type="text" id="title" name="title"></div> <div><input type="text" id="artist" name="artist"></div> <div><input type="text" id="album" name="album"></div> <div><input type="text" id="year" name="year"></div> </form> <script type="text/javascript" src="binary-buffer.js"></script> <script type="text/javascript" src="id3v2.js"></script> <script type="text/javascript" src="script.js"></script> </body> </html> 

')

Object for working with binary data (binary-buffer.js)


Description in the comments
 var BinaryBuffer=function(buffer){ this.buffer=buffer; this.length=buffer.length; }; BinaryBuffer.prototype={ //     slice:function(offset,length){ var buffer=new ArrayBuffer(length); for(var i=offset,j=0;i<this.length && j<length;i++,j++){ buffer[j]=this.buffer[i]; } return new BinaryBuffer(buffer); }, //    byteAt:function(i){ return this.buffer[i]&0xFF; }, //  ASCII  charAt:function(i){ var code=this.byteAt(i); if(code==0)return "?"; if(code<32)return "?"; return String.fromCharCode(code); }, //  ASCII  stringAt:function(offset,length){ var str=[]; for(var i=offset,j=0;i<offset+length;i++,j++) { str[j]=this.charAt(i); } return str.join(""); }, //  ASCII     toString:function(){ return this.stringAt(0,this.length); } }; 


We cling a file selection event (script.js)


Description in the comments
 //   File API . if(window.File && window.FileReader && window.FileList && window.Blob) { //        document.getElementById('files').addEventListener('change',function(e) { //      if(!e.target.files.length) { alert('Please select a file!'); return; } //      var file=e.target.files[0]; //    mp3,   -    if(file.type=='audio/mpeg'){ //    var tag=new ID3v2; //   // ..    , //     , //     . //      . tag.readFromFile(file,function(tag){ document.getElementById('title').value=tag.get('TIT2'); document.getElementById('artist').value=tag.get('TPE1'); document.getElementById('album').value=tag.get('TALB'); document.getElementById('year').value=tag.get('TDRC'); }); } else { alert('Unsupported file type <'+file.type+'>'); } }); } else { alert('The File APIs are not fully supported in this browser.'); } 


Well, the most delicious parsim file contents (id3v2.js)


Description in the comments
 var ID3v2=function(){ // C    this.errors=[]; //   this.version='Unknown'; //   this.flags={ isUnSynchronisation:false, hasExtendedHeader:false, isExperimental:false, hasFooter:false }; //    .    10    10   (  ) this.size=0; //   this.frames={}; }; ID3v2.prototype.readFromFile=function(file,callback){ //       if(!(callback instanceof Function)){ callback=function(target){}; } var self=this, //   FileReader reader=new FileReader; //  Synchsafe -        ,   , ,   // http://en.wikipedia.org/wiki/Synchsafe function UnSynchsafeInt(buffer){ var value=0; for(var i=0,length=buffer.length;i<length;i++){ value+=(buffer.byteAt(i)&0x7F)*Math.pow(Math.pow(2,7),length-i-1); } return value; } //          reader.onloadend=function(e){ //     if(e.target.readyState==FileReader.DONE){ //     Blob       BinaryBuffer var result=new BinaryBuffer(e.target.result); //  3      if(result.stringAt(0,3).toUpperCase()!=='ID3'){ self.errors.push(': ID3v2  !'); callback(self); return; } //        self.version='2.'+result.byteAt(3)+'.'+result.byteAt(4); //     . //      . self.flags.isUnSynchronisation=result.byteAt(5)&128?true:false; self.flags.hasExtendedHeader=result.byteAt(5)&64?true:false; self.flags.isExperimental=result.byteAt(5)&32?true:false; self.flags.hasFooter=result.byteAt(5)&16?true:false; //     4    7 self.size=UnSynchsafeInt(result.slice(6,4)); if(self.size<1){ self.errors.push(': ID3v2 !'); callback(self); return; } //       ,     reader.onloadend=function(e){ var result=new BinaryBuffer(e.target.result), cursor=0; //    . //         . //    10 . //     : ID (4 ),  (4 ),  (2 ) do { var frame={}; //  4     var id=result.stringAt(cursor,4); //     if(ID3v2.validFramesIds.indexOf(id)<0){ self.errors.push('Error: ID3v2    ('+id+')!'); cursor+=10; } else { frame.id=id; frame.size=UnSynchsafeInt(result.slice(cursor+4,4)); cursor+=10; frame.value=result.slice(cursor,frame.size).toString(); cursor+=frame.size; self.frames[id]=frame; } } while(cursor<=self.size); //  .  . . callback(self); }; reader.readAsArrayBuffer(file.slice(10,self.size)); } }; //     ,    ,     10  . // *** ID3    2.4.0      ,     ID3     . //   10   . reader.readAsArrayBuffer(file.slice(0,10)); }; //    ID3v2.prototype.get=function(id){ return this.frames[id]?this.frames[id].value:''; }; ID3v2.validFramesIds=[ 'AENC', // Audio encryption 'APIC', // Attached picture 'COMM', // Comments 'COMR', // Commercial frame 'ENCR', // Encryption method registration 'EQUA', // Equalization 'ETCO', // Event timing codes 'GEOB', // General encapsulated object 'GRID', // Group identification registration 'IPLS', // Involved people list 'LINK', // Linked information 'MCDI', // Music CD identifier 'MLLT', // MPEG location lookup table 'OWNE', // Ownership frame 'PRIV', // Private frame 'PCNT', // Play counter 'POPM', // Popularimeter 'POSS', // Position synchronisation frame 'RBUF', // Recommended buffer size 'RVAD', // Relative volume adjustment 'RVRB', // Reverb 'SYLT', // Synchronized lyric/text 'SYTC', // Synchronized tempo codes 'TALB', // Album/Movie/Show title 'TBPM', // BPM (beats per minute) 'TCOM', // Composer 'TCON', // Content type 'TCOP', // Copyright message 'TDAT', // Date 'TDLY', // Playlist delay 'TENC', // Encoded by 'TEXT', // Lyricist/Text writer 'TFLT', // File type 'TIME', // Time 'TIT1', // Content group description 'TIT2', // Title/songname/content description 'TIT3', // Subtitle/Description refinement 'TKEY', // Initial key 'TLAN', // Language(s) 'TLEN', // Length 'TMED', // Media type 'TOAL', // Original album/movie/show title 'TOFN', // Original filename 'TOLY', // Original lyricist(s)/text writer(s) 'TOPE', // Original artist(s)/performer(s) 'TORY', // Original release year 'TOWN', // File owner/licensee 'TPE1', // Lead performer(s)/Soloist(s) 'TPE2', // Band/orchestra/accompaniment 'TPE3', // Conductor/performer refinement 'TPE4', // Interpreted, remixed, or otherwise modified by 'TPOS', // Part of a set 'TPUB', // Publisher 'TRCK', // Track number/Position in set 'TRDA', // Recording dates 'TRSN', // Internet radio station name 'TRSO', // Internet radio station owner 'TSIZ', // Size 'TSRC', // ISRC (international standard recording code) 'TSSE', // Software/Hardware and settings used for encoding 'TYER', // Year 'TXXX', // User defined text information frame 'UFID', // Unique file identifier 'USER', // Terms of use 'USLT', // Unsychronized lyric/text transcription 'WCOM', // Commercial information 'WCOP', // Copyright/Legal information 'WOAF', // Official audio file webpage 'WOAR', // Official artist/performer webpage 'WOAS', // Official audio source webpage 'WORS', // Official internet radio station homepage 'WPAY', // Payment 'WPUB', // Publishers official webpage 'WXXX', // User defined URL link frame "TDRC" // Unknown, possibly year !!! ]; 


Links


ID3 Developer Information
HTML5 FileAPI
Synchsafe number
Attempts to write a library, join

UPDATE 1:
demo

Source: https://habr.com/ru/post/140695/


All Articles