Fwomaj 0.3 : Vidéos à la coupe au rayon frais

37
14
juil.
2016
Audiovisuel

Fwomaj est un lecteur multimédia qui permet la sélection rapide de fichiers vidéo au retour d'une séance de tournage (on dit « dérusher ») pour un montage ultérieur. Fwomaj est sous licence GPL 2.

Sommaire

Fwomaj 0.3

En premier lieu, il affiche la forme d'onde de la piste audio du fichier, afin de savoir tout de suite s'il s'y trouve du son, et à quel endroit.

Il permet également le transcodage de la vidéo en H264, et sa sauvegarde dans les trois containers courants: Matroska (.mkv) MPEG-4 (.mp4) et AVI (.avi) que l'utilisateur choisit à l'aide d'un menu.

Et enfin, il permet de couper le début et la fin de la vidéo à l'aide de contrôles visuels.

En bonus, il fournit également une fenêtre d'information qui liste les caractéristiques multimedia du fichier de façon exhaustive.

Fwomaj ICON

Code

Fwomaj est en Python 3, l'interface est en Gtk 3. Le moteur vidéo (et audio) est GStreamer 1.0.

Dépendances

Son & Lumières

C'est bien sûr FFmpeg qui fait le gros du travail : c'est lui qui génère l'image de la forme d'onde, lui encore qui découpe le fichier de temps à temps+n, et lui enfin qui encode tout ça, à son rythme de supertanker.

Au moment où l'utilisateur appuie sur Encode on récupère les valeurs des menus (qui sont par défaut aux valeurs que moi, j'utilise : 30 images / secondes, Matroska) et celles des deux réglettes début/fin, et on construit la commande FFmpeg (et le nom du fichier de destination) avec tout ça :

out_file = '{}_{}-{}_{}fps.{}'.format(filename,
                                      str(start_time),
                                      str(end_time),
                                      self.frame_rate,
                                      self.file_format)

command = [FFMPEG, '-y',
           '-i', filename,
           '-r', self.frame_rate,
           '-strict', '-2',
           '-c:v', 'libx264',
           '-ss', start_time,
           '-to', end_time,
           out_file]

Et on envoie tout ça à une classe qui

  • lance le process (en asynchrone, et rend la main) ;
  • vérifie toutes les secondes qu'il n'est pas fini ;
  • avertit l'utilisateur quand il est fini.

Le fichier de destination est sauvé dans le répertoire du fichier d'origine.

Au chargement d'un fichier multimedia – au lancement du programme ou après – c'est le même processus qui gère la génération de la forme d'ondes, qui s'affiche quand elle est prête (pour un gros fichier, ça peut prendre plusieurs longues secondes) sans ralentir l'interface.

Êtes-vous sûr de ne pas vouloir arrêter le processus d'annulation ?

Du coup, comme je ne lis pas la sortie de FFmpeg (je vérifie juste les codes de retour) je suis en asynchrone, yay, mais je perds la possibilité d'informer l'utilisateur de l'avancement du travail en cours, bouh ; juste un bidule qui pulse pour indiquer qu'il se passe quelque chose. Notez que FFmpeg lui-même ne le fait pas, mais il indique quelle image il est en train de traiter, or moi, j'ai plein de moyens de savoir combien d'images fait mon fichier, à commencer par Mediainfo. Eh. Dommage.

Pour arrêter un job FFmpeg qui prendrait trop de temps, il faut quitter le programme. Je ne suis pas en train de décrire un choix d'implémentation là, hein, mais la conséquence du choix de ne rien implémenter du tout pour le moment.

Chez moi, ça marche (tm) :) mais je vais quand même, c'est sûr, à un moment, faire une entrée de menu avec un raccourci clavier pour envoyer q au process FFmpeg en cours (oui, il écoute stdin – à la fois des pipes nommés pour le streaming ET le clavier pour les commandes – et s'exprime exclusivement sur stderr, il est spé' FFmpeg) j’attends de voir un peu comment ça se passe au niveau ergonomique.

Genre de style d'UI

Afficher une image, l'étirer sur toute la largeur de la fenêtre principale, puis la re-dimensionner quand change la taille de cette dernière, est un processus assez lourd, qui implique une gestion relativement fine des événements, si on veut faire ça en utilisant les classes et méthodes de Gtk lui-même (Gtk.image, Gtk.Pixbuf, Gtk.DrawingArea, Gtk.ScrolledWindow etc.) c'est ainsi que marchait la première version en Python2/Gtk2, mais le principe est le même.

Mais Gtk3 intègre CSS3, ce qui a permis de remplacer ce genre de machin :

    def on_resize(self, widget, event, window):

        allocation = widget.get_allocation()
        if self.temp_height != allocation.height or self.temp_width != allocation.width:
            self.temp_height = allocation.height
            self.temp_width = allocation.width
            pixbuf = self.waveform_image.get_pixbuf().scale_simple(allocation.width, 
                                                                   allocation.height,
                                                                   gtk.gdk.INTERP_NEAREST)
            widget.set_from_pixbuf(pixbuf)

Oui oui, c'est bien ça, à chaque événement (cette fonction est un callback sur l'événement on_resize de la fenêtre, donc des centaines de fois par seconde, dans la joie) on re-crée un pixbuf en attrapant celui de l'image en place, on le retaille aux dimensions XY de la fenêtre, et on le remet dans l'image, qu'on remet dans le widget, ouf :/ c'est comme ça qu'on fait, au centre hippique PyGtk.

Par quelque chose comme ça:

CSS = '#WBox {background-size:100% 100%;background-image: url("{}");}'.format(uri)

style_provider.load_from_data(CSS)

Quand j'ai percuté (je suis développeur web, moi, à la base) genre sous la douche, je me suis dit c'est pas possible, ça peut pas être si simple, ça a marché au premier essai.

Mediainfo

…Est le meilleur outil d'analyse de fichiers multimédia, oui du monde, même sans les mains, point final. J'avais commencé à implémenter une usine à mazout en utilisant les fonctions de "découverte" de GStreamer, pour éviter une dépendance, mais sa souplesse et son intelligence relative étaient ridicules face aux capacités d'introspection de Mediainfo.

Bugs

Quoi ? Naaan :) Si. On commence par les petits.

Blanker (Gtk)

Quand on passe en plein écran, les contrôles disparaissent, ainsi qu'il est d'usage. Ce n'est pas du vrai plein écran d'ailleurs, au sens où on l'entend : Le gestionnaire de fenêtre n'est pas averti, pour commencer, enfin je crois, je maximise juste la Gtk.DrawingArea où j'affiche les pixels qu'envoie le pipeline de GStreamer.

Quand on bouge la souris, ces contrôles réapparaissent, toujours selon les protocoles en vigueur. Mais je n'ai pas réussi (j'y ai passé toute une soirée !) à démarrer un timer à ce moment, pour qu'au bout de, mettons 10 secondes d'inactivité de la souris ou du clavier, lesdits contrôles disparaissent à nouveau. Je parie que c'est une tarte à la crème, un classique du développement d'interfaces graphiques, et que quelqu'un ici va bien nous trouver une solution :)

Rendu (GStreamer)

Ça n'a bien sur pas d'incidence sur le fichier produit, mais le rendu vidéo est bordé d'un pixel de couleur, variable, comme une sorte de somme spectrale de l'image en cours, et ça bouzille le noir qui est d'usage autour de tout film décent. Mon implémentation est bancale, clairement. Je déteste ce bug minuscule et en même temps énorme, il me donne l'impression de ne rien contrôler du tout.

C'est évidemment un bout de code que j'ai copié collé de je ne sais plus d'où, car c'est pas du tout comme s'il existait ne serait-ce qu'une page dans tous les interfubles qui dit "bon, voilà, GStreamer 1.0 est sorti, même gst-launch a été renommé gst-launch-1.0 pour qu'on comprenne bien que plus rien n'est compatible, et donc voilà quelques exemples d'usage en Python3 / Gtk3 oh rien du tout, juste une implémentation de base.

On peut faire plein de choses avec GStreamer. C'est un langage de pipes vidéo assez fascinant, qu'on prototype à l'aide de l'utilitaire gst-launch, pour construire des "tuyaux" d'images qui bougent:

gst-launch-1.0 videotestsrc pattern=1 ! video/x-raw,format=AYUV,framerate=\(fraction\)10/1,width=100,height=100 ! videobox border-alpha=0 top=-70 bottom=-70 right=-220 ! videomixer name=mix sink_0::alpha=0.7 sink_1::alpha=0.5 ! videoconvert ! xvimagesink videotestsrc ! video/x-raw,format=AYUV,framerate=\(fraction\)5/1,width=320,height=240 ! mix.

Mais GStreamer est si complexe que sa documentation plane dans les limbes…

Du coup GStreamer est… magique :

GStreamer

Sur cette image prise en plein écran (la sublime ouverture de « Michael Clayton  », T. Gilroy 2007) on remarque deux choses : l’agaçante bande de couleur évoquée plus haut (deux pixels mauves à gauches, et une sorte de frange verte intermittente d'un pixel tout autour) et les sous-titres… attend, quoi ?

Sous-titres (anti-bug, GStreamer)

Oui. GStreamer, sans que j'ai fait quoi que ce soit pour ça, m'extrait avec force diligence les sous-titres du container du film en question (Matroska, en l'occurence, qui est réputé pour ça entre autres) et me les affiche, synchronisés, en Times, c'est trop chou, mais, heu, comment je contrôle ça ? Une fonction (et pas n'importe quoi, la gestion des sous-titres je voulais même pas seulement y penser) qui tombe en marche par accident, c'est un bug aussi, non ? GStreamer 0.10 ne faisait pas ça ; on va pas se plaindre trop fort non plus, allez.

États (non-bug, Python)

Mon usage de Fwomaj est le suivant : Je double-clique sur un fichier vidéo, je le regarde ou je l'édite, bref je fais ce que j'ai à faire avec, et je le ferme. Et ça, ça marche très bien. Mais d'autres peuvent vouloir l'utiliser différemment. C'est dans cet esprit que j'ai codé un « Open File » dont je me sers jamais, par exemple ; quand on a fini d'encoder une vidéo, l'état de Fwomaj n'est pas vraiment net-net. Si ça se trouve, ça marche très bien, mais je n'ai pas testé cet usage (ouvrir un fichier, et l'encoder plein de fois avec plein de paramètres différents, puis en ouvrir un autre, dans la même instance, tiens, rien que le fait d'écraser le fichier — c'est ce qu'on fait maintenant : mêmes paramètres, même début, même fin = même nom de fichier, on écrase — c'est bien gentil, ça marche, mais si j'étais responsable Debian (par exemple) je ne laisserais clairement pas passer Fwomaj dans les dépôts officiels, à cause de ce genre de détail.

Ça vient de ma façon de coder, procédurale sinon déclarative (on dit aussi « travail de goret » par chez moi) et c'est vrai que je voulais juste un lecteur pour visionner, couper mes rushes et en harmoniser les caractéristiques pour pouvoir les monter sans devenir encore plus dingue (intermède : si tu achètes un SONY Alpha Nex5 au Japon ou aux USA, il fait des vidéos en 30 et 60 images/secondes. Si tu as la mauvaise idée de l'acheter en Europe, c'est une autre machine, modifiée en dur pour produire des vidéos en 25/50 images/secondes, et je ne ferai pas d'autre commentaire là-dessus, c'est mieux pour la tenue de cette dépêche) et que ce lecteur, je l'ai, super.

Maintenant, si j'avais un vœu pour ce petit bout de logiciel au-delà de ce qu'il m'apporte maintenant, c'est qu'un de ces gourous qui traînent par ici (nan mais vous pouvez filer en douce, trop tard hein, on lit vos commentaires, vous croyez quoi ?) se penche sur son berceau pour en ré-usiner (tiens, ça claque encore mieux en français dis-donc) le code en profondeur, oui. Fwomaj 0.3, en l'état, est un prototype. Qui marche pas mal, mais un prototype quand même. Il me semble que c'était ça l'idée de Python, non, de bricoler vite fait des trucs qui marchottent pas mal ? Bon, ben c'est réussi, merci les gars :)

Installation

En pratique, je n'ai testé Fwomaj 0.3 que sous Ubuntu 14.04 et 16.04, avec les environnements de bureau Unity et XFCE.

Debian

wget https://bitbucket.org/yphil/fwomaj/downloads/fwomaj_0.3_all.deb && sudo gdebi fwomaj_0.3_all.deb

Oui, je n'ai pas trouvé comment installer les dépendances d'un paquet (duh) avec dpgk..?

Ou on peut aussi construire soi-même le paquet. Ne pas se laisser abuser par le répertoire ./debian, Fwomaj est juste un script Python de 800 lignes et une icône.

git clone https://bitbucket.org/yphil/fwomaj.git
cd fwomaj
./build_package.sh
sudo gdebi -i ../fwomaj_0.3_all.deb

Et les autres systèmes?

Pour les autres Linux, ça doit être assez trivial. À minima, le script peut être lancé tel quel sur une machine où sont installées les quatre dépendances, il n'aura juste pas d'icône. Les outils qui servent à créer des paquets pour d'autres distributions n'auront probablement aucun mal à se débrouiller avec les éléments présents :

  • exécutable ;
  • page de man (minimale, exigée par Lintian) ;
  • icônes ;
  • journal (changelog) ;
  • et éventuellement les fichiers de contrôle/description, tout ça n'est guère spécifique.

Pour les autre systèmes, honnêtement, je ne sais pas. Bien sûr, on doit pouvoir faire tourner Gtk3 sous Windows, FFmpeg aussi mais GStreamer, je suis moins sûr.

En tout cas, les spécificités du système d'exploitation sont abstraites autant que faire se peut :

unique_file = os.path.join(tempfile.gettempdir(), 'fwomaj-{}.png'.format(time.time()))

Devrait marcher partout, en principe.

Il parait qu'il y a Python sous AmigaOS, maintenant :|

J'utilise Fwomaj depuis une petite quinzaine comme lecteur principal, j'ai préparé une demi-douzaine d'épisodes avec, et encodé un grand nombre de fichiers d'origines diverses, ça marche bien.

Allez-y, testez ;)

  • # Commentaires rapides

    Posté par (page perso) . Évalué à 7.

    dpkg gère les installations/mises à jour/suppressions de paquets, c'est dans apt (& friends/concurrents) que tu trouveras la partie résolution de dépendances.

    La page de manuel est construite (à partir du fichier d'exemple SGML) mais n'est pas embarquée dans le paquet résultant (tu pourrais la lister dans debian/manpages pour qu'elle le soit, mais il faudrait probablement commencer par modifier le boilerplate).

    J'ai bien fait de lancer la compilation à coup de debuild directement, le script build_package.sh semblant vouloir lancer un upload…

    En tout cas, cela semble se lancer et tourner correctement sur Debian Jessie. Peut-être que « Tous les fichiers » ou « Tous les fichiers vidéo » serait un meilleur choix dans le sélecteur de fichier ?

    Debian Consultant @ DEBAMAX

    • [^] # Re: Commentaires rapides

      Posté par (page perso) . Évalué à 1. Dernière modification le 15/07/16 à 09:46.

      dpkg gère les installations/mises à jour/suppressions de paquets, c'est dans apt (& friends/concurrents) que tu trouveras la partie résolution de dépendances.

      Oui, et justement, gdebi (ça commence à faire beaucoup de solutions pour installer des machins, more is less) que je ne connaissais pas. Au passage, ça fait des années que je crois installer les dépendances quand je dpkg -i (heureusement, c'est bien sur très rare, et ça n'arrivera plus: qui veut installer un paquet sans ses dépendances?) ce qui n'est pas sympa, grmph.

      La page de manuel est construite (à partir du fichier d'exemple SGML) mais n'est pas embarquée dans le paquet résultant (tu pourrais la lister dans debian/manpages pour qu'elle le soit, mais il faudrait probablement commencer par modifier le boilerplate).

      Ah tiens, je me disais aussi, que man fwomaj ne marchait pas (mais qui va taper ça ? :p) et de fait tu as raison, je ne fais que la générer:

      docbook-to-man debian/fwomaj.sgml > debian/fwomaj.1

      Mais je ne la copie pas dans l'archive! Bien vu.

      J'ai bien fait de lancer la compilation à coup de debuild directement, le script build_package.sh semblant vouloir lancer un upload…

      Oui (seulement si le build a réussi, note bien) mais bon, à ce stade si tu n'est pas moi, tu n'as qu'à ctrl+c puisque tu n'as pas ma clef, et tu as le paquet. C'est moins un script qu'un aide-mémoire, build_package.sh.

      En tout cas, cela semble se lancer et tourner correctement sur Debian Jessie. Peut-être que « Tous les fichiers » ou « Tous les fichiers vidéo » serait un meilleur choix dans le sélecteur de fichier ?

      Hm. C'est moins trivial qu'il n'y parait ; Actuellement, pour la requête de fichiers je construis "à l'équestre" 4 filtres, les types MIME que Fwomaj écrit, plus "Tous les fichiers", "*". Et oui, tu as raison, ce dernier devrait plutôt être un combo des premiers. Comme je l'ai dit dans la dépêche, ça ne correspond pas à mon usage, mais bon, j'ai pas non plus l'intention de sortir cette excuse tout le temps hein :) Note que les mimetypes sont correctement indiqués dans le fichier .desktop (j'ai recopié celui de smplayer) et que Fwomaj se comporte doit se comporter convenablement pour clic-droit "ouvrir avec…" avec un WM décent.

      Sans ça, pendant la rédaction de la dépêche, palm123< m'a donné plein de liens précieux pour faire une image docker (et pour comprendre exactement ce que c'est que Docker tout court pour commencer) heureusement que j'ai cliqué sur la plupart (mais pas tous) car le log est dans devnull maintenant..? :/

    • [^] # Re: Commentaires rapides

      Posté par (page perso) . Évalué à 2. Dernière modification le 15/07/16 à 10:27.

      Peut-être que « Tous les fichiers » ou « Tous les fichiers vidéo » serait un meilleur choix dans le sélecteur de fichier ?

      La meilleure implémentation serait celle qui interroge à la fois FFmpeg et GStreamer (c'est très simple, il y a une commande pour ça, en tout cas il y a ffmpeg -codecs) pour savoir exactement quels types de fichier on peut lire et écrire sur cette very machine. Quand je dis que ce n'est qu'un proto, c'est exactement ça que je veux dire.

      Allons plus loin, car on est au coeur du sujet, là. Toutes les combinaisons codec/conteneur ne sont pas possibles. Enfin si, tout est possible, mais certaines combinaisons bizzares ne seront pas faisables en une commande FFmpeg. Il en faudra plusieurs.

      Tout ça devrait pourrait être géré par une logique

      • Interrogation des capacité locales
      • Construction des filtres MIME
      • Construction des menus, qui présentent seulement les combinaisons possibles
        • Soit en grisant/supprimant à la volée les entrée de menu et fonctionnalité non compatibles entre elles
        • Soit en se débrouillant pour que tout soit compatible

      Mais pour ça il faut un spécialiste des invocations ésotériques de FFmpeg. Je dis ésotérique mais c'est pas très juste, c'est simplement très puissant, mais à la différence de GStreamer, c'est bien documenté. Juste un exemple, le switch -r $Nombre_images/secondes selon que tu l'utilises en entrée (CàD que tu le spécifies juste après le premier -i) fait les choses très différemment:

      As an input option, ignore any timestamps stored in the file and instead generate timestamps assuming constant frame rate fps. This is not the same as the -framerate option used for some input formats like image2 or v4l2 (it used to be the same in older versions of FFmpeg). If in doubt use -framerate instead of the input option -r.

      As an output option, duplicate or drop input frames to achieve constant output frame rate fps.

      Or selon que tu utilises telle option ou telle autre, tu pourras utiliser tel codec (note que le codec de Fwomaj est en dur: Dommage) or nous, comme on ne lit basiquement pas les erreurs de FFmpeg, j'ai choisi de limiter les paramètres de ses invocations à ceux que je connais et utilise et qui sont compatibles entre eux, ce qui fait peu ; note que bon, ça correspond aux standards pour autant que je sache.

      Tu vois la complexité grandissante si tu veux faire quelque chose de réellement intelligent et "universel" (disons terrestre, déjà) ? Overwhelming. On peut juste s'approcher au plus près de quelque chose d'utilisable et standard.

      • [^] # Commentaire supprimé

        Posté par . Évalué à -7. Dernière modification le 15/07/16 à 12:58.

        Ce commentaire a été supprimé par l'équipe de modération.

        • [^] # Re: Commentaires rapides

          Posté par (page perso) . Évalué à 3.

          Yep. Il faudrait des années pour tout tester. Avoir plein de fichiers bien pourris, avec des corruptions dans des endroits bien tordus… Faire plein de combinaisons improbables, ou pas.

          Note que ça ressemble au job idéal pour "super test unitaire". "Est-ce un oiseau, un avion ? Non, c'est super unit-test" :) Il faudrait commencer par coder une routine qui corrompt exprès des fichiers multimedia pour avoir du matos pour tester.

          Donc oui, considérant l'alternative, tavu, mon approche "juste les valeurs qui marchent en dur" a du sens :) Bon par ailleurs oui, il semble y avoir beaucoup de NIH sur les codecs et les containers, mais aussi plein d'autres critères.

          Voir les journaux et comms de Zenitram sur le sujet. Bonne chance pour les retrouver dans la masse ;)

          Spécifiquement, j'aimerais bien (le mot est faible) un journal ou une dépêche sur les horreurs qu'il a forcément du rencontrer dans sa tache pharaonique de "je lis tous les fichiers multimedia" plus on bosse avec (et bon, j'ai fait Louis Lumière dans les 80s, en fait les formats image/videos, j'ai passé un peu de temps sur la question quand même, sans parler de mes multiples - et tout nazes à coté - parsers à moi) plus on réalise l'ampleur de la tache. Par exemple quand je pense à pourrir soi-même les fichiers (accents chelous dans les tags, je sais pas, anything) pour écrire des tests unitaires, j'ai bon, non ?

          Je veux dire, à chaque itération du code de mediainfo, il faut tout re-tester, non ? Et les évolutions des codecs et des containers, des specs ? Ze-ni-tram, un-jour-nal! (tous avec moi) ZE-NI-TRAM, UN-JOUR-NAL! :D

          • [^] # Commentaire supprimé

            Posté par . Évalué à -7. Dernière modification le 15/07/16 à 15:59.

            Ce commentaire a été supprimé par l'équipe de modération.

          • [^] # Re: Commentaires rapides

            Posté par (page perso) . Évalué à 1.

            Spécifiquement, j'aimerais bien (le mot est faible) un journal ou une dépêche sur les horreurs qu'il a forcément du rencontrer dans sa tache pharaonique de "je lis tous les fichiers multimedia" plus on bosse avec

            Mouais, mais pour décrire toutes les merdes et les hacks de MI pour le gérer, il me faudrait 1 ou 2 semaines (ou plus) pour écrire le journal. Et c'est pas un taf des plus motivant.

            • [^] # Re: Commentaires rapides

              Posté par (page perso) . Évalué à 2.

              Mouais, mais pour décrire toutes les merdes et les hacks de MI pour le gérer, il me faudrait 1 ou 2 semaines (ou plus) pour écrire le journal. Et c'est pas un taf des plus motivant.

              Je vois très bien ce que tu veux dire. C'est (très) dur à écrire, ce genre de trucs, mais c'est très rigolo à lire :p

  • # Génial

    Posté par . Évalué à 5.

    J'ai adoré ta dépêche, c'est vraiment en plein dans l'idée que je me fait de linuxfr : c'est une présentation mais aussi un retour d'expérience et surtout un partage.

  • # MediaInfo

    Posté par (page perso) . Évalué à 2.

    Mediainfo… Est le meilleur outil d'analyse de fichiers multimédia, oui du monde, même sans les mains, point final.

    J'aime.
    (désolé)

    J'avais commencé à implémenter une usine à mazout en utilisant les fonctions de "découverte" de GStreamer, pour éviter une dépendance, mais sa souplesse et son intelligence relative étaient ridicules face aux capacités d'introspection de Mediainfo.

    Par curiosité, quel reproche fais-tu sur la souplesse de GStreamer? A première vue, son API semble propre.
    Et tu as rencontré des fichiers qui t'ont donné du fil à retordre ("intelligence relative")?

    • [^] # Re: MediaInfo

      Posté par (page perso) . Évalué à 2.

      (désolé)

      ?

      Et tu as rencontré des fichiers qui t'ont donné du fil à retordre ("intelligence relative")?

      Oui. Concrètement, des fichiers dont mon parser n'arrivait pas à lire la durée et le nombre de frames (les infos qui m'intéressent en priorité, ah j'ai oublié de dire dans le journal que MI, du coup, ne sert pas qu'à remplir la fenêtre "file info" mais également à donner les infos de base sur le fichier à l'ouverture, pour construire les réglettes, entre autres.

      Donc oui, quand à un moment je charge un fichier, et que mon début d'implémentation (bien sur que c'est pas la faute de GStreamer) me renvoie une valeur différente que celle que me donne MI, je réfléchis pas, je benne le premier et garde le second.

  • # Improvements ?

    Posté par . Évalué à 5.

    Salut,

    j'ai rapidement jeter un œil a ton code (le nom m'a fait marrer): bon on est d'accord pour une PoC c'est bien mais ça risque d'en dissuader plus d'un =D.
    Mes modestes conseils (qui son mes guidelines, vous aurez surement les votres) qui pourraient t'aider:

    • essaie de séparer la partie "lib" de la partie interface GTK et de la partie exécution de script pour commencer. Simplement tu peux faire un package fwomaj/ dans lequel tu crées 3 modules par exemple libfwomaj.py, cmd_scripts.py, gtk_ui.py ; En gros ça te permet si un jour tu veux faire un support en CLI d'ajouter un cli_ui.py qui utilisent tes popen de libfowmaj.py sans tout refaire.

      • libfwomaj.py : tu y mets toute tes fonctions ffmpeg, gstreamer, et mediainfo dans un premier temps, puis essaie de faire des objets et des mixin pour emballer/structurer le tout,
      • cmd_scripts.py : tu y mets la partie pour exécuter la ligne de commande (en gros ce que tu mettrais dans une fonction main (que tu n'as pas fait) ie: tes lignes 769-772) ce qui permet d'ajouter un parser, des options par défauts, bref la partie système,
      • gtk_ui.py : toute ta partie concernant gtk, décorrélée de toute ce que tu as mis dans les autres fichiers.
    • pour mediainfo tu peux utiliser le wrapper python PyMediainfo https://pymediainfo.readthedocs.io/en/latest/ ça t'évite d'aller ouvrir un popen pour récupérer les infos ;)

    D'une façon générale, j'aurai fait un objet Fwomaj qui lui va réaliser le binding entre la video et ton interface. Par exemple je trouverai sympa d'avoir un truc du style:

    class GtkUiFwomaj(...):
        def __init__( ... ):
            ...
            self.mycheese = Fwomaj('my_video.avi')
            # puis tu initialises ton UI avec les fonctions & attributs de ton objet Fwomaj
            ...

    La classe Fwomaj te permettant de récupérer les infos via mediainfo, d'initialiser ton pipeline GStreamer, de faire ta waveline le tout sans être dépendant de GTK. Par exemple ça peut donner:

    # Par exemple pour charger un nouveau fichier
        ...
        def on_load_file(self, widget, filename):
            """ Load a file, either at startup or later. """
            delete self.mycheese                 # some cleanup
            self.mycheese = Fwomaj(filename)     # our new file
            ...

    A vérifier mais ce genre de truc te permet de virer le fichier png de ta waveline quand tu delete l'objet par exemple. Au niveau des UI faire le nettoyage c'est souvent le bordel, même si au départ je n'ai qu'une ligne, je fais une fonction ui_cleanup(…) en prévision du futur (NB: tu peux aussi t'en servir à l'init pour être sur d'avoir quelque chose de cohérent entre les états/variables/éléments de ton UI).

    Ou encore ta classe WForm avec cette tête:

    class WForm(object):
    
        @classmethod
        def execute(cls, cheese, wbox, style_provider, spinner, label):
            ## ici cheese est un objet Fwomaj
            ...
            label.set_text(' Generating WaveForm image for {}... '.format(cheese.name)
            unique_file = os.path.join(tempfile.gettempdir(), 'fwomaj-{}.png'.format(time.time()))
    
            # on fait la waveline
            cheese.do_waveline(unique_file)
    
            # la suite qui elle dépend des GObject
            ...

    C'est simple à comprendre, ça t'évite d'aller mettre en global ta commande, même si tu caches un peu la misère dans une classe =D.

    Bref mes 2 copecs si tu as envie d'y re-travailler dessus pour l'améliorer. =)

    • [^] # Re: Improvements ?

      Posté par (page perso) . Évalué à 1.

      Bref mes 2 copecs si tu as envie d'y re-travailler dessus pour l'améliorer. =)

      Bien vu, ce serait effectivement plus élégant comme ça. Mais là j'ai trop de prod en retard pour retourner dans le code, donc je tourne autour des bugs ;p

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.