Autor |
Beitrag |
stigge
      
Beiträge: 426
WinXP
Delphi 2007
|
Verfasst: Mo 05.02.07 20:53
Wie kann ich die Länge eines MP3-Liedes herausfinden?
Mit mediaplayer1.length bekomme ich oft falsche Ergebnisse.
Kann man die Länge irgendwie aus den ID3-Sachen rausbekommen oder so?
Bitte helft mir!
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mo 05.02.07 21:09
Im ID3-Tag steht die Länge leider nicht drin. Mit etwas Overkill kann man meine Unit MP3FileUtils dafür benutzen. Beispielanwendungen liegen dabei. Diese Unit kann auch den ID3-Tag lesen und schreiben.
Und wenns wirklich nur um die Länge geht, dann kannst du einen Großteil des Codes wegschmeißen  . Schau dir mal die Klasse TMpegInfo in der Unit an, das ist das, was für dich wichtig ist.
Ich glaube, ich muss mal irgendwann ne FAQ machen, wo ich den Code dafür entsprechend zurecht kürze ... 
_________________ We are, we were and will not be.
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Mo 05.02.07 21:16
kann man sich nicht auch von der Mediaplayer komponente die länge in millisekunden ausgeben lassen. da muss man zuerst aber glaub ich Mediaplayer1.Timeformat:=tfmilliseconds o.ä. vor label1.caption:=inttostr(mediaplayer1.length) schreiben
lg el
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mo 05.02.07 21:41
So...ich hatte grade mal nix zu tun, bzw. braucht mal ne Abwechslung, da hab ich mal aus der Monster-Unit das wichtigste rauskopiert und in ein kleines Projekt eingefügt.
Die Klasse TMpegInfo ist komplett enthalten, die weiter zu kürzen macht kaum Sinn, da man für die Längenberechnung eh fast alles braucht, was da so nebenbei mit bestimmt wird.
Die Länge des ID3v2-Tags wird möglicherweise um 10 Byte verfälscht bestimmt, aber das hat auf das Ergebnis keinen Einfluss (die Größe wird eh nur dafür benutzt, um schneller den Anfang der Musik zu finden).
Viel einfacher gehts nicht - es sei denn man greift auf Mediaplayer oder bass.dll zurück, aber das ist langsamer  .
Einloggen, um Attachments anzusehen!
_________________ We are, we were and will not be.
|
|
stigge 
      
Beiträge: 426
WinXP
Delphi 2007
|
Verfasst: Mo 05.02.07 22:02
Ich hab's mir jetzt mal gedownloadet, werde es aber erst morgen mittag ausprobieren.
|
|
stigge 
      
Beiträge: 426
WinXP
Delphi 2007
|
Verfasst: Mo 05.02.07 22:42
Hab's doch schon jetzt angeschaut....und ich verstehe nichts^^. Wo ist den hier der Teil mit der Länge des Titels? Eventuell hier:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| procedure TForm1.Button1Click(Sender: TObject); var stream: TFilestream; TagSize: Integer; MpegInfo: TMpegInfo; begin
if opendialog1.Execute then begin stream := TFileStream.Create(opendialog1.FileName, fmOpenRead or fmShareDenyWrite);
TagSize := GetID3v2Size(stream);
stream.Seek(TagSize, soFromBeginning);
MpegInfo := TMpegInfo.create; MpegInfo.LoadFromStream(Stream);
Label1.Caption := IntTostr(MpegInfo.dauer) + ' Sekunden';
MpegInfo.free; Stream.free; end; end; |
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mo 05.02.07 23:01
Ich probier mal, ob ich das einigermaßen hinbekomme  - das ist nämlich wirklich nicht so einfach. Problem ist, dass die Dauer eines Stückes nirgendwo in der Datei steht, so dass man sie nicht auslesen, sondern aus den Daten zusammenfriemeln muss.
Eine mp3-Datei besteht aus vielen sogenannten Frames, das sind kleine Einheiten an Audio-Information. Jeder Frame besitzt einen 4-Byte großen Header. in diesen 4 Byte (=32 Bit) sind Informationen über Bitrate, Samplerate, Channelmode und einigem mehr vorhanden. Da diese Infos sehr platzsparend gespeichert werden sollen (So eine mp3 hat mehrere tausend Frames), müssen die echten Werte (z.B. 192 kbit/s) anhand von Tabellen aus dem Bitmuster herausgefriemelt werden. Dafür sind diese Arrays am Anfang.
Zusätzlich kann man nie sagen, wo der erste MPEG-Header anfängt, so dass man ihn erst suchen muss (man erkennt ihn an elf hintereinanderfolgenden Einsen, d.h. 11 von den 32 Bits gehen schon für diese Markierung drauf), und auch dann muss eine Überprüfung stattfinden, ob die restlichen Nullen und Einsen einen gültigen MPEG-Header bilden, denn nicht alle Kombinationen sind erlaubt.
Aus den Daten Bitrate, Samplerate sowie Version und Layer (das ist bei mp3 meistens 1 und 3, mp3 steht ja für MPEG Version1, Layer3), die man aus dem Header gewinnen kann, lässt sich die Länge des Frames berechnen. Wenn man konstante Bitrate hat, kann man dann zusammen mit der Dateigröße (minus evtl. der ID3-Tag-Größe) die Anzahl der Frames berechnen. Da ein Frame eine vordefinierte Spieldauer hat, kommt man dann an die Dauer des Liedes.
Wenn man nun variable Bitrate hat, dann kann jeder Frame eine andere Länge haben. Um die Länge dann 100%ig korrekt zu bestimmen, müsste man die ganze Datei durchsuchen und sich von Frame zu Frame hangeln und mitzählen - das dauert recht lange. Fast immer ist bei vbr-Dateien allerdings der erste MPEG-Frame gar kein echter MPEG-Frame, sondern ein sog. XING-Header, in dem die Anzahl der Frames drinsteht. Das nutze ich aus, um bei vbr die Dauer zu berechnen (das funktioniert auch in 99.99%).
Das ist alles etwas friemelig, aber wenn mans einmal hat, kann man das einfach benutzen. Ich habe das in eine Klasse gepackt, die sich einfach benutzen lässt. Der Code dafür ist im Button1.Click untergebracht. Einfach ne Klasseninstanz erzeugen, LoadfromStream aufrufen und dann auf die ermittelten Infos zugreifen.
_________________ We are, we were and will not be.
|
|
stigge 
      
Beiträge: 426
WinXP
Delphi 2007
|
Verfasst: Mo 05.02.07 23:06
Die Anwendung lässt sich nicht einmal starten^^
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mo 05.02.07 23:10
Bei mir läuft das durch, was kommt denn für ne Fehlermeldung?
_________________ We are, we were and will not be.
|
|
stigge 
      
Beiträge: 426
WinXP
Delphi 2007
|
Verfasst: Di 06.02.07 14:18
Ich bekomme einen Fehler beim Öffnen:
Damit dieses Projekt geöffnet werden kann, ist ein Upgrade erforderlich.
Dann klicke auf ok und alles öffnet sich wie gewohnt.
Wenn ich es nun starten möchte, bekomme ich folgende Fehler:
[Warnung] Unit1.pas(155): W1000 Symbol 'soFromBeginning' ist veraltet
[Fehler] Unit1.pas(156): E2250 Es gibt keine überladene Version von 'ReadBuffer', die man mit diesen Argumenten aufrufen kann
[Warnung] Unit1.pas(508): W1000 Symbol 'soFromBeginning' ist veraltet
[Fataler Fehler] Project1.dpr(7): F2063 Verwendete Unit 'Unit1.pas' kann nicht compiliert werden
Ich benutze übrigens Delphi 2005.
|
|
stigge 
      
Beiträge: 426
WinXP
Delphi 2007
|
Verfasst: Sa 17.02.07 19:05
Die Frage besteht übrigens weiterhin 
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Sa 17.02.07 19:17
stigge hat folgendes geschrieben: | Die Frage besteht übrigens weiterhin  |
Hallo,
wie wärs wenn du
a) den Quelltext um die Zeile 156 mal postest (da ist der einzige Fehler) und
b) dann die Aufrufzeile von ReadBuffer zeigst. Da du ja die Architect Version hast, kannst du mit rechtsclick->Im Quelltext anzeigen o.Ä. direkt den Quelltext der Prozedur anschauen und kannst dann den Prozeduraufruf rauskopieren. Oder du suchst in der Hilfe aus.
Er sollte irgendwie so aussehen:
Delphi-Quelltext 1:
| procedure ReadBuffer(bla...); |
Gruß Hape!
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
stigge 
      
Beiträge: 426
WinXP
Delphi 2007
|
Verfasst: Sa 17.02.07 19:27
Ich glaube es ist besser, wenn ich die Sache lasse
Ich habe nämlich keine Ahnung mehr, was ich da die ganze Zeit mache.
Die Frage ist sozusagen beantwortet.
Danke für die Hilfe
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Sa 17.02.07 19:40
stigge hat folgendes geschrieben: | Ich habe nämlich keine Ahnung mehr, was ich da die ganze Zeit mache. |
Nicht gleich aufgeben! Es ist kein Verbrechen Komponenten/Units zu benutzen die man nicht versteht, sondern nur deren "Schnittstelle"!
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
stigge 
      
Beiträge: 426
WinXP
Delphi 2007
|
Verfasst: Sa 17.02.07 19:50
Ich weiß ja nicht einmal, was ich jetzt überhaupt kopieren muss!
|
|
ZeitGeist87
      
Beiträge: 1593
Erhaltene Danke: 20
Win95-Win10
Delphi 10 Seattle, Rad Studio 2007, Delphi 7 Prof., C++, WSH, Turbo Pascal, PHP, Delphi X2
|
Verfasst: Sa 17.02.07 20:35
Hallo!
Funtioniert bei mir wunderbar:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| procedure get_Spieldauer(Player: TMediaPlayer; Var Minuten: String; Var Sekunden: String); Var track_length, _Position,SummaMin,SummaSec: Integer; begin
player.Open;
track_length:= player.TrackLength[0];
_Position:= player.Position;
SummaMin:= ((Track_length - _Position) div 1000) Div 60;
SummaSec:= ((Track_length - _Position) Div 1000) Mod 60;
If SummaSec < 10 Then Sekunden:= '0' + IntToStr(SummaSec) Else Sekunden:= IntToStr(SummaSec);
player.Close;
Minuten:= IntToStr(SummaMin); end;
procedure TForm1.Button1Click(Sender: TObject); var minuten, sekunden: string; begin get_Spieldauer(mediaplayer1, minuten, sekunden); caption:= Minuten + ':' + Sekunden; end;
procedure TForm1.Button1Click(Sender: TObject); var minuten, sekunden: string; begin get_Spieldauer(mediaplayer1, minuten, sekunden); caption:= Minuten + ':' + Sekunden; end; |
LG
Stefan
_________________ Wer Provokationen, Ironie, Sarkasmus oder Zynismus herauslesen kann soll sie ignorieren um den Inhalt meiner Beiträge ungetrübt erfassen zu können.
|
|
stigge 
      
Beiträge: 426
WinXP
Delphi 2007
|
Verfasst: Mi 14.03.07 20:50
Gausi hat folgendes geschrieben: | So...ich hatte grade mal nix zu tun, bzw. braucht mal ne Abwechslung, da hab ich mal aus der Monster-Unit das wichtigste rauskopiert und in ein kleines Projekt eingefügt.
Die Klasse TMpegInfo ist komplett enthalten, die weiter zu kürzen macht kaum Sinn, da man für die Längenberechnung eh fast alles braucht, was da so nebenbei mit bestimmt wird.
Die Länge des ID3v2-Tags wird möglicherweise um 10 Byte verfälscht bestimmt, aber das hat auf das Ergebnis keinen Einfluss (die Größe wird eh nur dafür benutzt, um schneller den Anfang der Musik zu finden).
Viel einfacher gehts nicht - es sei denn man greift auf Mediaplayer oder bass.dll zurück, aber das ist langsamer . |
Habs jetzt endlich zum Laufen bekommen^^ Danke!
|
|
|