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

Go Discussion :

GO 1.21 - Accès aux métadonnées d'un fichier multimédia


Sujet :

Go

  1. #1
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 311
    Points : 202
    Points
    202
    Par défaut GO 1.21 - Accès aux métadonnées d'un fichier multimédia
    Bonjour à tous,

    Je me suis mis à Go depuis quelques jours afin de régler un problème de performance d'un développement en python.

    L'application initiale a pour but de récupérer x fichiers audio ou vidéo (de tous types) et d'en extraire certaines métadonnées. Les résultats sont renvoyés dans un fichier excel.
    Je précise que tout le développement a été fait pour du Windows.

    Pour la version Python, nous avons utilisé ExifTool puis après un LibMediaInfo. Le second a ma préférence, pour cette version.

    J'essaie donc de transposer cette application sur Go et je suis à la recherche d'un package qui me permette de lire les métadonnées aussi simplement que mediaInfo.
    Comme je ne suis pas encore très familiarisé avec la recherche et la gestion des packages, je me tourne vers vous.

    Existe-il un package "natif"/"officiel" qui me permettent d'extraire ces métadonnées. A défaut, auriez vous une idée pour remplacer mediaInfo.

    En vous remerciant par avance.
    Bonne fin de journée
    Douter de tout, toujours, et surtout de soi-même...

  2. #2
    Membre extrêmement actif
    Avatar de Madmac
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    1 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 685
    Points : 1 376
    Points
    1 376
    Billets dans le blog
    7
    Par défaut
    Citation Envoyé par FadeToBlack Voir le message
    Bonjour à tous,

    Existe-il un package "natif"/"officiel" qui me permettent d'extraire ces métadonnées. A défaut, auriez vous une idée pour remplacer mediaInfo.

    En vous remerciant par avance.
    Bonne fin de journée
    C'est trop pointue comme application. La stratégie à adopter est de lancer une commande qui fera l'intermédiaire entre tes fichiers et ton application.
    Il faudrait vérifier si ces méta-données sont fait pour être accessible sous forme de donnée JSON.

    Et comme tu es un débutant,j'ai un petit conseil. C'est un truc qui m'en a fait bavé quand j'ai commencé en Go. Écrire des caractères n'est pas une bonne pratique avec GO. Les opérations sur les chaînes de caractères sont un casse-tête jusqu'à ce que tu maîtrise slice,.

  3. #3
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 311
    Points : 202
    Points
    202
    Par défaut
    Bonjour Madmac,

    Je ne comprends pas ce que tu veux dire par "c'est trop compliqué comme application".

    En pratique, je renseigne un répertoire donné, puis fait une liste de tous les fichiers audio/vidéo qu'il contient.
    A chaque fichier rencontré, je le mets dans un slice.

    une fois cela fait, je reprends chaque ligne du slice et j'extraie les métadonnées qui sont inscrites dans un slice ou un struct (je ne sais pas encore).

    Le but de la transposition de Python à Go est de maximiser le parallélisme de cette dernière partie. Python n'est pas super bon la dessus avec le GIL. Si je peux gagner quelques millièmes ou centièmes de secondes, cela serait terrible, car en général je travaille sur 10 à 20 000 fichiers à chaque fois.

    Ensuite écrire le résultat dans un fichier excel est autre chose. POur le moment, je voudrais faire un benchmark entre les deux langages.

    BOnne journée
    Douter de tout, toujours, et surtout de soi-même...

  4. #4
    Membre extrêmement actif
    Avatar de Madmac
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    1 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 685
    Points : 1 376
    Points
    1 376
    Billets dans le blog
    7
    Par défaut
    Citation Envoyé par FadeToBlack Voir le message
    Bonjour Madmac,

    Je ne comprends pas ce que tu veux dire par "c'est trop compliqué comme application".
    Trop pointu!. Trop spécialisé. Honnêtement je ne suis sur que le langage de base te permette la lecture ou le traitement des méta-données. Le langage est jeune et certaines choses ne sont pas possibles à faire avec ce langage.Tu peux tenter de voir ce que tu obtiens d'une métadonnée avec le type inconnu. {}

    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
    package main
    
    import "fmt"
    
    func main() {
    	var i interface{}
    	describe(i)
    
    	i = 42
    	describe(i)
    
    	i = "hello"
    	describe(i)
    }
    
    func describe(i interface{}) {
    	fmt.Printf("(%v, %T)\n", i, i)
    }
    Tu saisie la métadonnée avec le type inconnu, puis tu cast le résultat en String

    La façon de caster en Go
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var geek1 int = 845
     
    // explicit type conversion
    var geek2 float64 = float64(geek1)
     
    var geek3 int64 = int64(geek1)
     
    var geek4 uint = uint(geek1)
    Le type inconnu est une addition récente au langage. Donc on est un peu en territoire inconnu.

  5. #5
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 311
    Points : 202
    Points
    202
    Par défaut
    Bonjour Madmac,

    J'ai peur qu'il y ait un quiproquo dans notre discussion. Lorsque je parle des métadonnées, j'entends celles du fichiers multimedia considérés.

    En python, j'utilise PyMediaInfo qui est un wrapper de mediaInfo. Voici un exemple d'utilisation (issu de la doc)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    from pymediainfo import MediaInfo
     
    media_info = MediaInfo.parse("/home/user/image.jpg")
     
    general_track = media_info.general_tracks[0]
    image_track = media_info.image_tracks[0]
    print(
        f"{image_track.format} of {image_track.width}×{image_track.height} pixels"
        f" and {general_track.file_size} bytes."
    )
    Ce qui retourne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    JPEG of 828×828 pixels and 19098 bytes.
    Les données en retour sont en général des strings ou des integers. Si on veut obtenir la liste complète, on reçoit, de la librairie soit un tableau de tableau soit si précisé un JSON.

    Personnellement, je travaille soit avec les données unique soit directement avec le fichier JSON.

    Ce sont ces métadonnées que je désire retrouver.

    Si on part de l'exemple ci-dessous, le voudrais retrouver cette chaîne de caractères pour 5000 fichiers et exporter le résultat dans un fichier csv ou excel.
    Le but est de mettre en place des concurrences pour que le principe lecture des métadonnées soit le plus rapide possible.

    J'espère que ces quelques explications nous permettront de nous entendre.

    Bonne journée à toi
    Douter de tout, toujours, et surtout de soi-même...

  6. #6
    Membre éclairé
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 386
    Points : 788
    Points
    788
    Par défaut
    Bonjour FadeToBlack,

    Il n'existe pas de paquet officiel,
    les concepteurs du langage considèrent cela
    comme non essentiel au langage.

    C'est bien évidemment essentiel dans le cadre du développement
    de fonctionnalités comme la vôtre, il ne s'agit pas ici de remettre
    en cause votre besoin.

    Ceci étant établit, il existe des implémentations
    que l'on peut trouver sur Internet, et plus particulièrement,
    via le site officiel du langage https://pkg.go.dev/search?q=exif

    Les premiers résultats sont intéressant, on s'intéressera alors
    à prendre le temps de regarder les métrique d'usage de ces paquets.
    Le nombre d'étoile est intéressant, mais ce n'est pas véritablement significatif.
    Il faudra plutôt vous intéresser à la qualité des rapports de bugs, leurs anciennetés.
    Un autre point intéressant est de regarder les paquets qui en dépendent.
    On observera avec attention les exemples de chacun des paquets, tant aussi bien,
    que les programmes complémentaires fournit par l'auteur, par exemple
    https://github.com/rwcarlsen/goexif/blob/go1/exifstat/main.go


    Nonobstant la difficulté particulière de la gestion du format `exif`,
    il me semble que ce paquet https://github.com/rwcarlsen/goexif est optimal.

    J'aime,

    la diversité des cas de test
    https://github.com/rwcarlsen/goexif/tree/go1/exif/samples

    les tests de régression
    https://github.com/rwcarlsen/goexif/blob/go1/exif/regress_expected_test.go

    Le peu d'activité malgré une ancienneté du paquet
    https://github.com/rwcarlsen/goexif/tree/go1

    La possibilité de rajouter des analyseurs personnalisés
    https://github.com/rwcarlsen/goexif/blob/go1/exif/exif.go#L77

    L'utilisation d'un `io.Reader` comme source de lecture des données, cela permet,
    en théorie, d'éviter de charger des données inutile.
    https://github.com/rwcarlsen/goexif/blob/go1/exif/exif.go#L215


    Concernant le développement spécifique que vous tentez d'implémenter,
    je vous suggère la lecture de ce billet de blog, https://go.dev/blog/pipelines
    Vous y trouverez les briques élémentaire pour atteindre vos objectifs.

    J'attire votre attention sur le fait que l'essentiel du travail de la machine
    dans cette démarche est de transférer de la donnée du disque dur, ou lien réseau,
    vers la mémoire.
    A ce titre un stockage de données optimisé vous aidera à prendre avantage
    des possibilités offerte par la programmation concurrentielle.
    Il faudra par ailleurs prendre garde à tirer parti des APIs du langage
    pour optimiser les procédure de lecture des donnés, en l'occurrence
    bufio.Reader https://cs.opensource.google/go/go/+/refs/tags/go1.21.0:src/bufio/bufio.go;l=47

    Finalement, dans l'optique de la réalisation d'un programme qui exécute efficacement
    la fonctionnalité désirée, veuillez considérer des formats de stockage les plus rudimentaire.
    Excel est lourd, permet beaucoup de choses qui sont inutile à vos objectifs,
    CSV est plus adapté, mais l'on pourra toujours faire mieux en formatant soit même
    la sortie.
    Je vous déconseille le JSON, non pas car je ne l'aime pas, mais car de part sa nature
    particulière, il faudrait enregistrer l'ensemble de vos résultats en mémoire dans
    une tranche https://go.dev/ref/spec#Slice_types avant de pouvoir effectuer
    l'encodage.
    Si jamais l'utilisation de ce format est contraint, je vous suggère plutôt
    le JSONL https://jsonlines.org/ qui permettra d'implémenter une API de flux.

    Bonne Journée.

  7. #7
    Membre extrêmement actif
    Avatar de Madmac
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    1 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 685
    Points : 1 376
    Points
    1 376
    Billets dans le blog
    7
    Par défaut
    Si j'ai bien compris c'est la portion parallélisation qui te pose un problème. J'ai trouver cet article qui me semble prometteur qui pourrait peut-être d'aider. La solution suggéré est de transformé les étapes de traitement ou de filtrage en opération fait avec des flux en parallèle. Mais comme le code est long et détaillé. Un copie d'extrait ne serait pas appropriée: https://go.dev/blog/pipelines

  8. #8
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 311
    Points : 202
    Points
    202
    Par défaut
    Bonjour à vous deux,

    @unanonyme : Merci pour ces informations précises. J'ai regardé une partie des liens fournis et en particulier la librairie goexif.
    En théorie, elle semble correspondre totalement à ce que je voudrais, néanmoins et d'après ce que j'ai pu voir, il ne gère que les fichiers Photo et pas les fichiers audio et vidéo.

    Mais peut-être ais-je mal vu, car de base ExifTool permet d'extraire les métadonnées de tous les types de fichiers multimédia. Je vais essayer de faire un test.

    @Madmac : Ma problèmatique n'est, par encore, sur la gestion des concurrences, parallélisme et autres. Je n'en suis pas encore là de mon apprentissage du langage. Mais je pense que cela va venir.

    Pour le moment, je veux juste trouver un paquet (une librairie) qui puisse me permettre de voir les éléments des fichiers.


    Encore merci à vous deux et bonne journée
    Douter de tout, toujours, et surtout de soi-même...

  9. #9
    Membre éclairé
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 386
    Points : 788
    Points
    788
    Par défaut
    Bonjour,

    En effet, pour un support étendu des fichiers cette librairie
    ne sera pas peut être pas capable de répondre à votre
    besoin.

    Plusieurs options s'offre à vous.

    - Opter pour une librairie qui fournit une API
    de liaison Go->C comme celle ci :
    Elle utilise la librairie ffmpeg5.1 pour de meilleurs résultats

    https://pkg.go.dev/github.com/mutablelogic/go-media

    - Opter pour une librairie Go qui aura pour tâche
    de conduire l'exécution d'un binaire

    A titre d'exemple,
    https://pkg.go.dev/github.com/robmurtha/expose

    - Opter pour l'écriture d'une librairie Go afin
    de répondre à cette tâche.

    A bien regarder le site du programme exiftool
    c'est une tâche qui semble audacieuse.
    On regardera le code source pour s'en donner une idée.
    https://github.com/exiftool/exiftool


    Bonne journée

  10. #10
    Membre éclairé
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 386
    Points : 788
    Points
    788
    Par défaut
    Bonjour,

    En prenant quelques instants pour m'intéresser à votre librairie
    python j'ai remarqué que c'était une librairie de liaison vers une librairie
    particulière.

    https://github.com/sbraz/pymediainfo

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    This small package is a wrapper around the MediaInfo library.
    Je suppose qu'il s'agit de celle ci :

    https://mediaarea.net/en/MediaInfo

    En commençant par là, il est possible de trouver
    quelques paquets dédiés à cette librairie.

    https://pkg.go.dev/search?q=mediainfo

    Bonne journée.

  11. #11
    Membre éclairé
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 386
    Points : 788
    Points
    788
    Par défaut
    Bonjour,

    Par curiosité j'ai fait le travail inverse, écrire une version python,
    langage avec lequel je n'ai pas d'expérience significative.

    Sans efforts d'optimisation particuliers, j'observe un gain.
    Le banc de test est composé de 3000 fichiers de quelques centaines d'octet à 2/3 Mo.
    La machine est (en gros) un core i7 avec du SSD.
    L'exécution Go est un peu plus rapide, de l'ordre d'une seconde,
    sur cet ordinateur et ce jeu de données.

    Néanmoins, plusieurs problèmes se posent pour comparer.
    - l'essentiel du temps CPU dépensé est situé dans la dépendance C, on ne pourra rien y faire.
    - les deux programmes ne réalisent pas exactement la même chose.
    C'est vaguement similaire.

    Dans cette situation il est difficile de trancher sur le cap à suivre.

    Je notes tout de même quelques points.
    - L'environnement d'exécution Go utilise mieux les ressources CPU
    que le Python.
    - Le code Python est plus concis, peut être plus simple pour ce que l'on
    attend de ce programme

    Dans les deux cas l'outillage de profilage est sensiblement le même.

    Pour référence,

    main.py

    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
     
    import time
    import sys
    from threading import Thread
    from pymediainfo import MediaInfo
    import pathlib
     
    path = "chemin d'accès"
    if len(sys.argv)>1:
        path = sys.argv[1]
     
    thread_cnt = 2
    if len(sys.argv)>2:
        thread_cnt = int(sys.argv[2])
     
    threads = []
    lst = []
     
    desktop = pathlib.Path(path)
    for item in desktop.rglob("*"):
        if item.is_file():
            lst.append(item)
     
    def parseMediaInfo(files):
        for f in files:
            mi = MediaInfo.parse(f)
            x = mi.to_json()
            print(x, end="\n")
     
     
    items_cnt = len(lst) / thread_cnt
    for i in range(thread_cnt):
        begin = int(items_cnt*i)
        end = int(items_cnt*(i+1))
        if end > len(lst):
            end = int(len(lst))
        t = Thread(target=parseMediaInfo, args=(lst[begin:end],))
        threads.append(t)
     
    for t in threads:
        t.start()
    for t in threads:
        t.join()
     
    print(len(lst), "\n")

    main.go

    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
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
     
    package main
     
    import (
    	"bufio"
    	"bytes"
    	"encoding/json"
    	"errors"
    	"flag"
    	"fmt"
    	"io"
    	"io/fs"
    	"log"
    	"os"
    	"path/filepath"
    	"strings"
    	"sync"
     
    	"github.com/Voodfy/go-mediainfo/mediainfo"
    	"github.com/pkg/profile"
    )
     
    func main() {
     
    	d := "chemin d'accès"
     
    	directory := flag.String("directory", d, "directory to scan")
    	concurency := flag.Int("concurrency", 1, "set the concurrency level")
    	profil := flag.String("pprof", "", "a profile kind to record (cpu, mem, allocs)")
    	flag.Parse()
     
    	{
    		profiles := map[string]func(p *profile.Profile){
    			"cpu":    profile.CPUProfile,
    			"mem":    profile.MemProfile,
    			"allocs": profile.MemProfileAllocs,
    		}
    		if *profil != "" {
    			p, ok := profiles[*profil]
    			if ok {
    				defer profile.Start(
    					profile.Quiet,
    					profile.ProfilePath("."),
    					p,
    				).Stop()
    			}
    		}
    	}
     
    	_ = directory
    	_ = concurency
     
    	if *concurency < 1 {
    		log.Println("invalid concurrency level, it must be greater than 0")
    		os.Exit(1)
    	}
     
    	if *directory == "" {
    		log.Println("invalid directory, the value is required")
    		os.Exit(1)
    	}
     
    	dst := io.Writer(os.Stdout)
    	// dst = io.Discard
    	var err error
    	if *concurency < 2 {
    		err = procedural(*directory, dst)
    	} else {
    		err = concurrent(*directory, *concurency, dst)
    	}
     
    	if err != nil {
    		log.Println("an error occured:", err)
    		os.Exit(1)
    	}
     
    }
     
    func procedural(directory string, dst io.Writer) error {
     
    	enc := json.NewEncoder(dst)
    	mi := mediainfo.New()
    	defer mi.Close()
     
    	filesystem := os.DirFS(directory)
    	err := fs.WalkDir(filesystem, ".", func(path string, d fs.DirEntry, err error) error {
    		if err != nil {
    			return err
    		}
    		if d.IsDir() {
    			return nil
    		}
    		path = filepath.Join(directory, path)
    		res := parseMediaInfo(mi, path)
    		err = enc.Encode(res)
    		return err
    	})
     
    	return err
    }
     
    func concurrent(directory string, cnt int, dst io.Writer) error {
    	in := make(chan string, 100)
    	out := make(chan parsedMediaInfo, 100)
    	generalError := make(chan error, 2)
     
    	var wg sync.WaitGroup
    	for i := 0; i < cnt; i++ {
    		wg.Add(1)
    		go func() {
    			defer wg.Done()
    			mi := mediainfo.New()
    			defer mi.Close()
    			for file := range in {
    				out <- parseMediaInfo(mi, file)
    			}
    		}()
    	}
    	go func() {
    		wg.Wait()
    		close(out)
    	}()
     
    	var wgErr sync.WaitGroup
    	wgErr.Add(1)
    	go func() {
    		defer wgErr.Done()
    		filesystem := os.DirFS(directory)
    		err := fs.WalkDir(filesystem, ".", func(path string, d fs.DirEntry, err error) error {
    			if err != nil {
    				return err
    			}
    			if d.IsDir() {
    				return nil
    			}
    			path = filepath.Join(directory, path)
    			in <- path
    			return nil
    		})
    		if err != nil {
    			generalError <- err
    		}
    		close(in)
    	}()
     
    	wgErr.Add(1)
    	go func() {
    		defer wgErr.Done()
    		enc := json.NewEncoder(dst)
    		_ = enc
    		i := 0
    		defer func() {
    			fmt.Println(i)
    		}()
    		for res := range out {
    			i++
    			err := enc.Encode(res)
    			if err != nil {
    				generalError <- err
    				break
    			}
    		}
    		for range out {
    		}
    	}()
    	go func() {
    		wgErr.Wait()
    		close(generalError)
    	}()
     
    	var err error
    	for e := range generalError {
    		err = errors.Join(err, e)
    	}
    	return err
    }
     
    type parsedMediaInfo struct {
    	Err  string `json:",omitempty"`
    	Info map[string]map[string]string
    }
     
    func parseMediaInfo(mi *mediainfo.MediaInfo, file string) (res parsedMediaInfo) {
     
    	if err := mi.Open(file); err != nil {
    		res.Err = fmt.Sprintf("%v: %v", err.Error(), file)
    		return
    	}
     
    	info := mi.Inform()
    	res.Info = map[string]map[string]string{}
     
    	sc := bufio.NewScanner(bytes.NewBufferString(info))
     
    	var currentKind string
    	lineIndex := -1
    	for sc.Scan() {
    		l := sc.Text()
    		l = strings.TrimSpace(l)
    		lineIndex++
     
    		if len(l) < 1 {
    			continue
    		}
     
    		semiColonPos := strings.Index(l, ":")
    		if semiColonPos < 0 {
    			currentKind = l
    			res.Info[currentKind] = map[string]string{}
    			continue
    		}
     
    		if currentKind == "" {
    			res.Err = fmt.Sprintf(
    				"unable to parse the content at line %v in file %v",
    				lineIndex, file,
    			)
    			return
    		}
     
    		col := l[:semiColonPos]
    		value := l[semiColonPos:]
     
    		col = strings.TrimSpace(col)
    		value = strings.TrimSpace(value)
     
    		res.Info[currentKind][col] = value
    	}
    	if err := sc.Err(); err != nil {
    		res.Err = fmt.Sprintf(
    			"unable to parse the content at line %v in file %v",
    			lineIndex, file,
    		)
    	}
     
    	return
    }
    Bonne Journée.

Discussions similaires

  1. [Python 3.X] Accès aux métadonnées d'un ficher XLS avec Python
    Par MajeQC dans le forum Général Python
    Réponses: 1
    Dernier message: 26/10/2015, 17h35
  2. accès aux métadonnées d'une photo
    Par TERRIBLE dans le forum Windows Presentation Foundation
    Réponses: 2
    Dernier message: 11/04/2011, 06h54
  3. Accès aux données d'un fichier XML
    Par emmab dans le forum Flash
    Réponses: 2
    Dernier message: 13/08/2009, 12h07
  4. Accéder aux métadonnées d'un fichier
    Par Laur3nT dans le forum Windows Forms
    Réponses: 8
    Dernier message: 29/05/2008, 09h59
  5. Pas accès aux lots SQL et fichiers DTS
    Par elmagnifico dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 09/09/2003, 08h51

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