Ich habe mich mal rangesetzt und ein Modul programmiert, dass die ID3-Tags aus MPEG-Dateien auslesen kann.
Es werden die Versionen v1.0, v1.1 und v2.3 und v2.4 (eingeschränkt) unterstützt und dabei werden die wichtigsten ID3-Frames ausgelesen.
Edit 13.07.2020: Komplett neue Version (deswegen auch die Änderung des Threadtitels).
- Es werden jetzt nicht nur die ID3-Frames ausgelesen, sondern auch noch der MPEG-Header analysiert (Bitrate, Kodiermethode, Samlingfrequenz, Laufzeit, etc.).
- Fast komplett neu geschrieben. Der Code ist jetzt sehr Objektorientiert. Das erleichert die Verwendung, weil alle Daten im Objekt enthalten sind.
- DIe benutzen Konstanten (Arrays) sind jetzt in einer extra Datei untergebracht ("ooMPEGconstants.nim").
- Ich habe den Code ausführlich kommentiert. Hauptsächlich, damit ich mich selbst, nach einem Jahr oder so, noch daran erinnern kann, was ich da geschrieben habe, aber vielleicht ist das ja auch für euch hilfreich.
Edit 18.08.2020: So einiges entdeckt man erst, wenn man die Funktionen auf zahlreiche MP3s loslässt.
- Bug, beim ID3v1.x Format. Dort konnte ein Array-Überlauf passieren, wenn die Genrenummer >126 war. Behoben!
- Man kann jetzt als ID3-Versionsnummer auch "0" angeben. In dem Fall wird versucht, erst die ID3v2.x Daten zu laden und wenn die nicht vorhanden sind, dann ID3v1.x.
- Wenn beim ID3v1.x Format zwar die "TAG"-Kennung vorhanden ist, aber dann keine Daten vorhanden sind, kommt es nun zum "Fallback" auf den Dateinamen.
- Wenn beim ID3v2.x Format die Größe eines Frames 0 Bytes beträgt, wird der Frame jetzt übersprungen (fehlerhafte ID3-Daten).
- Wenn nach dem ID3v2.x Tag nicht gleich ein MPEG-Header folgt, sondern erst einige Bytes später, wurde die MP3-Datei als "nicht gültig" angesehen. Behoben!
- Wenn keinerlei ID3-Daten vorhanden sind, erfolgt ein "Fallback" auf die Daten im Dateinamen (mit Separator-Split). Jetzt gibt es noch ein letztes "Fallback" (wenn auch der Separator nicht gefunden wird). Es wird dann der Dateiname (ohne Endung) als Interpret eingetragen.
Hier mal das Beispielprogramm:
import ooMPEG, wNim
echo "Unterstuetzte Frames (", aID3v2Frames.len, "): ", aID3v2Frames
let mpeg = MPEGinfo() # MPEGinfo-Objekt erstellen
# Mit "readInfo" wird die uebergebene MPEG-Datei eingelesen und analysiert.
# Die Daten befinden sich dann im Objekt und koennen benutzt werden.
# Parameter: Dateiname, gewuenschte ID3-Version, Trennzeichen
# Die Trennzeichen dienen dazu, Interpret und Titel auch dann zu ermitteln,
# wenn *keine* ID3-Daten gespeichert sind.
# Dabei wird versucht, die Daten anhand des Dateinamens zu ermitteln.
# Der Dateiname muss dieses Format aufweisen: <Interpret><Trennzeichen><Titel>
if mpeg.readInfo("Status Quo - Whatever You Want.mp3", 0, " - "):
echo "MPEG-Version: ", mpeg.Version
echo "MPEG-Layer: ", mpeg.Layer
echo "MPEG-Methode: ", mpeg.CompMethod
echo "MPEG-Bitrate: ", mpeg.Bitrate, " kBit/s"
echo "Samplingfreq: ", mpeg.Samplingrate, " kHz"
echo "Dateigroesse: ", mpeg.Filesize, " Bytes"
echo "Musikgroesse: ", mpeg.Datasize, " Bytes"
echo "ID3-Version: ", mpeg.ID3version
echo "ID3-Frames: ", mpeg.getID3frames
echo "Encoded by: ", mpeg.getID3value("TENC")
echo "Interpret: ", mpeg.getID3value("TPE1")
echo "Titel: ", mpeg.getID3value("TIT2")
echo "Album: ", mpeg.getID3value("TALB")
echo "Track: ", mpeg.getID3value("TRCK")
echo "Jahr: ", mpeg.getID3value("TYER")
echo "Genre: ", mpeg.getID3value("TCON")
echo "Laufzeit: ", mpeg.Duration, " Millisekunden"
echo "Laufzeit: ", mpeg.DurationString, " (mm:ss)"
echo "Bilderanzahl: ", mpeg.ApicCount
let apic1 = mpeg.getID3data("APIC2") # Binaerdaten des Bildes holen
# Zum testen, ob das APIC-Bild korrekt ausgelesen wird
let app = App()
let frame = Frame(title="Test", size=(640, 480))
let panel = Panel(frame)
let idPic = StaticBitmap(panel, size=(260, 260), pos=(10, 10), style=wSbCenter)
idPic.setBackgroundColor(0x004A1A1A)
let idInterpret = StaticText(panel, label=mpeg.getID3value("TPE1"), size=(360, 60), pos=(280, 30))
idInterpret.font = Font(14, faceName="Arial", weight=wFontWeightNormal)
let idTitle = StaticText(panel, label=mpeg.getID3value("TIT2"), size=(360, 60), pos=(280, 60))
idTitle.font = Font(14, faceName="Arial", weight=wFontWeightNormal)
if apic1.len > 0:
let myImage = Image(apic1) # die Binaerdaten in ein Image umwandeln
var sw, sh: int = 240 # Zielgroesse 240x240 px
let h = myImage.height # momentane hoehe
let w = myImage.width # und breite
if h > w: sw = 240 - (h - 240) # wenn hoehe groesser, dann die breite anpassen
if h < w: sh = 240 - (w - 240) # wenn breite groesser, dann die hoehe anpassen
let scaleImage = myImage.scale(sw, sh) # Image skalieren (legt eine Kopie an)
idPic.bitmap = Bitmap(scaleImage) # und dem Bitmap-Control zuweisen
frame.center()
frame.show()
app.mainLoop()
Alles anzeigen
Alles nochmal im ZIP-Archiv (Anhang) zum herunterladen.