Bildinformation aus id3v2-Tag auslesen

Html

Erfahrenes Mitglied
Hallo, möchte gerne die id3v2-Informationen aus mp3-Dateien auslesen. Habe dazu folgenden Code gefunden:

PHP:
<?php

/*
//===================================================\\
|                                                     |
|               ID-Tag Reader by Ansi                 |
|                                                     |
|          Reading IDv1.1 and IDv4.0 Tags             |
|                                                     |
|     if you want more frames to be read consult      |
|        http://www.id3.org/id3v2.3.0.html            |
|                                                     |
|                                                     |
\\===================================================//
*/

function readHeader($mp3){

// -------> Config <-------

$unuebliche_tags = true;    //gibt auch Tags aus, die von der üblichen Software *nicht* genutzt werden

// -------> Config <-------

    $header = array();

    //Liste der genutzen Frames für ID3v2.3 und deren
    //Rückgabe im $header[]- Array. Um Übersichtlichkeit
    //zu wahren werden alle Frames, die nicht in dieser
    //Liste stehen standardmäßig später *nicht* ausgegeben.
    $frames = array(
        'TPE1'    =>    'artist',
        'TALB'    =>    'album',
        'COMM'    =>    'comment',
        'TBPM'    =>    'bitrate',
        'TCON'    =>    'genre',
        'TCOM'    =>    'composer',
        'TDAT'    =>    'date',
        'TENC'    =>    'encoder',
        'TIT2'    =>    'title',
        'TIT3'    =>    'subtitle',
        'TLAN'    =>    'languages',
        'TLEN'    =>    'length',
        'TYER'    =>    'year',
        'TRCK'    =>    'track',
        'TORY'    =>    'year',
        'TCOP'    =>    'copyright');
    
    //Liste der Genres und ihrer Entsprechung
    $genres = array(
        0   => 'Blues',
        1   => 'Classic Rock',
        2   => 'Country',
        3   => 'Dance',
        4   => 'Disco',
        5   => 'Funk',
        6   => 'Grunge',
        7   => 'Hip-Hop',
        8   => 'Jazz',
        9   => 'Metal',
        10  => 'New Age',
        11  => 'Oldies',
        12  => 'Other',
        13  => 'Pop',
        14  => 'R&B',
        15  => 'Rap',
        16  => 'Reggae',
        17  => 'Rock',
        18  => 'Techno',
        19  => 'Industrial',
        20  => 'Alternative',
        21  => 'Ska',
        22  => 'Death Metal',
        23  => 'Pranks',
        24  => 'Soundtrack',
        25  => 'Euro-Techno',
        26  => 'Ambient',
        27  => 'Trip-Hop',
        28  => 'Vocal',
        29  => 'Jazz+Funk',
        30  => 'Fusion',
        31  => 'Trance',
        32  => 'Classical',
        33  => 'Instrumental',
        34  => 'Acid',
        35  => 'House',
        36  => 'Game',
        37  => 'Sound Clip',
        38  => 'Gospel',
        39  => 'Noise',
        40  => 'Alternative Rock',
        41  => 'Bass',
        42  => 'Soul',
        43  => 'Punk',
        44  => 'Space',
        45  => 'Meditative',
        46  => 'Instrumental Pop',
        47  => 'Instrumental Rock',
        48  => 'Ethnic',
        49  => 'Gothic',
        50  => 'Darkwave',
        51  => 'Techno-Industrial',
        52  => 'Electronic',
        53  => 'Pop-Folk',
        54  => 'Eurodance',
        55  => 'Dream',
        56  => 'Southern Rock',
        57  => 'Comedy',
        58  => 'Cult',
        59  => 'Gangsta',
        60  => 'Top 40',
        61  => 'Christian Rap',
        62  => 'Pop/Funk',
        63  => 'Jungle',
        64  => 'Native US',
        65  => 'Cabaret',
        66  => 'New Wave',
        67  => 'Psychadelic',
        68  => 'Rave',
        69  => 'Showtunes',
        70  => 'Trailer',
        71  => 'Lo-Fi',
        72  => 'Tribal',
        73  => 'Acid Punk',
        74  => 'Acid Jazz',
        75  => 'Polka',
        76  => 'Retro',
        77  => 'Musical',
        78  => 'Rock & Roll',
        79  => 'Hard Rock',
        80  => 'Folk',
        81  => 'Folk-Rock',
        82  => 'National Folk',
        83  => 'Swing',
        84  => 'Fast Fusion',
        85  => 'Bebob',
        86  => 'Latin',
        87  => 'Revival',
        88  => 'Celtic',
        89  => 'Bluegrass',
        90  => 'Avantgarde',
        91  => 'Gothic Rock',
        92  => 'Progressive Rock',
        93  => 'Psychedelic Rock',
        94  => 'Symphonic Rock',
        95  => 'Slow Rock',
        96  => 'Big Band',
        97  => 'Chorus',
        98  => 'Easy Listening',
        99  => 'Acoustic',
        100 => 'Humour',
        101 => 'Speech',
        102 => 'Chanson',
        103 => 'Opera',
        104 => 'Chamber Music',
        105 => 'Sonata',
        106 => 'Symphony',
        107 => 'Booty Bass',
        108 => 'Primus',
        109 => 'Porn Groove',
        110 => 'Satire',
        111 => 'Slow Jam',
        112 => 'Club',
        113 => 'Tango',
        114 => 'Samba',
        115 => 'Folklore',
        116 => 'Ballad',
        117 => 'Power Ballad',
        118 => 'Rhytmic Soul',
        119 => 'Freestyle',
        120 => 'Duet',
        121 => 'Punk Rock',
        122 => 'Drum Solo',
        123 => 'Acapella',
        124 => 'Euro-House',
        125 => 'Dance Hall',
        126 => 'Goa',
        127 => 'Drum & Bass',
        128 => 'Club-House',
        129 => 'Hardcore',
        130 => 'Terror',
        131 => 'Indie',
        132 => 'BritPop',
        133 => 'Negerpunk',
        134 => 'Polsk Punk',
        135 => 'Beat',
        136 => 'Christian Gangsta Rap',
        137 => 'Heavy Metal',
        138 => 'Black Metal',
        139 => 'Crossover',
        140 => 'Contemporary Christian',
        141 => 'Christian Rock',
        142 => 'Merengue',
        143 => 'Salsa',
        144 => 'Trash Metal',
        145 => 'Anime',
        146 => 'Jpop',
        147 => 'Synthpop');

    //MP3 einlesen
    $filelength = filesize($mp3);
    $hdl = fopen($mp3, "rb");
    if($hdl):
            $content .= fread($hdl, $filelength);
        fclose($hdl);
    endif;

    //Versuche ID3v2 Tag zu finden
    $IDTag = strpos($content, "ID3");

    //Wenn ID3v2 nicht gefunden wird nach ID3v1
    //suchen, entspricht TAG
    if($IDTag === false):
        $IDTag = strpos($content, "TAG");        
        if($IDTag === false):
            $header['type'] = "kein Header gefunden";
            return $header;
            exit;
        else:
            $header['type'] = "ID3v1";
            //$header['pos'] = $IDTag;
        endif;
    else:
        $header['type'] = "ID3v2";
        //$header['pos'] = $IDTag;
    endif;

    switch ($header['type']):
        //ID3v2 Tags auslesen: Flexiblere Felder
        case "ID3v2":
            //10 Byte des ID3 Headers auslesen
            $ID3Header = substr($content, $IDTag, 10);
            
            //Exakte Version der genutzen ID3v2 Version ermitteln
            $header['type'] .= ".".ord(substr($ID3Header, 3, 1)).".".ord(substr($ID3Header, 4, 1));
            
            //Gesamte Headerlänge inklusive Frames ermitteln
            $HeaderLength =  265 * 8 * 8 * ord(substr($ID3Header, 6, 1)) + 265 * 8 * ord(substr($ID3Header, 7, 1)) + 265 *  ord(substr($ID3Header,  8, 1)) + ord(substr($ID3Header,  9, 1));
            
            //ID3 Header in Variabel ablegen, $content leeren
            $ID3Header = substr($content, $IDTrag, $HeaderLength + 10);
            $content = "";

            //Startposition für Frameerkennung ist Byte 10
            $CurPos = 10;
            
            //So lange Frames suchen / auslesen, bis eine Frameposition
            //leer ist oder der Header durchlaufen wurde
            while($CurPos < $HeaderLength + 10):
                $FrameName = substr($ID3Header, $CurPos, 4);
                if(trim($FrameName) != ""):
                    $FrameLength = 265 * 8 * 8 * ord(substr($ID3Header, $CurPos + 4, 1)) + 265 * 8 * ord(substr($ID3Header, $CurPos + 5, 1)) + 265 *  ord(substr($ID3Header,  $CurPos + 6, 1)) + ord(substr($ID3Header,  $CurPos + 7, 1));
                    $FrameContent = substr($ID3Header, $CurPos + 10, $FrameLength);
                    $CurPos = $CurPos + $FrameLength + 10;
                    if(array_key_exists($FrameName, $frames) == true):
                        $header[$frames[$FrameName]] = $FrameContent;
                    elseif($unuebliche_tags == true):    
                        $counter++;
                        $header[$FrameName."_".$counter] = $FrameContent;
                    endif;
                else:
                    break;
                endif;
            endwhile;
            break;

        //Hier wird der ID3V1.1 Standard vorausgesetzt,
        //der im letzten Byte des Kommentares (127) den Track speichert
        case "ID3v1.1":
            $header['titel'] = trim(substr($content, $IDTag + 3, 30));
            $header['artist'] = trim(substr($content, $IDTag + 33, 30));
            $header['album'] = trim(substr($content, $IDTag + 63, 30));
            $header['year'] = trim(substr($content, $IDTag + 93, 4));
            $header['comment'] = trim(substr($content, $IDTag + 97, 29));
            $header['track'] = ord(trim(substr($content, $IDTag + 126, 1)));
            $header['genre'] = ord(trim(substr($content, $IDTag + 127, 1)));
            if(!$header['genre'] === false):
                $header['genre'] = $genres[$header['genre']];
            endif;
            break;
    endswitch;

    return $header;

}

// Tabelle für ID- Tags generieren

echo "<table><tr><th align = 'left'>Feld</th><th align = 'left'>Inhalt</th></tr>";

    foreach (readHeader('Add N To [X] - 04 - kingdom of shades.mp3') as $key => $value){
        echo "<tr><td>$key</td><td>$value</td></tr>";
    }

echo "</table>";?>


Der Code funktioniert zwar super bis auf eine Kleinigkeit. Und zwar ist es ja möglich im id3v2 die Cover bzw Inlets mit anzugeben. Doch beim auslesen mit obigem Code eines solchen id3v2-Tags stehen dann unter den allgemeinen Informationen (album, interpret etc...) nur lauter seltsame Zeichen. Denke das sollen die Bildinformationen sein. Aber damit kann ich nix anfangen.

Lässt sich das irgendwie in brauchbare Informationen wandeln. Welche Informationen werden zu den Bildern überhaupt in dem id3v2 tag gespeichert.


mfg,Olli
 
Du müsstest ein externes Skript benutzen, dass den Content als Bilddatei ausweist.

Sagen wir, das Bild kommt als JPEG an, müsste es ungefähr so aussehen:

PHP:
<!-- Einbinden -->
<img src="./bild.php?pic=<?php echo urlencode($var); ?>" />

Und die bild.php müsste ungefähr so aussehen:

PHP:
<?php
$pic = urldecode($_GET['var']);
header('Content-Type: image/jpeg');
print($var);
?>
 
Erstmal danke für deine Antwort...

Was ich lediglich brauche ist eigentlich der Pfad des Bildes.

Ich benötige zum Schluss einfach mehrere Variablen:

$artist
$album
$genre
$Pfad zum Coverbild

die ich dann einfach in eine Datenbank schreiben kann.

Das einzige was mir halt Probleme macht ist den Pfad zum zugehörigen Cover in einer Variable zu speichern.

Das Auslesen vom Rest funktioniert ja und das übertragen in DB weiß ich auch wie das geht.

Vielleicht kann mir da jemand nochmal das ganze etwas genauer posten. Sorry aber bin phpnewbie


//EDIT

Hallo habe das ganze jetzt mal so in den o.g Code eingebunden:


PHP:
.......

$ausgabe=readHeader('LeAnn Rimes\2004 The Best Of\04 - LeAnn Rimes - I Need You.mp3');

echo $ausgabe["type"]."<br>";
echo $ausgabe["artist"]."<br>";
echo $ausgabe["title"]."<br>";
echo $ausgabe["album"]."<br>";

//echo $ausgabe["APIC_1"]."<br>";
//print_r($ausgabe);

echo "<img src=bild.php?var=".urlencode($ausgabe["APIC_1"])." />" ;


Und hier meine bild.php

PHP:
<?php


$pic = urldecode($_GET['var']);
header('Content-Type: image/jpeg');
print($pic);



?>


Doch leider zeigt mir der Browser kein Bild an sondern nur ein Platzhalter.


Warum?


mfg,Olli
 
Könntest du mir mal eine solche MP3 mal schicken?
Aus irgendeinem Grund kann ich in WinAmp dieses Feld nicht entdecken, noch hat irgendeine meiner MP3s dieses Feld drin.
E-Mail hast du als PN.
 
[OFF] ...
Mal so nebenbei ... ich tummel mich ja viel in Musiksachen rum, aber habe noch NIE einen Genré gefunden, der mit "Negerpunk (siehe $genres = array( ... 133))" bezeichnet wurde :eek:
[/OFF]
 
Der Code funktioniert zwar super bis auf eine Kleinigkeit. Und zwar ist es ja möglich im id3v2 die Cover bzw Inlets mit anzugeben. Doch beim auslesen mit obigem Code eines solchen id3v2-Tags stehen dann unter den allgemeinen Informationen (album, interpret etc...) nur lauter seltsame Zeichen. Denke das sollen die Bildinformationen sein. Aber damit kann ich nix anfangen.

Hallo!
Hab zwar ID3Tags bisher nur in Verbindung mit Java bearbeitet, aber ich habe eine Vermutung warum du nur lauter seltsame Zeichen erhältst: bei ID3Tags der Version 2 ist es möglich den Zeichensatz selber zu wählen. Mögliche Zeichensätze waren Iso-Latin-1, UTF-8 und zwei UTF-16 Zeichensätze glaub ich. Wenn du also einen Wert des Tags ausliest, aber im falschen Zeichensatz darstellst erhältst du eben soeinen Zeichensalat. Wie gesagt ist nur eine Vermutung, am besten nimmst du eine MP3, löscht sämtliche ID3-Tags und speicherst dann nur den ID3v2 Tag. Mit dieser kannst du dann Testen ob das Skript überhaupt richtig funktioniert. Bein Überfliegen habe ich nämlich niergends eine Konvertierung des Zeichensatzes gefunden.
By the way: mit Hilfe eines Hex-Editors ist es auch möglich sich die Tags anzuschauen.
Btw2: viele Mp3s mit Bild habe ich nicht, aber in irgendeinem Editor ist mir mal eine Mp3 mit Bild aufgefallen. Dieses muss wohl mit in der Mp3 gespeichert gewesen sein.

mfg flo
 
Hallo Olli,

Der Code funktioniert zwar super bis auf eine Kleinigkeit. Und zwar ist es ja möglich im id3v2 die Cover bzw Inlets mit anzugeben. Doch beim auslesen mit obigem Code eines solchen id3v2-Tags stehen dann unter den allgemeinen Informationen (album, interpret etc...) nur lauter seltsame Zeichen. Denke das sollen die Bildinformationen sein. Aber damit kann ich nix anfangen.
Ja, das sind die Bildinformationen. Bilder (außer SVG) sind Binärdateien. Binärdateien verwenden 8 Bit, wodurch Bytewerte außerhalb des ASCII-Bereichs (0-127) auftreten können. Dazu kommt, dass der ASCII-Zeichensatz selber 33 nicht-druckbare Zeichen enthält.

Lässt sich das irgendwie in brauchbare Informationen wandeln. Welche Informationen werden zu den Bildern überhaupt in dem id3v2 tag gespeichert.
Das steht alles in der Spezifikation des ID3-Tags:
Code:
4.14.   Attached picture

   This frame contains a picture directly related to the audio file.
   Image format is the MIME type and subtype [MIME] for the image. In
   the event that the MIME media type name is omitted, "image/" will be
   implied. The "image/png" [PNG] or "image/jpeg" [JFIF] picture format
   should be used when interoperability is wanted. Description is a
   short description of the picture, represented as a terminated
   text string. There may be several pictures attached to one file, each
   in their individual "APIC" frame, but only one with the same content
   descriptor. There may only be one picture with the picture type
   declared as picture type $01 and $02 respectively. There is the
   possibility to put only a link to the image file by using the 'MIME
   type' "-->" and having a complete URL [URL] instead of picture data.
   The use of linked files should however be used sparingly since there
   is the risk of separation of files.

     <Header for 'Attached picture', ID: "APIC">
     Text encoding      $xx
     MIME type          <text string> $00
     Picture type       $xx
     Description        <text string according to encoding> $00 (00)
     Picture data       <binary data>


   Picture type:  $00  Other
                  $01  32x32 pixels 'file icon' (PNG only)
                  $02  Other file icon
                  $03  Cover (front)
                  $04  Cover (back)
                  $05  Leaflet page
                  $06  Media (e.g. label side of CD)
                  $07  Lead artist/lead performer/soloist
                  $08  Artist/performer
                  $09  Conductor
                  $0A  Band/Orchestra
                  $0B  Composer
                  $0C  Lyricist/text writer
                  $0D  Recording Location
                  $0E  During recording
                  $0F  During performance
                  $10  Movie/video screen capture
                  $11  A bright coloured fish
                  $12  Illustration
                  $13  Band/artist logotype
                  $14  Publisher/Studio logotype


Hier eine Implementierung, die alle Angaben ausliest und das Bild in eine Datei schreibt:
PHP:
while($CurPos < $HeaderLength + 10):
	$FrameName = substr($ID3Header, $CurPos, 4);
	if(trim($FrameName) != ""):
		$FrameLength = toNumber(substr($ID3Header, $CurPos+4, 4));
		$FrameContent = substr($ID3Header, $CurPos + 10, $FrameLength);
		$CurPos = $CurPos + $FrameLength + 10;

		if(array_key_exists($FrameName, $frames) == true):
			$header[$frames[$FrameName]] = $FrameContent;
		elseif($unuebliche_tags == true):
			if ($FrameName == "APIC")
			{
				// Textenkodierung auslesen (relevant fuer die Beschreibung)
				$textencoding = ord(substr($FrameContent, 0, 1));

				// Trennungszeichen bestimmen
				// 1 Byte fuer Latin1 und UTF8
				// 2 Bytes fuer UTF16 und UTF16BE
				$textdelimiter = chr(0);
				if ($textencoding == 1 || $textencoding == 2)
					$textdelimiter .= chr(0);

				$pos = 1;

				// Mimetype suchen (durch Nullbyte beendet)
				$k = strpos($FrameContent, chr(0), $pos);
				$mimetype = substr($FrameContent, $pos, $k - $pos);
				$pos = $k + 1;

				// Picture type
				$picture_type = ord(substr($FrameContent, $pos, 1));
				$pos++;

				// Beschreibung
				$k = strpos($FrameContent, $textdelimiter, $pos);
				if (strlen($textdelimiter) == 2 && ($k - $pos) % 2 != 0)
					$k++;

				$description = substr($FrameContent, $pos, $k - $pos);
				$pos = $k + strlen($textdelimiter);
				
				// Rest in Datei schreiben
				$filename = 'test.';
				if ($mimetype == 'image/png')
					$filename .= 'png';
				else if ($mimetype == 'image/jpeg')
					$filename .= 'jpg';

				file_put_contents($filename, substr($FrameContent, $pos));
			}

			$counter++;
			$header[$FrameName."_".$counter] = $FrameContent;
		endif;
	else:
		break;
	endif;
endwhile;
Das kannst du natürlich frei an deine Ansprüche anpassen. Wenn du z.B. nur das Bild haben willst, dann kannst du auch nur MIME-Type und das Bild auslesen und den Rest auslassen etc.

Deine Längenberechnung stimmte nicht (und war ziemlich umständlich), ich habe das durch folgende Funktion ersetzt:
PHP:
function toNumber($data) {
	$sum = 0;
	$last = strlen($data) - 1;

	for($i = 0; $i <= $last; $i++)
		$sum |= ord($data[$i]) << (($last - $i) * 8);

	return $sum;
}

Ich hoffe, dass dich das weiter bringt.

Gruß
Marvin
 
Vielen Dank für die ausführliche Antwort! Bin leider phpnewbie und muss gestehen das ich den Code nicht so wirklich verstehe.

Den Teil zum Auslesen vom id3v1 Tag kann ich ja noch nachvollziehen aber der Teil mit den Frames ....?.....

Habe jetzt mal folgenden Code getestet.

PHP:
<?php

/*
//===================================================\\
|                                                     |
|               ID-Tag Reader by Ansi                 |
|                                                     |
|          Reading IDv1.1 and IDv4.0 Tags             |
|                                                     |
|     if you want more frames to be read consult      |
|        http://www.id3.org/id3v2.3.0.html            |
|                                                     |
|                                                     |
\\===================================================//
*/
function toNumber($data) {
    $sum = 0;
    $last = strlen($data) - 1;

    for($i = 0; $i <= $last; $i++)
        $sum |= ord($data[$i]) << (($last - $i) * 8);

    return $sum;
}  



function readHeader($mp3){

// -------> Config <-------

$unuebliche_tags = true;    //gibt auch Tags aus, die von der üblichen Software *nicht* genutzt werden

// -------> Config <-------

    $header = array();

    //Liste der genutzen Frames für ID3v2.3 und deren
    //Rückgabe im $header[]- Array. Um Übersichtlichkeit
    //zu wahren werden alle Frames, die nicht in dieser
    //Liste stehen standardmäßig später *nicht* ausgegeben.
    $frames = array(
        'TPE1'    =>    'artist',
        'TALB'    =>    'album',
        'COMM'    =>    'comment',
        'TBPM'    =>    'bitrate',
        'TCON'    =>    'genre',
        'TCOM'    =>    'composer',
        'TDAT'    =>    'date',
        'TENC'    =>    'encoder',
        'TIT2'    =>    'title',
        'TIT3'    =>    'subtitle',
        'TLAN'    =>    'languages',
        'TLEN'    =>    'length',
        'TYER'    =>    'year',
        'TRCK'    =>    'track',
        'TORY'    =>    'year',
        'TCOP'    =>    'copyright');
    
    //Liste der Genres und ihrer Entsprechung
    $genres = array(
        0   => 'Blues',
        1   => 'Classic Rock',
        2   => 'Country',
        3   => 'Dance',
        4   => 'Disco',
        5   => 'Funk',
        6   => 'Grunge',
        7   => 'Hip-Hop',
        8   => 'Jazz',
        9   => 'Metal',
        10  => 'New Age',
        11  => 'Oldies',
        12  => 'Other',
        13  => 'Pop',
        14  => 'R&B',
        15  => 'Rap',
        16  => 'Reggae',
        17  => 'Rock',
        18  => 'Techno',
        19  => 'Industrial',
        20  => 'Alternative',
        21  => 'Ska',
        22  => 'Death Metal',
        23  => 'Pranks',
        24  => 'Soundtrack',
        25  => 'Euro-Techno',
        26  => 'Ambient',
        27  => 'Trip-Hop',
        28  => 'Vocal',
        29  => 'Jazz+Funk',
        30  => 'Fusion',
        31  => 'Trance',
        32  => 'Classical',
        33  => 'Instrumental',
        34  => 'Acid',
        35  => 'House',
        36  => 'Game',
        37  => 'Sound Clip',
        38  => 'Gospel',
        39  => 'Noise',
        40  => 'Alternative Rock',
        41  => 'Bass',
        42  => 'Soul',
        43  => 'Punk',
        44  => 'Space',
        45  => 'Meditative',
        46  => 'Instrumental Pop',
        47  => 'Instrumental Rock',
        48  => 'Ethnic',
        49  => 'Gothic',
        50  => 'Darkwave',
        51  => 'Techno-Industrial',
        52  => 'Electronic',
        53  => 'Pop-Folk',
        54  => 'Eurodance',
        55  => 'Dream',
        56  => 'Southern Rock',
        57  => 'Comedy',
        58  => 'Cult',
        59  => 'Gangsta',
        60  => 'Top 40',
        61  => 'Christian Rap',
        62  => 'Pop/Funk',
        63  => 'Jungle',
        64  => 'Native US',
        65  => 'Cabaret',
        66  => 'New Wave',
        67  => 'Psychadelic',
        68  => 'Rave',
        69  => 'Showtunes',
        70  => 'Trailer',
        71  => 'Lo-Fi',
        72  => 'Tribal',
        73  => 'Acid Punk',
        74  => 'Acid Jazz',
        75  => 'Polka',
        76  => 'Retro',
        77  => 'Musical',
        78  => 'Rock & Roll',
        79  => 'Hard Rock',
        80  => 'Folk',
        81  => 'Folk-Rock',
        82  => 'National Folk',
        83  => 'Swing',
        84  => 'Fast Fusion',
        85  => 'Bebob',
        86  => 'Latin',
        87  => 'Revival',
        88  => 'Celtic',
        89  => 'Bluegrass',
        90  => 'Avantgarde',
        91  => 'Gothic Rock',
        92  => 'Progressive Rock',
        93  => 'Psychedelic Rock',
        94  => 'Symphonic Rock',
        95  => 'Slow Rock',
        96  => 'Big Band',
        97  => 'Chorus',
        98  => 'Easy Listening',
        99  => 'Acoustic',
        100 => 'Humour',
        101 => 'Speech',
        102 => 'Chanson',
        103 => 'Opera',
        104 => 'Chamber Music',
        105 => 'Sonata',
        106 => 'Symphony',
        107 => 'Booty Bass',
        108 => 'Primus',
        109 => 'Porn Groove',
        110 => 'Satire',
        111 => 'Slow Jam',
        112 => 'Club',
        113 => 'Tango',
        114 => 'Samba',
        115 => 'Folklore',
        116 => 'Ballad',
        117 => 'Power Ballad',
        118 => 'Rhytmic Soul',
        119 => 'Freestyle',
        120 => 'Duet',
        121 => 'Punk Rock',
        122 => 'Drum Solo',
        123 => 'Acapella',
        124 => 'Euro-House',
        125 => 'Dance Hall',
        126 => 'Goa',
        127 => 'Drum & Bass',
        128 => 'Club-House',
        129 => 'Hardcore',
        130 => 'Terror',
        131 => 'Indie',
        132 => 'BritPop',
        133 => 'Negerpunk',
        134 => 'Polsk Punk',
        135 => 'Beat',
        136 => 'Christian Gangsta Rap',
        137 => 'Heavy Metal',
        138 => 'Black Metal',
        139 => 'Crossover',
        140 => 'Contemporary Christian',
        141 => 'Christian Rock',
        142 => 'Merengue',
        143 => 'Salsa',
        144 => 'Trash Metal',
        145 => 'Anime',
        146 => 'Jpop',
        147 => 'Synthpop');

    //MP3 einlesen
    $filelength = filesize($mp3);
    $hdl = fopen($mp3, "rb");
    if($hdl):
            $content .= fread($hdl, $filelength);
        fclose($hdl);
    endif;

    //Versuche ID3v2 Tag zu finden
    $IDTag = strpos($content, "ID3");

    //Wenn ID3v2 nicht gefunden wird nach ID3v1
    //suchen, entspricht TAG
    if($IDTag === false):
        $IDTag = strpos($content, "TAG");        
        if($IDTag === false):
            $header['type'] = "kein Header gefunden";
            return $header;
            exit;
        else:
            $header['type'] = "ID3v1";
            //$header['pos'] = $IDTag;
        endif;
    else:
        $header['type'] = "ID3v2";
        //$header['pos'] = $IDTag;
    endif;

    switch ($header['type']):
        //ID3v2 Tags auslesen: Flexiblere Felder
        case "ID3v2":
            //10 Byte des ID3 Headers auslesen
            $ID3Header = substr($content, $IDTag, 10);
            
            //Exakte Version der genutzen ID3v2 Version ermitteln
            $header['type'] .= ".".ord(substr($ID3Header, 3, 1)).".".ord(substr($ID3Header, 4, 1));
            
            //Gesamte Headerlänge inklusive Frames ermitteln
            $HeaderLength =  265 * 8 * 8 * ord(substr($ID3Header, 6, 1)) + 265 * 8 * ord(substr($ID3Header, 7, 1)) + 265 *  ord(substr($ID3Header,  8, 1)) + ord(substr($ID3Header,  9, 1));
            
            //ID3 Header in Variabel ablegen, $content leeren
            $ID3Header = substr($content, $IDTrag, $HeaderLength + 10);
            $content = "";

            //Startposition für Frameerkennung ist Byte 10
            $CurPos = 10;
            
            //So lange Frames suchen / auslesen, bis eine Frameposition
            //leer ist oder der Header durchlaufen wurde
while($CurPos < $HeaderLength + 10):
    $FrameName = substr($ID3Header, $CurPos, 4);
    if(trim($FrameName) != ""):
        $FrameLength = toNumber(substr($ID3Header, $CurPos+4, 4));
        $FrameContent = substr($ID3Header, $CurPos + 10, $FrameLength);
        $CurPos = $CurPos + $FrameLength + 10;

        if(array_key_exists($FrameName, $frames) == true):
            $header[$frames[$FrameName]] = $FrameContent;
        elseif($unuebliche_tags == true):
            if ($FrameName == "APIC")
            {
                // Textenkodierung auslesen (relevant fuer die Beschreibung)
                $textencoding = ord(substr($FrameContent, 0, 1));

                // Trennungszeichen bestimmen
                // 1 Byte fuer Latin1 und UTF8
                // 2 Bytes fuer UTF16 und UTF16BE
                $textdelimiter = chr(0);
                if ($textencoding == 1 || $textencoding == 2)
                    $textdelimiter .= chr(0);

                $pos = 1;

                // Mimetype suchen (durch Nullbyte beendet)
                $k = strpos($FrameContent, chr(0), $pos);
                $mimetype = substr($FrameContent, $pos, $k - $pos);
                $pos = $k + 1;

                // Picture type
                $picture_type = ord(substr($FrameContent, $pos, 1));
                $pos++;

                // Beschreibung
                $k = strpos($FrameContent, $textdelimiter, $pos);
                if (strlen($textdelimiter) == 2 && ($k - $pos) % 2 != 0)
                    $k++;

                $description = substr($FrameContent, $pos, $k - $pos);
                $pos = $k + strlen($textdelimiter);
                
                // Rest in Datei schreiben
                $filename = 'test.';
                if ($mimetype == 'image/png')
                    $filename .= 'png';
                else if ($mimetype == 'image/jpeg')
                    $filename .= 'jpg';

                file_put_contents($filename, substr($FrameContent, $pos));
            }

            $counter++;
            $header[$FrameName."_".$counter] = $FrameContent;
        endif;
    else:
        break;
    endif;
endwhile;  

        //Hier wird der ID3V1.1 Standard vorausgesetzt,
        //der im letzten Byte des Kommentares (127) den Track speichert
        case "ID3v1.1":
            $header['titel'] = trim(substr($content, $IDTag + 3, 30));
            $header['artist'] = trim(substr($content, $IDTag + 33, 30));
            $header['album'] = trim(substr($content, $IDTag + 63, 30));
            $header['year'] = trim(substr($content, $IDTag + 93, 4));
            $header['comment'] = trim(substr($content, $IDTag + 97, 29));
            $header['track'] = ord(trim(substr($content, $IDTag + 126, 1)));
            $header['genre'] = ord(trim(substr($content, $IDTag + 127, 1)));
            if(!$header['genre'] === false):
                $header['genre'] = $genres[$header['genre']];
            endif;
            break;
    endswitch;

    return $header;

}



$ausgabe=readHeader('LeAnn Rimes\2004 The Best Of\04 - LeAnn Rimes - I Need You.mp3');


print_r($ausgabe);




?>






Doch bei der Ausgabe des arrays steht in APIC_1 wieder nur Zeichen:

Aber denke eher das ich den Code nicht ganz richtig zusammen gebastelt hab!?




Sorry das ich als nachfragen muss, mfg Olli



Halt, jetzt habe ich festgestellt das ein Bild test.jpg in dem Ordner erstellt wurde. Allerdings ist das Bild nur zur Hälfte auufgebaut.
Sorry wenn ich jetzt frage aber warum erstellt er mir ein neues Bild.... Möchte doch nur den Pfad zum OriginalCover in einer Variable gespeichert haben.


Mensch das ist echt kompliziert...
 
Zuletzt bearbeitet:
Moin,

Halt, jetzt habe ich festgestellt das ein Bild test.jpg in dem Ordner erstellt wurde. Allerdings ist das Bild nur zur Hälfte auufgebaut.
Sorry wenn ich jetzt frage aber warum erstellt er mir ein neues Bild.... Möchte doch nur den Pfad zum OriginalCover in einer Variable gespeichert haben.

Es gibt in dem Sinne kein "Original-Cover". Das Cover wird mit Hilfe der 'Attached picture'-Frame des ID3-Tags in die MPEG-Datei eingebettet. Sprich du musst es erst auslesen und speichern. Danach kannst du den Pfad zum gespeicherten Bild anstelle des Frame-Inhaltes zum Array hinzufügen.

Dass es nur zur Hälfte ausgelesen wird, liegt an folgender Zeile:
PHP:
$HeaderLength =  265 * 8 * 8 * ord(substr($ID3Header, 6, 1)) + 265 * 8 * ord(substr($ID3Header, 7, 1)) + 265 *  ord(substr($ID3Header,  8, 1)) + ord(substr($ID3Header,  9, 1));
Die Berechnung stimmt nicht, weswegen er vorzeitig aufhört den Tag auszulesen.
Hierfür kannst du wieder die toNumber-Funktion nutzen:
PHP:
$HeaderLength =  toNumber(substr($ID3Header, 6, 4));

Gruß
Marvin
 

Neue Beiträge

Zurück