Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi DSPack : Länge von Lied vor Abspielen herausbekommen (https://www.delphipraxis.net/85558-dspack-laenge-von-lied-vor-abspielen-herausbekommen.html)

Nils_13 1. Feb 2007 14:33


DSPack : Länge von Lied vor Abspielen herausbekommen
 
Hi,

wie kann man mit dem DSPack die Länge eines beliebigen Liedes, bevor man es abspielt, herausfinden bzw. auf eine Variable zuweisen ? Ich habe keine Befehle gefunden, welche dies "im Vorraus" erledigen könnten.

EWeiss 1. Feb 2007 15:06

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Zitat:

Zitat von Nils_13
Hi,

wie kann man mit dem DSPack die Länge eines beliebigen Liedes, bevor man es abspielt, herausfinden bzw. auf eine Variable zuweisen ? Ich habe keine Befehle gefunden, welche dies "im Vorraus" erledigen könnten.

KA
Aber ich weiss das es über MPEGInfo geht.

EDIT:
Und beliebig geht gar nicht.
Immer abhängig vom Dateityp

gruss

Nils_13 1. Feb 2007 16:50

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Ich brauche die Länge von .mpeg, .wmv, .avi, .dat. MPEG hast du eben schon genannt, werde mich gleich drumkümmern. DAT ist nichts anderes als MPEG. Wie steht es allerdings mit WMV und AVI ?

EWeiss 1. Feb 2007 18:14

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Zitat:

Zitat von Nils_13
Ich brauche die Länge von .mpeg, .wmv, .avi, .dat. MPEG hast du eben schon genannt, werde mich gleich drumkümmern. DAT ist nichts anderes als MPEG. Wie steht es allerdings mit WMV und AVI ?

Bei
"WMV", "WMA", "RMI", "AVI", "ASF", "DAT", "WAV", "RM"
Kannst du die länge über FilgraphManager erfahren.

FilgraphManager befindet sich in der Typelib QuartzTypeLib Quartz.dll.

von meinen Projekt!
Code:
           
Set MediaControl = New FilgraphManager
If MediaControl Is Nothing Then
 MsgBox "Kann die Ojektlib Mediacontrol nicht erstellen"
 Exit Sub
End If
Set MediaPosition = MediaControl
MediaControl.RenderFile (strFullSongName)
SongTime = MediaPosition.Duration
strMin = SongTime \ 60
strSec = Int(SongTime - strMin * 60)
strX = format(strMin, "00") & ":" & format(strSec, "00")
CDA mußt du binär auslesen

"MPE", "MPEG", "MPG", "MOV", "3GP", "MID"
Kannst du über mci in erfahrung bringen

gruß

Garfield 17. Feb 2007 09:52

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Zitat:

Zitat von Nils_13
DAT ist nichts anderes als MPEG.

Das ist falsch. Wenn man eine DAT von VCD auf die Festplatte kopiert, werden nicht nur Daten des MPEG-1-Videos sondern die kompletten CD-Sektoren sowie der RIFF-Header mitkopiert. Somit hast Du einen RIFF-Header und 28 Byte pro Sektor zu viel.

EWeiss 17. Feb 2007 16:37

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
@Nils
Nimm dir mal die mmsystem unit wenn die noch nicht in dein projekt eingebunden ist
Damit kannst du die länge der songs / Videos einfach in erfahrung bringen.

MCI ist das schlagwort.

gruss

Nils_13 17. Feb 2007 17:06

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Und wie mit MCI ? Die Msdn-Hilfe hat nicht mal eine Liste aller Parameter oder ich bin blind :roll:

xaromz 17. Feb 2007 17:09

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Hallo,

wenn Du DirectShow verwenden willst, kannst Du folgende Funktion verwenden (Ergebnis in Millisekunden):
Delphi-Quellcode:
uses
  ActiveX, DirectShow9;

...

function GetDuration(const FileName: WideString): Cardinal;
var
  GB: IGraphBuilder;
  MediaSeeking: IMediaSeeking;
  RefTime: Int64;
begin
  Result := 0;

  if Succeeded(CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
      IID_IGraphBuilder, GB)) and
     Succeeded(GB.RenderFile(PWideChar(FileName), nil)) and
     Succeeded(GB.QueryInterface(IMediaSeeking, MediaSeeking)) then
  begin
    MediaSeeking.GetDuration(RefTime);
    Result := Cardinal(RefTime div 10000);
  end;
end;
Gruß
xaromz

Sunlight7 17. Feb 2007 17:11

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
MCI ist mit Vorsicht zu geniesen, weil nur 16 Bit und je nach Typ 1 oder 2 GB Dateibeschräkung.

EWeiss 17. Feb 2007 17:36

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Zitat:

Zitat von Sunlight7
MCI ist mit Vorsicht zu geniesen, weil nur 16 Bit und je nach Typ 1 oder 2 GB Dateibeschräkung.

Es geht doch nur darum die zeiten der einzelnen streans in erfahrung zu bringen.
Er will ja nichts damit abspielen.

Dabei spielt es keine rolle ob 16Bit oder 32. Oder?

@Nils ..
Wie das geht habe ich dir doch anhand eines Beispiel geschildert.

gruss

Sunlight7 17. Feb 2007 17:41

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Eben doch, da MCI auf 16 Bit aufsetzt und das hier beschriebene Problem auftaucht, das die Werte bei größeren Dateien nicht stimmen.

EWeiss 17. Feb 2007 17:55

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Zitat:

Zitat von Sunlight7
Eben doch, da MCI auf 16 Bit aufsetzt und das hier beschriebene Problem auftaucht, das die Werte bei größeren Dateien nicht stimmen.

Destotrotz er braucht nur einen befehl um die länge eines Titels in ms zu bekommen.
Dazu reicht

Error := mciSendString('status movie time format', Data, 128, 0);
getTimeFormat := Data

Das ist alles.

Data ist ein String wobei 128 der rückgabe wert des Strings in einer länge von 128 ist.
Und Songs mit einer größe von 2GB hab ich noch nicht gesehen. :mrgreen: :zwinker:

EDIT:
Ergänzung:
Delphi-Quellcode:
function getLengthInMS; string;
Var
  Error : Integer:
  Data : string;

begin
    Error := mciSendString('set movie time format ms', 0, 0, 0)
    Error := mciSendString('status movie length', Data, 128, 0)
    Result := Data;
end;
Error gibt den wert 0 zurück wenn alles in ordnung.

Geschrieben nicht getestet!

gruss

Sunlight7 17. Feb 2007 18:57

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Bei AVIs gilt 1 GB Beschränkung :zwinker:
Und wer sagt, das sich die Nutzer nur Musikvideos ansehen? :stupid:
Ich habe Filme, die über 1 GB sind :mrgreen:

Zitat:

Zitat von EWeiss
Geschrieben nicht getestet!

Stimmt, da seh ich beim hinschauen 3 Fehler :wink:
Der Typ Data muß PChar oder ein Array sein.
Rückgabewert wird nicht überprüft.
Semikolon vergessen :mrgreen:

"Movie" ist der Aliasname :wink:

EWeiss 17. Feb 2007 19:29

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Zitat:

Zitat von Sunlight7
Bei AVIs gilt 1 GB Beschränkung :zwinker:
Und wer sagt, das sich die Nutzer nur Musikvideos ansehen? :stupid:
Ich habe Filme, die über 1 GB sind :mrgreen:

Zitat:

Zitat von EWeiss
Geschrieben nicht getestet!

Stimmt, da seh ich beim hinschauen 3 Fehler :wink:
Der Typ Data muß PChar oder ein Array sein.
Rückgabewert wird nicht überprüft.
Semikolon vergessen :mrgreen:

"Movie" ist der Aliasname :wink:

HEheheehehee erwischt..
translated from Vb ;) muss noch was lernen.! :wall:

gruss

Nils_13 18. Feb 2007 10:29

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Und wie wendet man die Prozedur korrekt an ? Ich habe eine normalerweise funktionierende Überprüfung eingebaut, ob es eine Audio oder Videodatei ist und ab diesem Zeitpunkt knallt es bei Application.Run. Der Debugger ist duch alles durch und beim Run bleibt der Debugger in einer Schleife hängen. Deshalb weiß ich nicht ansatzweise, wo der Fehler liegt.

Nachtrag:
Ich weiß jetzt wo der Fehler liegt:
Delphi-Quellcode:
Result := Data;
Was tun ?

Der Fehler tritt übrigens beim Anwendungsstart auf, wenn die zuletzt in der Playlist gewesenen Lieder ausgelesen werden (aus Playlist). Ich habe mit Absicht nur Videos in der Playlist stehen, welche zu Anfang geladen wird.

EWeiss 18. Feb 2007 14:12

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Schick mir dein Teil nochmal das Sample ..
Baue dir dann Heute .. Morgen eine funktionierende Abfrage ein, wenn ich das kann ;)

gruss

Sunlight7 18. Feb 2007 20:23

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Abend!

Du solltest Dateinamen in das 8+3 Format wandeln :wink: , da sonst MCI bei zu langen Dateinamen crasht. :stupid:
Hier ein Auszug von meiner Komponente, welche MCI nutzt.

Delphi-Quellcode:
...

   CloseMedia;

   FIDString:='SMC'+IntToStr(Random(16777216));
   If UpperCase(ExtractFileExt(FileName))='.CDA' then
      goto OpenTrack;


OpenFile:
   // Nur im 8+3 Dateiformat öffnen, Dateienamen mit mehr als 64 Zeichen lassen MCI crashen!
   i:=mciSendString(PChar('open "'+SExtractShortFileName(FFileName)+'" alias '+FIDString), nil, 0, TSMCForm(SMCForm).Handle);
   If i<>0 then begin
      ShowErrorMessage(i);
      SetLastError(i);
      Exit;
   end;
   mciSendString(PChar('status "'+FIDString+'" length '), PC, 255, 0);
   FFrames:=StrToIntDef(PC, 0);
   mciSendString(PChar('status "'+FIDString+'" nominal frame rate'), PC, 255, 0);
   FFrameRate:=StrToIntDef(PC, 0) / 1000;
   Goto Resume;

   mciSendString(PChar('capability "'+FIDString+'" has video'), PC, 255, 0);
   FIsVideoDevice:=(PC='true');
   mciSendString(PChar('capability "'+FIDString+'" has audio'), PC, 255, 0);
   FIsAudioDevice:=(PC='true');

   // Test ob Audio im geladenen Media ist, falls dies ein Video ist
   // Achtung: Muß vor SetAudio sein !
   If FIsVideoDevice then begin
      mciSendString(PChar('status "'+FIDString+'" audio'), PC, 255, 0);
      FIsAudioDevice:=(PC='on');
   end;

   FFileName:=FileName;
   SavedMode:=smcNotReady;

   SendString('set', 'time format ms');
   If Assigned(FOnGetDisplayHandle) then FOnGetDisplayHandle(Self, FDisplayHandle);
   SetDisplayHandle(FDisplayHandle);

   // Video Größe
   If FIsVideoDevice then begin
      mciSendString(PChar('where "'+FIDString+'" source '), PC, 255, 0);
      s:=Copy(PC, 5, 255);
      If s<>'' then begin
         For i:=1 to System.Length(s) do
            If s[i]=' ' then begin
               FVideoWidth:=StrToIntDef(Copy(s, 1, i-1), 0);
               FVideoHeight:=StrToIntDef(Copy(s, i+1, System.Length(s)-i), 0);
               Break;
            end;
      end;
      FDisplayRect:=Rect(0, 0, FVideoWidth, FVideoHeight);
   end;
   FDisplayWidth:=FVideoWidth;
   FDisplayHeight:=FVideoHeight;
   // Umgehen eines MCI Bug's bei .MP3 und .WMA
   If FIsVideoDevice then
      if (FVideoWidth<4) or (FVideoHeight<4) then FIsVideoDevice:=False;

   If Assigned(FOnSetDisplayRect) then try
      FOnSetDisplayRect(Self);
   except
   end;

   If FIsVideoDevice then SetDisplaySize(FDisplayRect, FStretchToWindow);
   If not FAutoPlay then UpdateDisplay;

   If not FPlayAudio then DisableAudio;
   If not FPlayVideo then DisableVideo;

   mciSendString(PChar('status "'+FIDString+'" length '), PC, 255, 0);
   FLength:=StrToIntDef(PC, 0);
   mciSendString(PChar('set "'+FIDString+'" seek exactly on'), PC, 255, TSMCForm(SMCForm).Handle);

   If FSpeed<>1000 then SetSpeed(FSpeed);

DoPlay:
   If FAutoPlay then Play;
...
Grüßle!

Nils_13 19. Feb 2007 08:47

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Kannst du mir auch noch sagen, was ich davon überhaupt in mein Testprogramm einbauen kann ? Da sind so viele Zeilen, mit denen ich überhaupt nichts anfangen kann, drinnen (so ist das nunmal bei Codeausschnitten).

Lasse2002 19. Feb 2007 10:34

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Hat es schon mal jemand mit IMediaDet probiert? Dieses Interface ist dafür gedacht, die Länge und evtl. noch ein paar weitere Infos von einer Mediadatei herauszubekommen.

Delphi-Quellcode:
function GetMediaLength(const AFileName: WideString): Double;
var
  MediaDet: IMediaDet;
  hr: HResult;
begin
  hr := CoCreateInstance(CLSID_MediaDet, nil, CLSCTX_INPROC_SERVER,
    IID_IMediaDet, MediaDet);
  if Succeeded(hr) then
  begin
    MediaDet.put_Filename(AFilename);
    MediaDet.get_StreamLength(Result);
  end
  else
    Result := -1;

  MediaDet := nil;
end;
Aufrufen mit:
Delphi-Quellcode:
I := GetMediaLength('E:\demo.avi');
ShowMessage('Länge: ' + FloatToStr(i) + ' Sekunden');

Nils_13 19. Feb 2007 12:50

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Und was braucht und woher bekommt man die dazugehörigen Sachen ? Ich hoffe, dass man MediaDet nicht mitschicken muss.

xaromz 19. Feb 2007 13:29

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Hallo,

das IMediaDet-Interface ist wohl ein Teil von DirectShow. Du benötigst also nur die Header, welche ja beim DSPack dabei sind.

Gruß
xaromz

Nils_13 19. Feb 2007 14:04

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Ok, schön. Aber irgendwie gibt es immer Probleme:
Delphi-Quellcode:
var i : Double;
begin
  i := GetMediaLength('E:\asd.avi');
  ShowMessage('Länge: ' + FloatToStr(i) + ' Sekunden');
Dann soll das natürlich noch verwandelt werden. Dies soll mit folgender Prozedur geschehen, aber wie ?
Delphi-Quellcode:
function TfrmMain.DurationMinSec(Sekunden : Integer) : String;
var Hour, Min, Sec : Integer;
begin
  Hour     := Sekunden div 1440;
  dec(Sekunden, Hour*1440);
  Min      := Sekunden div 60;
  Sec      := Sekunden - Min * 60;
  if Boolean(Hour) then
    Result := Format('%d:%.2d:%.2d', [Hour, Min, Sec])
  else
    Result := Format('%.2d:%.2d', [Min, Sec]);
end;
*** EDIT ***
Zwar nicht gerade elegant, aber es funktioniert:
Delphi-Quellcode:
procedure TfrmMain.b1Click(Sender: TObject);
var s : String;
    i : Integer;
    p : Integer;
begin
  s := FloatToStr(GetMediaLength('<<<Pfad+Dateiname>>>'));
  p := Pos(',', s);
  if not p <= -1 then
  begin
    s := Copy(s, 0, p-1);
    s := DurationMinSec(StrToInt(s));
  end;

  ShowMessage(s);
end;

function TfrmMain.DurationMinSec(Sekunden : Integer) : String;
var Hour, Min, Sec : Integer;
begin
  Hour     := Sekunden div 1440;
  dec(Sekunden, Hour*1440);
  Min      := Sekunden div 60;
  Sec      := Sekunden - Min * 60;
  if Boolean(Hour) then
    Result := Format('%d:%.2d:%.2d', [Hour, Min, Sec])
  else
    Result := Format('%.2d:%.2d', [Min, Sec]);
end;
Ich werde noch ein wenig rumtesten, aber bedanke mich hiermit schonmal bei allen Benutzern, welche in diesem Thread gepostet haben :) ! Es funktioniert endlich :party:

Lasse2002 19. Feb 2007 22:41

Re: DSPack : Länge von Lied vor Abspielen herausbekommen
 
Einfacher geht es so:
Delphi-Quellcode:
function TfrmMain.DurationMinSec(Sekunden : Integer) : String;
begin
  Result := TimeToStr(Sekunden / SecsPerDay);
end;
Man kann mit einer einfachen Divison durch SecsPerDay einen Wert von Sekunden in ein TDateTime umwandeln.

Oder wenn GetMediaLength gleich ein TDateTime zurückgeben soll:
Delphi-Quellcode:
function GetMediaLength(const AFileName: WideString): TDateTime;
var
  MediaDet: IMediaDet;
  hr: HResult;
  Tmp: Double;
begin
  hr := CoCreateInstance(CLSID_MediaDet, nil, CLSCTX_INPROC_SERVER,
    IID_IMediaDet, MediaDet);
  if Succeeded(hr) then
  begin
    MediaDet.put_Filename(AFilename);
    if Succeeded(MediaDet.get_StreamLength(Tmp)) then
      Tmp := Tmp / SecsPerDay
    else
      Tmp := 0;
  end
  else
    Tmp := 0;

  Result := Tmp;
  MediaDet := nil;
end;
Da -1 von TimeToStr in 1 Sekunde umgewandelt wird, ist es besser im Fehlerfall 0 zurückzugeben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:03 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz