Media Player Control erhält nicht die Spieldauer des .mp3 Files

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    Media Player Control erhält nicht die Spieldauer des .mp3 Files

    Hi,

    ich habe mir einen kleinen "Media Player" gebaut. Den benötige ich, um von CDs Sprachen zu lernen - da muss ich häufig anhalten, um ein paar Sekunden zurück oder nach vorn zu springen. Wie das Ding aussieht seht ihr im Anhang.

    Es wird die Startposition (die kann man einstellen), die aktuelle Position und die Gesamtdauer angezeigt. Dazwischen liegt eine Track Bar.

    Das klappt auch prima für die meisten CDs.

    Jetzt habe ich aber eine CD, bei der etwas schief geht ! Die Start Routine erhält als Gesamtdauer der .mp3 Datei 0 Sekunden, obwohl sie tatsächlich rund 4 Minuten lang ist ! Das Feld

    AxWindowsMediaPlayer1.currentMedia.duration)

    enthält 0 und nicht 240 wie es richtig wäre !

    Das ist sehr blöde, denn die Gesamtdauer benötige ich zum Einstellen der Track Bar und später auch zum "Springen" ...

    Hat jemand eine Idee, warum das bei dieser einen CD nicht funktioniert ... und wie ich das beheben oder notfalls umgehen kann ?

    Viele Grüße
    Peter
    Bilder
    • s 2019-08-20 09-58-357.jpg

      17,24 kB, 829×210, 76 mal angesehen
    • s 2019-08-20 09-55-011.jpg

      43,98 kB, 1.058×321, 74 mal angesehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()

    Das Problem hatte ich neulich auch. Ich hab gesehen, dass erst das Lied kurz gestartet und gestoppt werden musste, bevor die Länge im Player erfasst wurde. Dafür hab ich das hier verwendet:

    VB.NET-Quellcode

    1. Private Async Sub LoadMediaFile(FilePath As String)
    2. WMP.URL = FilePath '*
    3. WMP.Settings.Mute = True '*
    4. WMP.Ctlcontrols.Play() '*
    5. Await Threading.Tasks.Task.Delay(1000) '*
    6. TBarSongTime.Maximum = CInt(10 * WMP.CurrentMedia.Duration) + 1
    7. TBarSongTime.Visible = True
    8. WMP.Settings.Mute = False '*
    9. WMP.Ctlcontrols.Stop() '*
    10. End Sub

    * relevanter Code
    Vielleicht geht es besser, aber ich hab mir noch nicht die Zeit dafür genommen, etwas besseres zu suchen. Denn die Sekunde nach dem Laden der Datei gönn ich dem Programm.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Danke, das klingt ja sehr vielversprechend.

    Leider scheint das bei mir nicht zu funktionieren ... :(

    Auch wenn ich 10 Sekunden warte, bleibt es immer noch bei 0 Sekunden Gesamtdauer ....

    Mache ich irgendetwas falsch ?

    LG
    Peter
    Bilder
    • s 2019-08-20 10-40-106.jpg

      39,45 kB, 1.021×367, 74 mal angesehen
    Es ist interessant. Ich bin über hier und hier zurück ins vbp-Forum zu diesem Thread gekommen. Daraus entstand dann zum Längenauslesen:

    VB.NET-Quellcode

    1. <Runtime.InteropServices.DllImport("winmm.dll", EntryPoint:="mciSendStringA")> Private Shared Function MciSendString(Command As String, ReturnString As Text.StringBuilder, ReturnLength As Integer, Callback As IntPtr) As Integer : End Function
    2. Private Function GetMP3LengthInMilliseconds(FilePath As String) As Integer
    3. MciSendString($"open {FilePath} type MPEGVideo alias mp3audio", Nothing, 0, IntPtr.Zero)
    4. Dim DurationString As New Text.StringBuilder
    5. MciSendString("status mp3audio length", DurationString, 255, IntPtr.Zero)
    6. MciSendString("close mp3audio", Nothing, 0, IntPtr.Zero)
    7. Return Integer.Parse(DurationString.ToString)
    8. End Function

    Das Problem: Mit meiner Testdatei der Länge 01:17 (mm:ss) komme ich mit der Funktion auf ca. 97000 Millisekunden. Das sind aber über anderthalb Minuten. Vielleicht läuft die Funktion bei Dir. Aber ich find den Fehler noch nicht bei mir. :(
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Irgendwie ist das nicht mein Tag.

    Bei mir liefert der Funktionsaufruf nichts zurück !

    Ehe ich mich jetzt daran mache, die von dir genannten Links durchzuarbeiten, würde ich gern erst mal fragen, ob ich vielleicht irgend einen simplen Fehler gemacht habe ....

    LG
    Peter
    Bilder
    • s 2019-08-20 14-28-467.jpg

      37,17 kB, 1.026×240, 77 mal angesehen
    Das passiert bei mir, wenn der Dateipfad nicht stimmt. Bitte das erstmal ggf. vorher mit dem hier testen:

    VB.NET-Quellcode

    1. If Not IO.File.Exists(FilePath) Then MessageBox.Show("Der Dateipfad ist falsch, die angegebene Datei existiert nicht.")
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @Peter329 Kannst Du mal das Projekt posten, da lässt es sich besser Fehlerfinden. ;)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hier ist eine Routine zum Testen:

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. AxWindowsMediaPlayer1.Ctlcontrols.pause()
    5. TextBox1.BackColor = SystemColors.Window
    6. If OpenFileDialog1.ShowDialog() = DialogResult.Cancel Then Exit Sub
    7. TextBox1.Text = OpenFileDialog1.FileName
    8. TextBox2.Text = ""
    9. Dim myObject As String = TextBox1.Text.Trim
    10. If Not File.Exists(myObject) Then
    11. MessageBox.Show(myObject & " does not exist")
    12. Exit Sub
    13. End If
    14. TextBox1.BackColor = Color.LightGreen
    15. 'Get duration ---------------------------------------------------------------------
    16. AxWindowsMediaPlayer1.URL = myObject
    17. Dim Duration As Double = AxWindowsMediaPlayer1.currentMedia.duration '<------------
    18. AxWindowsMediaPlayer1.Ctlcontrols.stop()
    19. TextBox2.Text = Duration.ToString
    20. If Duration = 0 Then MessageBox.Show("Duration cannot be extracted.",
    21. "Control Error",
    22. MessageBoxButtons.OK,
    23. MessageBoxIcon.Error)
    24. End Sub
    25. End Class


    Ohne jeden Schnickschnack ! :)

    Es geht nur darum die Gesamtspieldauer einer .mp3 Datei zu ermitteln.

    LG
    Peter

    P.S.: Wenn das Windows Media Player Control in der Toolbox nicht erscheint, dann kann man es wie folgt einbinden:

    Rechts-Click auf die Toolbox .... Elemente-Auswählen anklicken ... den Reiter COM-Komponenten auswählen - Häkchen vor "Media Player" setzen ....
    Bilder
    • s 2019-08-20 17-23-144.jpg

      33,35 kB, 1.020×367, 65 mal angesehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()

    Uh, tricky. Ich hab da noch was gefunden. Der Dateiname muss gekürzt werden. Das wurde in dem oben erwähnten vbp-Thread beschrieben (GetShortName), weil die mciSendString wohl nicht mit "langen" Dateinamen klarkommt.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ich habe jetzt deine Idee aufgegriffen und die Version mit den 8.3 Dateinamen nachvollzogen. Und siehe da, die Sache klappt ! :)

    Bei den Dateien, mit denen ich getestet habe, stimmt die angezeigte Dauer auf die Sekunde genau mit der tatsächlichen Spieldauer überein.

    Die Funktion könnte für andere interessant sein. Deshalb stelle ich das Coding hier noch einmal ein. Ich habe die "bösen" Funktionen ersetzt und auch Option "Strict On" verwendet. Jetzt sollte die Routine hoffentlich auch den Regeln der reinen Lehre entsprechen. :)

    Allerdings benötige ich noch vbNullChar und VaL() aus dem VisualBasic Namespace ... da bin ich nach wie vor unschlüssig wie ich das ohne Kopfstände in .NET realisieren soll ... na, vielleicht kann das ja jemand noch verraten ...


    Vielen Dank für deine Hilfe !

    LG
    Peter

    VB.NET-Quellcode

    1. Private Function GetMP3Length(ByVal strFileName As String) As Long
    2. Dim strBuffer As New String(" "c, 255)
    3. Dim lRet As Long
    4. Dim sReturn As New String(" "c, 255)
    5. ' Da die mciSendString Funktion mit langen Dateinamen
    6. ' nicht korrekt arbeitet, muss zuvor der kurze
    7. ' 8.3 Dateiname der MP3-Datei ermittelt werden.
    8. lRet = GetShortPathName(strFileName, strBuffer, strBuffer.Length)
    9. If lRet <> 0 Then _
    10. strFileName = strBuffer.Substring(0, strBuffer.IndexOf(vbNullChar))
    11. ' MP3-Datei öffnen
    12. mciSendString("open " & strFileName & " type MPEGVideo alias mp3audio", "0", 0, 0)
    13. ' Länge der Datei in Millisekunden auslesen
    14. lRet = mciSendString("status mp3audio length", sReturn, sReturn.Length, 0&)
    15. ' MP3-Datei schliessen
    16. mciSendString("close mp3audio", "0", 0, 0)
    17. GetMP3Length = CLng(Val(sReturn))
    18. End Function
    19. Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String,
    20. ByVal lpstrReturnString As String,
    21. ByVal uReturnLength As Integer,
    22. ByVal hwndCallback As Integer) As Integer
    23. Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String,
    24. ByVal lpszShortPath As String,
    25. ByVal cchBuffer As Integer) As Integer

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Peter329“ ()