Autor Beitrag
stigge
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 426

WinXP
Delphi 2007
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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 ... :gruebel:

_________________
We are, we were and will not be.
elundril
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3747
Erhaltene Danke: 123

Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 426

WinXP
Delphi 2007
BeitragVerfasst: Mo 05.02.07 22:02 
Ich hab's mir jetzt mal gedownloadet, werde es aber erst morgen mittag ausprobieren.
stigge Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 426

WinXP
Delphi 2007
BeitragVerfasst: 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:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mo 05.02.07 23:01 
Ich probier mal, ob ich das einigermaßen hinbekomme :lol: - 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 426

WinXP
Delphi 2007
BeitragVerfasst: Mo 05.02.07 23:06 
Die Anwendung lässt sich nicht einmal starten^^
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 426

WinXP
Delphi 2007
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 426

WinXP
Delphi 2007
BeitragVerfasst: Sa 17.02.07 19:05 
Die Frage besteht übrigens weiterhin :oops:
wulfskin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: Sa 17.02.07 19:17 
user profile iconstigge hat folgendes geschrieben:
Die Frage besteht übrigens weiterhin :oops:
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:
ausblenden Delphi-Quelltext
1:
procedure ReadBuffer(bla...);					


Gruß Hape!

_________________
Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
stigge Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 426

WinXP
Delphi 2007
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: Sa 17.02.07 19:40 
user profile iconstigge 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 426

WinXP
Delphi 2007
BeitragVerfasst: Sa 17.02.07 19:50 
Ich weiß ja nicht einmal, was ich jetzt überhaupt kopieren muss!
ZeitGeist87
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1593
Erhaltene Danke: 20

Win95-Win10
Delphi 10 Seattle, Rad Studio 2007, Delphi 7 Prof., C++, WSH, Turbo Pascal, PHP, Delphi X2
BeitragVerfasst: Sa 17.02.07 20:35 
Hallo!

Funtioniert bei mir wunderbar:

ausblenden volle Höhe 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:
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: StringVar Sekunden: String);
Var track_length, _Position,SummaMin,SummaSec: Integer;
begin

 player.Open;

 //Länge des Tracks
 track_length:= player.TrackLength[0];

 //Aktuelle Position des Tracks
 _Position:= player.Position;

 //Minuten Berechnen
 SummaMin:= ((Track_length - _Position) div 1000Div 60;

 //Sekunden Berechnen
 SummaSec:= ((Track_length - _Position) Div 1000Mod 60;

 //0 bei Sekunden hinzufügen wenn Sekunden < 10
 //Ausgabe Sekunden
 If SummaSec < 10 Then
  Sekunden:= '0' + IntToStr(SummaSec)
 Else
  Sekunden:= IntToStr(SummaSec);

 player.Close;

 //Ausgabe Minuten
 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 426

WinXP
Delphi 2007
BeitragVerfasst: Mi 14.03.07 20:50 
user profile iconGausi 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!