IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

[D7] Durée d'une vidéo au format MP4


Sujet :

Delphi

  1. #21
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 844
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 844
    Points : 11 274
    Points
    11 274
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Au coup d’œil, une question me vient : les record tiennent-ils compte dans tous les cas (exe 32/64 bits, D7/Delphi actuel) de l'alignement sur 8 octets dont il me semble me souvenir des spécifications ?
    Delphi 5 Pro - Delphi 10.4 Rio Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  2. #22
    Membre confirmé Avatar de Galet
    Homme Profil pro
    Consultant/Programmeur Robotique industrielle
    Inscrit en
    Mars 2010
    Messages
    323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant/Programmeur Robotique industrielle

    Informations forums :
    Inscription : Mars 2010
    Messages : 323
    Points : 483
    Points
    483
    Par défaut
    Citation Envoyé par Charly910 Voir le message
    ... fasse 10 fois mieux !
    Le temps de chargement de bArray représente 90% du temps total, en limitant la taille de chargement à 1ko, avec le même code, le temps est divisé par 10 .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      if Taille>1023 then Taille:=1023;
    C'est sans doute moins bien que Cirec et Paul, mais le gain est instantané.
    Belle journée,
    Windows 10 / Delphi Tokyo
    "Les choses ne changent pas. Change ta façon de les voir, cela suffit" Lao Tseu

  3. #23
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    ah tu as été plus rapide que moi
    j'aimerai bien mais je doute sérieusement, je dirai que tu t'y es pris après moi
    pare contre dans les fichiers que j'ai utilisé pour les testes certain on l'info en début de fichier et d'autre à la fin ...
    et sur un fichier de 2Go avec l'info en fin ça ne risque pas de prendre du temps ?
    d'où mon changement de tactique avec un buffer + gros et une recherche en début et si pas trouvé en fin de fichier.
    ce qui a rendu de code quasi instantané.

    Citation Envoyé par tourlourou Voir le message
    Bonjour,
    Au coup d’œil, une question me vient : les record tiennent-ils compte dans tous les cas (exe 32/64 bits, D7/Delphi actuel) de l'alignement sur 8 octets dont il me semble me souvenir des spécifications ?
    Ben si je dis pas de bêtises par défaut delphi aligne les records en {$Align8}
    Citation Envoyé par Aide Delphi
    Défaut {$A8}
    {$ALIGN 8}
    En mode {$A8} ou {$A+}, les champs des types enregistrement déclarés sans le modificateur packed et les champs des structures classe sont alignés sur les frontières des quadruples mots.
    pour le mode 32Bits il n'y a pas de soucis ça fonctionne
    n'ayant pas de fichier avec des données en 64Bits j'ai pas testé.
    Ceci dit pour respecter le nombre d'octets à lire j'ajouterai certainement le packed
    Bien que ce soit en contradiction avec l'alignement sur 8 octets.

    Je suis un peu perdu là !
    peut être que Paul pourrait nous éclairer

    Cordialement,
    @+

  4. #24
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 339
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 339
    Points : 3 107
    Points
    3 107
    Par défaut
    Bonjour Cirec

    merci pour ta solution

    j'ai testé, mais StrMoov n'était pas déclaré j'ai déclaré : StrMoov : AnsiString;

    GetMP4Duration me renvoie systématiquement -1 ?

    A+
    Charly

  5. #25
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par Charly910 Voir le message
    Bonjour Cirec

    merci pour ta solution

    j'ai testé, mais StrMoov n'était pas déclaré j'ai déclaré : StrMoov : AnsiString;

    GetMP4Duration me renvoie systématiquement -1 ?

    A+
    Charly
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const
      StrMoov: AnsiString = #$6D#$6F#$6F#$76#0#0#0#$6C#$6D#$76#$68#$64;
    je vais corriger l'autre poste

    Cordialement,
    @+

  6. #26
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 339
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 339
    Points : 3 107
    Points
    3 107
    Par défaut
    Bonjour Paul,

    Merci, mais j'ai un problème avec ton code en D7 :

    J'ai remplacé Exit(False ) par Result := False ; Exit ;

    par contre avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          S.Seek(H.Size - SizeOf(H), TSeekOrigin.soCurrent); // sauter la section
    :

    j'ai une erreur : Type Object ou Class requis ?

    A+
    Charly

  7. #27
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 339
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 339
    Points : 3 107
    Points
    3 107
    Par défaut
    @Cirec : merci ça fonctionne très bien et c'est très rapide

    @Galet : oui on peut limiter à 1ko, mais dans certains MP4, la balise mvhd est presque en fin de fichier

    A+
    Charly

  8. #28
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par Charly910 Voir le message
    Bonjour Paul,

    Merci, mais j'ai un problème avec ton code en D7 :

    J'ai remplacé Exit(False ) par Result := False ; Exit ;

    par contre avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          S.Seek(H.Size - SizeOf(H), TSeekOrigin.soCurrent); // sauter la section
    :

    j'ai une erreur : Type Object ou Class requis ?

    A+
    Charly

    S.Seek(H.Size - SizeOf(H), soCurrent);

    je suppose, c'est juste pour avancer dans le Stream de "H.Size - SizeOf(H)"
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #29
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    S.Seek(H.Size - SizeOf(H), soCurrent);

    je suppose, c'est juste pour avancer dans le Stream de "H.Size - SizeOf(H)"
    en D7 c'est encore soFromCurrent
    Citation Envoyé par Classes.pas
    { TStream seek origins }

    soFromBeginning = 0;
    soFromCurrent = 1;
    soFromEnd = 2;
    Cordialement,
    @+

  10. #30
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    @PaulToth

    ton code fonctionne bien quand l'info est en début de fichier
    mais déclenche une Erreur de lecture du flux quand elle se trouve vers la fin.

    dans la boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        repeat
          H.Size := LSwap(H.Size); 
          S.Seek(H.Size - SizeOf(H), soFromCurrent); // sauter la section
          S.ReadBuffer(H, SizeOf(H)); // lire la suivante
        until H.Tag = 'moov'; // jusqu'au "moov"
    comme les Chunk ne se suivent pas obligatoirement
    du coup au bout de 3 répétitions H.Size contient une valeur totalement farfelue !!!

    Cordialement,

    @+

  11. #31
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par Cirec Voir le message
    @PaulToth

    ton code fonctionne bien quand l'info est en début de fichier
    mais déclenche une Erreur de lecture du flux quand elle se trouve vers la fin.

    dans la boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        repeat
          H.Size := LSwap(H.Size); 
          S.Seek(H.Size - SizeOf(H), soFromCurrent); // sauter la section
          S.ReadBuffer(H, SizeOf(H)); // lire la suivante
        until H.Tag = 'moov'; // jusqu'au "moov"
    comme les Chunk ne se suivent pas obligatoirement
    du coup au bout de 3 répétitions H.Size contient une valeur totalement farfelue !!!

    Cordialement,

    @+
    je n'ai testé qu'avec un seul et unique MP4

    mais normalement, le MP4 contient des blocks TMP4Chunk, qui peuvent eux même contenir des TMP4Chunk

    donc je lis le premier qui doit être un 'ftyp', et je le saute (on avance de H.Size - SizeOf(H))
    quand je trouve un "moov", je lis à l'intérieur jusqu'à ce que je trouve un "mvhd"

    ah mais peut-être que ton MP4 contient plusieurs "moov" sans "mvhd" avant celui qui n'en contienne un

    du coup il faut dans la boucle tenir compte de la taille du "moov" pour sortir de la boucle si on arrive au bout

    quelque chose comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    function GetMP4Duration(const AFileName: string; var Duration: Int64): Boolean;
    type
      TMP4Chunk = packed record
        Size: Cardinal;
        Tag : array[0..3] of AnsiChar;
      end;
      TMP4Mvhd = packed record
        Ver: Byte;
        Flags: array[0..2] of Byte;
        case Boolean of
          True: (
            Creation1, Modified1: UInt64;
            Timescale1: Cardinal;
            Duration1: UInt64;
          );
          False: (
            Creation2, Modified2: Cardinal;
            Timescale2: Cardinal;
            Duration2: Cardinal;
          );
        end;
    var
      S: TFileStream;
      H: TMP4Chunk;
      M: TMP4Mvhd;
      L: Cardinal;
    begin
      Result := False;
      S := TfileStream.Create(AFileName, fmOpenRead or fmShareDenyNone);
      try
        S.ReadBuffer(H, SizeOf(H)); // lecture d'un entête MP4
        if H.Tag <> 'ftyp' then // vérification du type
          Exit(False);
        repeat // on peut avoir à lire +sieurs "moov"
          while H.Tag <> 'moov' do
          begin
            H.Size := LSwap(H.Size);
            S.Seek(H.Size - SizeOf(H), TSeekOrigin.soCurrent); // sauter la section
            S.ReadBuffer(H, SizeOf(H)); // lire la suivante
          end;
          L := LSwap(H.Size) - SizeOf(H);
          S.ReadBuffer(H, SizeOf(H)); // lire dans "moov"
          while (L > 0) and (H.Tag <> 'mvhd') do // jusque "mvhd"
          begin
            H.Size := LSwap(H.Size);
            Dec(L, H.Size);
            S.Seek(H.Size - SizeOf(H), TSeekOrigin.soCurrent);
            S.ReadBuffer(H, SizeOf(H));
          end;
        until H.Tag = 'mvhd';
        S.ReadBuffer(M, SizeOf(M)); // lire son contenu
        if M.Ver = 1 then // en fonction de la version
        begin
          M.Duration2 := LLSwap(M.Duration2); // non testé !
          M.Timescale1 := LSwap(M.Timescale1);
          Duration := M.Duration1 div M.Timescale1;
        end else begin
          M.Duration2 := LSwap(M.Duration2);
          M.Timescale2 := LSwap(M.Timescale2);
          Duration := M.Duration2 div M.Timescale2; // calculé la durée en secondes
        end;
        Result := True;
      finally
        S.Free;
      end;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  12. #32
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    re,

    j'ai compris d'où venait le souci ...
    c'est pas ton code directement mais en codant une ligne différemment tout fonctionne !!!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
          //S.Seek(H.Size - SizeOf(H), soFromCurrent); // sauter la section
          S.Position := S.Position + (H.Size - SizeOf(H));
    bizarrement avec Seek ça ne fonctionne pas correctement en D7
    en pas à pas peu importe la valeur de H.Size - SizeOf(H)
    il conservait sa valeur
    et après 3 ou 4 passe seek fonctionne à nouveau mais la position est déjà erronée.

    j'avais aussi un problème avec Seek dans mon code et je suis aussi passé pas Position !

    étrange quand même.

    Cordialement,
    @+

  13. #33
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 429
    Points : 24 794
    Points
    24 794
    Par défaut
    Version D7 du code de Paul Toth, il fonctionne pour 117 MP4 lus sur 118 trouvé, une Erreur de lecture, je ne teste pas sur la machine qui compile donc code de débogage bien vilain
    Si je retrouve ce que j'avais fait pour des fichiers H264 à l'époque ou je gérais des DVR Dahua.


    Sans la sortie sur "Next H not moov aborted" il y a aurait une erreur
    En soFromCurrent : "Read Next H not moov - EReadError "Stream read error" - 2010960942 -> 2010960942 / 1220300993"
    En soCurrent : "Read Next H not moov - EReadError "Stream read error" - 4295850655 -> 4295850655 / 1220300993"

    Peut-être ajouter une gestion de fin de fichier prématurée ou se protéger de valeurs incohérentes dans le fichier lui-même

    soFromCurrent et soCurrent existet en D7, cela différencie la version 32 et 64 Bits
    C'est pour cela que dans un cas, cela qu'en soFromCurrent gérant des Integer, cela donne un nombre en 2... et en soCurrent, cela prend en 4...
    Tout ça parce que le Seek tente un déplacement négatif donc en arrière qui part totalement en vrille !


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    unit MP4HeaderReader_MainForm;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        Edit1: TEdit;
        Button2: TButton;
        Edit2: TEdit;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Déclarations privées }
        procedure ScanMP4(const ADirectory: TFileName);
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
     
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ScanMP4(Edit1.Text);
     
     
     
    end;
     
     
    function GetMP4Duration(const AFileName: string; var Duration: Int64): Boolean;
     
      function LSwap(C: Cardinal): Cardinal;
      begin
        Result := Swap(C) shl 16 + Swap(C shr 16);
      end;
     
      function LLSwap(L: UInt64): UInt64;
      begin
        Result := LSwap(L) shl 32 + LSwap(L shr 32);
      end;
     
    type
      TMP4Chunk = packed record
        Size: Cardinal;
        Tag : array[0..3] of AnsiChar;
      end;
      TMP4Mvhd = packed record
        Ver: Byte;
        Flags: array[0..2] of Byte;
        case Boolean of
          True: (
            Creation1, Modified1: UInt64;
            Timescale1: Cardinal;
            Duration1: UInt64;
          );
          False: (
            Creation2, Modified2: Cardinal;
            Timescale2: Cardinal;
            Duration2: Cardinal;
          );
        end;
     
      procedure _ReadBuffer(AStream: TFileStream; var ABuffer; ASize: Int64; const AHint: string);
      var
        P: Int64;
      begin
        P := AStream.Position;
        try
          AStream.ReadBuffer(ABuffer, ASize);
        except
          on E: Exception do
            raise ExceptClass(E.classType).CreateFmt('Read %s - %s "%s" - %d -> %d / %d', [AHint, E.ClassName, E.Message, P, AStream.Position, AStream.Size]);
        end;
      end;
    var
      S: TFileStream;
      H: TMP4Chunk;
      M: TMP4Mvhd;
      L: Cardinal;
    begin
     
      Result := False;
      S := TfileStream.Create(AFileName, fmOpenRead or fmShareDenyNone);
      try
        _ReadBuffer(S, H, SizeOf(H), 'First H'); // lecture d'un entête MP4
        if H.Tag <> 'ftyp' then // vérification du type
          Exit;
     
        repeat // on peut avoir à lire +sieurs "moov"
          while H.Tag <> 'moov' do
          begin
            H.Size := LSwap(H.Size);
            if H.Size < SizeOf(H) then
              raise Exception.Create('Next H not moov aborted');
            S.Seek(H.Size - SizeOf(H), soCurrent); // sauter la section
            _ReadBuffer(S, H, SizeOf(H), 'Next H not moov'); // lire la suivante
          end;
          L := LSwap(H.Size) - SizeOf(H);
          _ReadBuffer(S, H, SizeOf(H), 'Current H moov'); // lire dans "moov"
          while (L > 0) and (H.Tag <> 'mvhd') do // jusque "mvhd"
          begin
            H.Size := LSwap(H.Size);
            if H.Size < SizeOf(H) then
              raise Exception.Create('Next H not mvhd aborted');
            Dec(L, H.Size);
            S.Seek(H.Size - SizeOf(H), soCurrent);
            _ReadBuffer(S, H, SizeOf(H), 'Next H not mvhd');
          end;
        until H.Tag = 'mvhd';
        _ReadBuffer(S, M, SizeOf(M), 'Current M mvhd'); // lire son contenu
        if M.Ver = 1 then // en fonction de la version
        begin
          M.Duration2 := LLSwap(M.Duration2); // non testé !
          M.Timescale1 := LSwap(M.Timescale1);
          Duration := M.Duration1 div M.Timescale1;
        end else begin
          M.Duration2 := LSwap(M.Duration2);
          M.Timescale2 := LSwap(M.Timescale2);
          Duration := M.Duration2 div M.Timescale2; // calculé la durée en secondes
        end;
        Result := True;
      finally
        S.Free;
      end;
    end;
     
    procedure TForm1.ScanMP4(const ADirectory: TFileName);
    var
      Dir: TFileName;
      Path, Filter, FileName: string;
      sr: TSearchRec;
      Duration: Int64;
    const
      faNormal      = $00000080;
    begin
      Path := IncludeTrailingPathDelimiter(ADirectory);
      Filter := Path + '*.mp4';
     
      // Les Fichiers !
      if FindFirst(Filter, faNormal, sr) = 0 then
      begin
        try
          repeat
            FileName := Path + sr.Name;
            try
              if GetMP4Duration(FileName, Duration) then
                Memo1.Lines.Add(FileName + ' : ' + IntToStr(Duration))
              else
                Memo1.Lines.Add(FileName + ' : Error')
            except
              on E: Exception do
                Memo1.Lines.Add(FileName +  ' : ' + E.Message);
            end;
          until FindNext(sr) <> 0;
        finally
          FindClose(sr);
        end;
      end;
     
      // Les Dossiers !
      Filter := Path + '*';
      if FindFirst(Filter, faDirectory, sr) = 0 then
      begin
        try
          repeat
            if ((sr.Attr and faDirectory) = faDirectory) and (sr.Name <> '.') and (sr.Name <> '..') then
            begin
              Dir := Path + sr.Name;
              ScanMP4(Dir);
            end;
     
          until FindNext(sr) <> 0;
        finally
          FindClose(sr);
        end;
      end;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    var
      Duration: Int64;
    begin
      if GetMP4Duration(Edit2.Text, Duration) then
        Memo1.Lines.Add(Edit2.Text + ' : ' + IntToStr(Duration))
      else
        Memo1.Lines.Add(Edit2.Text + ' : Error');
    end;
     
    end.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  14. #34
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    pour le debugage sur le poste client je ne serais trop te recommander madExcept, cet outils m'a sauvé la mise plus d'une fois

    tu peux même faire en sorte qu'il t'envoie l'erreur par mail (ce que je fais), le client n'y voit que du feu, mais à la maj suivante, l'erreur à disparu
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  15. #35
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 339
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 339
    Points : 3 107
    Points
    3 107
    Par défaut
    Bonsoir,

    pour ma part, les 2 codes me donnent satisfaction, celui de Paul Toth et celui de Cirec.

    J'ai fait des tests approximatifs qui montrent qu'ils sont quasiment aussi rapide l'un que l'autre.

    je n'ai pas eu de problème avec le code de Paul, sauf quand le fichier MP4 faisait 0 k !

    Merci donc

    A+
    Charly

  16. #36
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 420
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 420
    Points : 1 325
    Points
    1 325
    Par défaut
    Bonjour à toutes et à tous,

    Chapeau bas à Cirec et à Paul THOT.

    Pour répondre à Charly910 j'avais testé une version sans fichier .bat qui utilise le lecteur sans le faire lire et qui donne aussi l'indication pour les mp4, mp3:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    procedure TForm1.OuvrirClick(Sender: TObject);
    var
     
      FileName, res : string;
     
      h, min, sec : string[3];
    begin
     
    op1.CleanupInstance;
    chappli := ExtractFilePath(Application.ExeName);
     
    ForceCurrentDirectory := True;
     
    SetCurrentDir (chappli); 
     
    op1.Filter := 'Fichiers Musical (*.mp4;*.mp3;*.wma)|*.mp4;*.mp3;*.wma|Fichiers Mp4 (*.mp4)|*.mp4|Fichiers Mp3 (*.mp3)|*.mp3|Fichiers Wma (*.wma)|*.wma' ;
     
    if op1.Execute then
        begin
     
     Mp1.FileName := op1.filename;
     Mp1.Open;
     
        h := inttostr(mp1.Length div 3600000 );//initialisation des heures
     
        min := inttostr(mp1.Length div 60000);//initialisation des minutes
     
        sec := inttostr(mp1.Length div 1000 - 60*strtoint(min));//initialisation des secondes
     
     
        if strtoint(h) <10 then
            h := '0'+h;
        if strtoint(min)<10 then
            min := '0'+min;
        if strtoint(sec)<10 then
           sec := '0'+sec;
     
        Edit1.text := h+':'+min+':'+sec;
      end;
     
    end;
    Rien à voir avec les solutions proposées qui fonctionnent sur D6 et Win10 64 bits.

    Cordialement,

    cincap

  17. #37
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 339
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 339
    Points : 3 107
    Points
    3 107
    Par défaut
    Bonjour,

    le problème est largement résolu avec des solutions très rapides.

    Test avec un panel de 690 videos :

    - environ 200 ms pour Cirec
    - environ 150 ms pour Paul Toth et ShaiLeTroll

    Je n'ai pas pu tester la solution de Cincap car j'ai un problème à l'ouverture du TMediaPlayer

    En tout cas merci à Tous les 4

    A+
    Charly

  18. #38
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 420
    Détails du profil
    Informations personnelles :
    Âge : 71
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 420
    Points : 1 325
    Points
    1 325
    Par défaut
    @ Charly910, avec Win10 et certains pc dès fois il existe des bugs.

    Par contre la version avec le fichier .bat que tu as testée permet de donner la durée pour les fichiers .mp4, .mp3, .wma et .wav.

    Il suffirait à un expert de le convertir en Delphi puisque j'utilise "CreateOleObject('Shell.Application');".


    Si il le faut je communique le .bat pour ne pas polluer le site.

    @+,

    cincap

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Convertir une vidéo (au format MOV) au format AVI
    Par Mariion dans le forum Vidéo
    Réponses: 2
    Dernier message: 14/11/2010, 20h09
  2. une vidéo sous format .DAT
    Par Msysteme dans le forum Vidéo
    Réponses: 1
    Dernier message: 26/09/2010, 03h32
  3. Comment obtenir la durée d'une vidéo?
    Par bakabdel dans le forum ASP.NET
    Réponses: 0
    Dernier message: 13/04/2009, 14h39
  4. [Video] ouvrir une vidéo au format 3gp
    Par optitou dans le forum Vidéo
    Réponses: 5
    Dernier message: 26/03/2007, 10h56
  5. [TMediaPlayer] connaître la durée d'une vidéo
    Par jcs2 dans le forum Delphi
    Réponses: 5
    Dernier message: 29/08/2006, 20h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo