Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Własna funkcja do wyciągania tagów ID3v2
Forum PHP.pl > Forum > PHP
shinuexx
Witam napisałem sobie własną funkcję do wyciągania tagów ID3v2 z plików mp3, ale mam pewien problem z niektórymi plikami. Zdarza się że czasem źle odczytuje rozmiar tagu i bądź też ramki (głównie przy GEOB oraz APIC). Podczas robienia podpierałem się trochę istniejącymi skryptami a strukturę tagu mam ze strony http://www.id3.org/. Poniżej przesyłam kod. Może gdzieś popełniłem błąd przy przetwarzaniu tagu.
  1.  
  2. // Funkcja wyciągająca nagłówek tagu
  3.  
  4. function id3v2header($file)
  5. {
  6. $stream=fopen($file,"r");
  7. $header=fread($stream,10);
  8. fclose($stream);
  9.  
  10. $id3v2header['filename']=$file;
  11. if(substr($header,0,3)!="ID3")
  12. {
  13. $id3v2header['exist']=FALSE;
  14. $id3v2header['size']=0;
  15. return $id3v2header;
  16. exit();
  17. };
  18. $id3v2header['exist']=TRUE;
  19. $id3v2header['tagid']=substr($header,0,3);
  20. $id3v2header['version']=be2int($header[3]).".".be2int($header[4]);
  21. $flags=be2bin($header[5]);
  22. $id3v2header['flags']['full']=$flags;
  23. $id3v2header['flags']['unsynchronisation']=substr($flags,0,1);
  24. $id3v2header['flags']['extended_header']=substr($flags,1,1);
  25. $id3v2header['flags']['experimental_indicator']=substr($flags,2,1);
  26. $id3v2header['flags']['footer_present']=substr($flags,3,1);
  27. $id3v2header['size']=unsynchsafe(be2int(substr($header,6,4)));
  28.  
  29. return $id3v2header;
  30. };
  31.  
  32. // Funkcja wyciągająca cały tag
  33.  
  34. function id3v2tag($file, $tagsize)
  35. {
  36. if($tagsize==0)
  37. {
  38. $id3v2tag['exist']=FALSE;
  39. return $id3v2tag;
  40. exit();
  41. };
  42. $id3v2tag['exist']=TRUE;
  43. $stream=fopen($file,"r");
  44. $tag=fread($stream,$tagsize);
  45. fclose($stream);
  46. $id3v2tag['fulltag']=substr($tag,10);
  47. $allowedtag=file("inc/txtfiles/allowed_tag.txt");
  48. $x=0;
  49. $count['WXXX']=0;
  50. $count['APIC']=0;
  51. $count['UFID']=0;
  52. $count['GEOB']=0;
  53. $count['COMM']=0;
  54. $count['TXXX']=0;
  55. $count['POPM']=0;
  56. $count['USLT']=0;
  57. $count['AENC']=0;
  58. $count['SYLT']=0;
  59. $count['LINK']=0;
  60. $count['RVA2']=0;
  61. $count['USER']=0;
  62. $count['COMR']=0;
  63. $count['EQU2']=0;
  64. $count['ENCR']=0;
  65. $count['GRID']=0;
  66. $count['PRIV']=0;
  67. $count['SIGN']=0;
  68. $listpos=0;
  69. while ($x<($tagsize-10))
  70. {
  71. $frame=substr($id3v2tag['fulltag'],$x,4);
  72. for($y=0;$y<4;++$y)
  73. {
  74. $fid[$y]=be2bin(substr($frame,$y,1));
  75. };
  76. $condition= ($fid[0]!=0x00 &&
  77. ((ord($frame[0])>=0x30 && ord($frame[0])<=0x39) || (ord($frame[0])>=0x41 && ord($frame[0])<=0x5A)) &&
  78. $fid[1]!=0x00 &&
  79. ((ord($frame[1])>=0x30 && ord($frame[1])<=0x39) || (ord($frame[1])>=0x41 && ord($frame[1])<=0x5A)) &&
  80. $fid[2]!=0x00 &&
  81. ((ord($frame[2])>=0x30 && ord($frame[2])<=0x39) || (ord($frame[2])>=0x41 && ord($frame[2])<=0x5A)) &&
  82. $fid[3]!=0x00 &&
  83. ((ord($frame[3])>=0x30 && ord($frame[3])<=0x39) || (ord($frame[3])>=0x41 && ord($frame[3])<=0x5A)) &&
  84. in_array($frame."\n",$allowedtag));
  85. if($condition==true)
  86. {
  87. $id3v2tag['framelist']["$listpos"]['id']=$frame;
  88. $id3v2tag['framelist']["$listpos"]['fullname']=framefullname($frame);
  89.  
  90. $condition=(
  91. $frame=="WXXX" ||
  92. $frame=="APIC" ||
  93. $frame=="UFID" ||
  94. $frame=="GEOB" ||
  95. $frame=="COMM" ||
  96. $frame=="TXXX" ||
  97. $frame=="POPM" ||
  98. $frame=="USLT" ||
  99. $frame=="AENC" ||
  100. $frame=="SYLT" ||
  101. $frame=="LINK" ||
  102. $frame=="RVA2" ||
  103. $frame=="USER" ||
  104. $frame=="COMR" ||
  105. $frame=="EQU2" ||
  106. $frame=="ENCR" ||
  107. $frame=="GRID" ||
  108. $frame=="PRIV" ||
  109. $frame=="SIGN");
  110.  
  111. if($condition==true)
  112. {
  113. $id3v2tag['frames']["$frame"]["$count[$frame]"]['id']=$frame;
  114. $x+=4;
  115. $id3v2tag['frames']["$frame"]["$count[$frame]"]['fullname']=framefullname($frame);
  116. $id3v2tag['frames']["$frame"]["$count[$frame]"]['size']=unsynchsafe(be2int(substr($id3v2tag['fulltag'],$x,4)));
  117. if($frame=="APIC")
  118. {
  119. $id3v2tag['frames']["$frame"]["$count[$frame]"]['size']=2*$id3v2tag['frames']["$frame"]["$count[$frame]"]['size'];
  120. };
  121. $x+=4;
  122. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_status_flag']['full']=be2bin(substr($id3v2tag['fulltag'],$x,1));
  123. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_status_flag']['tag_alter_preservation']=substr($id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_status_flag']['full'],1,1);
  124. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_status_flag']['file_alter_preservation']=substr($id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_status_flag']['full'],2,1);
  125. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_status_flag']['read_only']=substr($id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_status_flag']['full'],3,1);
  126. $x++;
  127.  
  128. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['full']=be2bin(substr($id3v2tag['fulltag'],$x,1));
  129. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['grouping_identity']=substr($id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['full'],1,1);
  130. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['compresion']=substr($id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['full'],4,1);
  131. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['encryption']=substr($id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['full'],5,1);
  132. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['unsynchronisation']=substr($id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['full'],6,1);
  133. $id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['data_length_indicator']=substr($id3v2tag['frames']["$frame"]["$count[$frame]"]['flags']['frame_format_flag']['full'],7,1);
  134. $x++;
  135. $id3v2tag['frames']["$frame"]["$count[$frame]"]['data']=substr($id3v2tag['fulltag'],$x,$id3v2tag['frames']["$frame"]["$count[$frame]"]['size']);
  136. $id3v2tag['frames']["$frame"]["$count[$frame]"]['processed_data']=identifyframe($id3v2tag['frames']["$frame"]["$count[$frame]"]['id'],$id3v2tag['frames']["$frame"]["$count[$frame]"]['data']);
  137.  
  138. $id3v2tag['lastletters']=substr($id3v2tag['frames']["$frame"]["$count[$frame]"]['data'],-4);
  139. $id3v2tag['lastletterspos']=strpos($id3v2tag['fulltag'],$id3v2tag['lastletters'])+10;
  140. $count[$frame]++;
  141. }
  142. else
  143. {
  144. $id3v2tag['frames']["$frame"]['id']=$frame;
  145. $x+=4;
  146. $id3v2tag['frames']["$frame"]['fullname']=framefullname($frame);
  147. $id3v2tag['frames']["$frame"]['size']=unsynchsafe(be2int(substr($id3v2tag['fulltag'],$x,4)));
  148. $x+=4;
  149. $id3v2tag['frames']["$frame"]['flags']['frame_status_flag']['full']=be2bin(substr($id3v2tag['fulltag'],$x,1));
  150. $x++;
  151. $id3v2tag['frames']["$frame"]['flags']['frame_status_flag']['tag_alter_preservation']=substr($id3v2tag['frames']["$frame"]['flags']['frame_status_flag']['full'],1,1);
  152. $id3v2tag['frames']["$frame"]['flags']['frame_status_flag']['file_alter_preservation']=substr($id3v2tag['frames']["$frame"]['flags']['frame_status_flag']['full'],2,1);
  153. $id3v2tag['frames']["$frame"]['flags']['frame_status_flag']['read_only']=substr($id3v2tag['frames']["$frame"]['flags']['frame_status_flag']['full'],3,1);
  154.  
  155. $id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['full']=be2bin(substr($id3v2tag['fulltag'],$x,1));
  156. $id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['grouping_identity']=substr($id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['full'],1,1);
  157. $id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['compresion']=substr($id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['full'],4,1);
  158. $id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['encryption']=substr($id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['full'],5,1);
  159. $id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['unsynchronisation']=substr($id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['full'],6,1);
  160. $id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['data_length_indicator']=substr($id3v2tag['frames']["$frame"]['flags']['frame_format_flag']['full'],7,1);
  161. $x++;
  162. $id3v2tag['frames']["$frame"]['data']=substr($id3v2tag['fulltag'],$x,$id3v2tag['frames']["$frame"]['size']);
  163. $id3v2tag['frames']["$frame"]['processed_data']=identifyframe($id3v2tag['frames']["$frame"]['id'],$id3v2tag['frames']["$frame"]['data']);
  164. if($id3v2tag['coding']=$id3v2tag['frames']["$frame"]['processed_data']['encoding'])
  165. {}
  166. else if($id3v2tag['coding']==null)
  167. {$id3v2tag['coding']="UTF-8";}
  168. else{};
  169. $id3v2tag['lastletters']=substr($id3v2tag['frames']["$frame"]['data'],-4);
  170. $id3v2tag['lastletterspos']=strpos($id3v2tag['fulltag'],$id3v2tag['lastletters'])+10;
  171. };
  172. $listpos++;
  173. }
  174. else
  175. {
  176. $x++;
  177. };
  178. };
  179. return $id3v2tag;
  180. };
  181.  
  182. // Identyfikacja ramek
  183.  
  184. function framefullname($frame)
  185. {
  186. $file="inc/txtfiles/framefullname.txt";
  187. $list=file($file);
  188. $li=count($list);
  189. $x=0;
  190. while($x<$li)
  191. {
  192. $id=substr($list[$x],0,4);
  193. $fullname=substr($list[$x],5);
  194. $lii=strlen($fullname)-1;
  195. $framefullname["$id"]=substr($fullname,0,$lii);
  196. ++$x;
  197. };
  198.  
  199. return $framefullname["$frame"];
  200. };


  1. // pełna nazwa ramki
  2.  
  3. function framefullname($frame)
  4. {
  5. $file="inc/txtfiles/framefullname.txt";
  6. $list=file($file);
  7. $li=count($list);
  8. $x=0;
  9. while($x<$li)
  10. {
  11. $id=substr($list[$x],0,4);
  12. $fullname=substr($list[$x],5);
  13. $lii=strlen($fullname)-1;
  14. $framefullname["$id"]=substr($fullname,0,$lii);
  15. ++$x;
  16. };
  17.  
  18. return $framefullname["$frame"];
  19. };
  20.  
  21. // identyfikacja kodowania ramki
  22.  
  23. function coding_table($type,$id3v2tagcoding)
  24. {
  25. switch($id3v2tagcoding)
  26. {
  27. case 0x00:
  28. $info['coding']="ISO-8859-1";
  29. $info['pagecoding']="ISO-8859-2";
  30. $info['terminator']=chr(0);
  31. break;
  32.  
  33. case 0x01:
  34. $info['coding']="UTF-16";
  35. $info['pagecoding']="UTF-8";
  36. $info['terminator']=chr(0);
  37. $info['terminator'].=chr(0);
  38. break;
  39.  
  40. case 0x02:
  41. $info['coding']="UTF-16BE";
  42. $info['pagecoding']="UTF-8";
  43. $info['terminator']=chr(0);
  44. $info['terminator'].=chr(0);
  45. break;
  46.  
  47. case 0x03:
  48. $info['coding']="UTF-8";
  49. $info['pagecoding']="UTF-8";
  50. $info['terminator']=chr(0);
  51. break;
  52. default:
  53. $info['coding']="UTF-8";
  54. $info['pagecoding']="UTF-8";
  55. $info['terminator']=chr(0);
  56. break;
  57. };
  58. return $info["$type"];
  59. };
  60.  
  61. // funkcja do wyciągania rozmiaru z synchsafe (znaleziona na internecie w C)
  62.  
  63. function unsynchsafe($in)
  64. {
  65. $out = 0;
  66. $mask = 0x7F000000;
  67.  
  68. while ($mask)
  69. {
  70. $out >>= 1;
  71. $out |= $in & $mask;
  72. $mask >>= 8;
  73. }
  74.  
  75. return $out;
  76. }
  77.  
  78. // Z Big Endian na heksadecymalną liczbę
  79.  
  80. function binhex($bin)
  81. {
  82. $hex=dechex(bindec($bin));
  83. return $hex;
  84. };
  85.  
  86. // Z Big Endian na binarny zapis
  87.  
  88. function be2bin($byteword)
  89. {
  90. $binvalue = '';
  91. $bytewordlen = strlen($byteword);
  92. for ($i=0;$i<$bytewordlen;$i++)
  93. {
  94. $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
  95. }
  96. return $binvalue;
  97. };
  98.  
  99. // z Big Endian na ciąg znaków drukowanych
  100.  
  101. function be2str($word)
  102. {
  103. $string="";
  104. for($y=0; $y<strlen($word);$y++)
  105. {
  106. $string.=chr(bindec(be2bin($word[$y])));
  107. };
  108. return $string;
  109. };
  110.  
  111. // Z Big Endian na liczbę dziesiętną - zamienia cały ciąg znaków na liczbę dziesiętną (nie było mi potrzebne nic innego)
  112.  
  113. function be2int($be)
  114. {
  115. $int=bindec(be2bin($be));
  116. return $int;
  117. };
  118.  
  119. // Identyfikacja niektórych bajtów na odpowiednie wartości wyciągane z pliku jak np. typ obrazka
  120.  
  121. function select_from_file_table($in, $name)
  122. {
  123. $file=file("inc/txtfiles/$name.txt");
  124. //$in=hexdec($in);
  125. $explode=array();
  126. $li=count($file);
  127. $x=0;
  128. while($x<$li)
  129. {
  130. $explode[$x]=explode(";;",$file[$x]);
  131. $x++;
  132. };
  133. $x=0;
  134. while($x<$li)
  135. {
  136. $explode[$x][0]=hexdec($explode[$x][0]);
  137. $x++;
  138. };
  139. $x=0;
  140. while($x<$li)
  141. {
  142. $o=strlen($explode[$x][1])-2;
  143. $out[$explode[$x][0]]=substr($explode[$x][1],0,$o);
  144. $x++;
  145. };
  146. return $out["$in"];
  147. }
  148.  


jeszcze jedna funkcja ale nie mieści się w poście dlatego wrzucę linka do niej:
Identify frame


Prosiłbym moderatora o usunięcie tego mojego tematu.
mls
A czy nie byłoby prościej skorzystać z http://getid3.sourceforge.net/?
shinuexx
Potrzebowałem wartości zwracane w UTF-8 więc tak czy tak musiałbym przerabiać istniejący kod. Z tego względu wolałem go sam napisać. A poza tym zwraca on podobne wartości jak getid3. Nie jestem też pewien ale wydaje mi się że ramkę GEOB getid3 też źle czyta bo nie zgadza się to z dokumentacją.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.