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

Langage Java Discussion :

Sortie standard d'une commande FFmpeg et barre de progression


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Février 2011
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 21
    Par défaut Sortie standard d'une commande FFmpeg et barre de progression
    Bonjour!

    J'aimerais faire une barre de progression pour FFmpeg en Java


    FFmpeg c'est un logiciel libre dédiés au traitement de flux audio ou vidéo (enregistrement, lecture ou conversion d'un format à un autre).

    J’utilise ce programme pour detecter des pertes d'enregistrements..
    Pour cela j'utilise les lignes de commandes de FFmpeg avec Java (sous Eclipse).

    Exemple de ma ligne de commande:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ffmpeg -i fichierAanalyser.avi -vf blackdetect=d=0.1:pic_th=0.70:pix_th=0.00 -an -f null -
    Si vous voulez savoir plus sur les options de ffmpeg, ffmpeg

    En faisant plusieurs recherches sur le net et je suis tomber sur ce site. calcul etat d'avancement
    Sur ce site, bien que ce soit en php et qu'il faudrait adapter la solution en java (ou pas?) on peut voir comment récupérer de manière précise le pourcentage de conversion effectué.

    Mais le problème c'est que quand je lance la commande le programme en java récupère la sortie mais ne s'actualise qu'une fois l'execution de la commande terminée.

    En gros je veux utiliser le pourcentage calculé durant la conversion et l'utilisé pour faire une barre de progression.
    • Jusqu’à maintenant j'ai cherché du coté des thread mais j'avoue ne pas trop savoir comment aborder ce domaine la.
    • Sinon une autre solution pourrait être d’écrire dans un fichier texte au fur et à mesure la sortie de la commande pour faire une barre de progression qui se base sur ce fichier txt. Mais je ne vois pas comment écrire en continue sur un autre fichier:


    Voici une partie du code ou la récupération de la sortie de la commande à lieu :
    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
       public void getBlackInformation( String filename )
        {
        	String blackDetect = " -vf blackdetect=d=0.1:pic_th=0.70:pix_th=0.00 -an -f null -";
        	String cmd = "\"" + filename + "\"" + blackDetect ;
            Map<String,String> fieldMap = executeInquiry(cmd);
            if( fieldMap.containsKey( "black_start" ) )
            {
               fieldMap.get( "black_start" );
            }
        }
     
    protected String consumeStream( InputStream is )
        {
            StringBuilder sb = new StringBuilder();
            try
            {
                BufferedReader br = new BufferedReader( new InputStreamReader( is ) );
                String line = br.readLine();
                while( line != null )
                {
                    sb.append( line );
                    line = br.readLine();
                }
            }
            catch( Exception e )
            {
                e.printStackTrace();
            }
            return sb.toString();
        }
     
    protected Map<String,String> executeInquiry( String filename )
    {
        System.out.println( "Execute Inquiry for file: " + filename );
        Map<String,String> fieldMap = new HashMap<String,String>();
     
        try
        {
            // Build the command line
            StringBuilder sb = new StringBuilder();
            sb.append( "ffmpeg" );
            sb.append( " -i " );
            sb.append( filename );
     
            // Execute the command
            System.out.println( "Command line: " + sb );
            Process p = Runtime.getRuntime().exec( sb.toString() );
     
            // Read the response
            BufferedReader input = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
            BufferedReader error = new BufferedReader( new InputStreamReader( p.getErrorStream() ) );
     
            // Parse the input stream
            String line = input.readLine();
            System.out.println( "ffmpeg execution of: " + filename );
            while( line != null )
            {
                System.out.println( "\t***" + line );
                line = input.readLine();
            }
     
            // Parse the error stream
            line = error.readLine();
            System.out.println( "Error Stream: " + filename );
            int valtest = 0;
            while( line != null )
            {
                // Handle the line
                if( line.startsWith( "FFmpeg version" ) )
                {
                    // Handle the version line:
                    //    FFmpeg version 0.6.2-4:0.6.2-1ubuntu1, Copyright (c) 2000-2010 the Libav developers
                    String version = line.substring( 15, line.indexOf( ", Copyright", 16  ) );
                    fieldMap.put( "version", version );
                }
     
                else if( line.indexOf( "Duration:" ) != -1 )
                {
                    // Handle Duration line:
                    // Duration: 00:42:53.59, start: 0.000000, bitrate: 1136 kb/s
                    String duration = line.substring( line.indexOf( "Duration: " ) + 10, line.indexOf( ", start:" ) );
                    fieldMap.put( "duration", duration );
     
                    String bitrate = line.substring( line.indexOf( "bitrate: " ) + 9 );
                    fieldMap.put( "bitrate", bitrate );
                }
     
                else if( line.indexOf( "black_start:" ) != -1 )
                {
                	this.cpt ++;
                	String black_start = line.substring( line.indexOf( "black_start:" ) + 12, line.indexOf( " black_end:" ) );
                	fieldMap.put( "Perte n°"+cpt+" Début", black_start );
     
                	String black_end = line.substring( line.indexOf( "black_end:" ) + 10, line.indexOf( " black_duration:" ) );
                    fieldMap.put( "Perte n°"+cpt+" Fin", black_end );
     
                	String black_duration = line.substring( line.indexOf( "black_duration:" ) + 15);
                    fieldMap.put( "Perte n°"+cpt+" Durée", black_duration );
     
     
    				//label1[cpt].setText(" Debut : "+black_start+" Fin : "+black_end+" Durée : "+black_duration);
     
                    dlm.addElement("  Perte n°"+cpt+"   -   Debut : "+black_start+"     Durée : "+black_duration+"     Fin : "+black_end+     "  ");
                    //labelPertes.setVisible(true);
     
                    valtest = 1;
                }
     
                //Read the next line
                System.out.println( "\t***" + line );
                line = error.readLine();
            }
            if (valtest==0)
            {
            	Color gree = new Color(61, 200, 42);
            	labelPertes.setVisible(false);
            	labelIfBlack.setText("Pas de perte d'enregistrement");
            	labelIfBlack.setForeground(gree);
            }
            else
            {
            	labelIfBlack.setText("Pertes detectées");
            	labelIfBlack.setForeground(Color.red);
            }
     
     
        }
     
        catch( Exception e )
        {
            e.printStackTrace();
        }
     
        // Debug: dump fields:
        System.out.println( "Fields:" );
        for( String field : fieldMap.keySet() )
        {
            System.out.println( "\t" + field + " = " + fieldMap.get( field ) );
        }
     
        return fieldMap;
    }

    Merci d'avance pour votre aide


  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    En l'état c'est normal que ça fasse ça : tu lis d'abord la sortie standard, jusqu'à ce qu'elle soit finie. C'est-à-dire jusqu'à ce qu'on sache qu'elle soit finie, c'est-à-dire jusqu'à ce que l'OS ferme la sortie standard, c'est-à-dire jusqu'à ce que le programme soit terminé.
    Et après seulement tu commences à lire la sortie d'erreur. Donc c'est normal.

    Pour le résoudre, le plus simple serait sans doute de ne pas lire la sortie standard. Juste lire la sortie d'erreur et rien d'autre.
    Si je ne me trompe pas, ffmpeg ne met pas grand-chose sur la sortie standard, et a donc peu de chances de remplir le buffer et rester bloqué dessus.

    Et si je me trompe, alors ma foi, oui, il va falloir utiliser deux threads en parallèle : un qui lit la sortie standard et un qui lit la sortie d'erreur.

    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
    Thread stdOutputThread = new Thread(new Runnable() {
      public void run() {
        maMethodeQuiLitLaSortieStandard();
      }
    });
     
    Thread errOutputThread = new Thread(new Runnable() {
      public void run() {
        maMethodeQuiLitLaSortieErreur();
      }
    })();
     
    stdOutputThread.start();
    errOutputThread.start();
     
    stdOutputThread.join();
    errOutputThread.join();
     
    // les deux ont fini.
    Et n'hésite pas à lire la JavaDoc de Thread et des tutoriaux si tu en trouves.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre averti
    Inscrit en
    Février 2011
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 21
    Par défaut
    Merci thelvin!

    Effectivement ce qui m'interesse se trouve dans la sortie d'erreur, et le fait de ne pas lire la sortie standard me permets de ne pas être bloqué..
    Cette solution fonctionne parfaitement!


    Encore merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Filtrage de la sortie standard d'une commande
    Par Platon d'athene dans le forum Débuter
    Réponses: 2
    Dernier message: 24/05/2012, 12h43
  2. Rediriger la sortie standard dans une variable
    Par Erielle dans le forum Shell et commandes GNU
    Réponses: 4
    Dernier message: 22/10/2010, 16h24
  3. [Log4J] Récupérer la sortie standard d'une classe appellée
    Par luthier dans le forum Général Java
    Réponses: 4
    Dernier message: 15/04/2010, 17h22
  4. Récupérer la sortie standard dans une autre classe
    Par EvilAngel dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 22/12/2006, 17h15
  5. Recupération d'un sortie standard via une commande ssh.
    Par yanndan dans le forum Administration système
    Réponses: 1
    Dernier message: 28/08/2006, 16h56

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