Blogeek|Sioc

Geekeries de tout poil

Recaler le son d’un fichier vidéo

Quoi de plus énervant qu’un fichier vidéo dont le son n’est pas bien calé ? Ou bien calé au début, mais qui se décale en cours de route ?
Voici quelques commandes basées sur libav pour extraire la bande son, et la ré-intégrer dans la vidéo.

Pour les manips intermédiaires je recommande audacity qui permet de bidouiller la piste audio dans tous les sens. On est sur un blog de geek : je laisse tout un chacun le soin d’imaginer les techniques possibles, mais avec audacity on peut sans problème ajouter ou enlever un morceau au début de la piste (décalage simple), mais aussi rectifier un décalage qui apparait progressivement (effect > change tempo), voire de le faire sur une sélection pour les plus courageux qui veulent noter de nombreux points de contrôle dans leur vidéo 🙂

Allons-y ! Allons-y !

Demux :

D’abord vérifier le format de votre piste audio et son bitrate avec un petit :

avconv -i mon_film_telecharge_sur_bittorrent_en_toute_legalite.mp4
 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'mon_film_telecharge_sur_bittorrent_en_toute_legalite.mp4':
 Metadata:
 major_brand     : mp42
 minor_version   : 0
 compatible_brands: mp42isomavc1
 creation_time   : 2013-10-02 21:17:00
 Duration: 01:33:09.21, start: 0.000000, bitrate: 3154 kb/s
 Stream #0.0(und): Audio: aac, 44100 Hz, stereo, s16, 256 kb/s
 Stream #0.1(und): Video: h264 (High), yuv420p, 1280x720, 3603 kb/s, 23.98 fps, 23.98 tbr, 23976 tbn, 47.95 tbc

En fonction du format de l’audio, extraire avec une extension appropriée :

avconv -i mon_film_telecharge_sur_bittorrent_en_toute_legalite.mp4 -vn -acodec copy piste_audio.aac

Explication : -vn pour pas de vidéo, -acodec copy pour copier la piste audio sans modif

Audacity :

ouvrir le fichier de bande son, et faire les modifs appropriées… have fun… à la fin faire file > export et choisir un format sans perte (ex : wav)

Remux :

avconv -i mon_film_telecharge_sur_bittorrent_en_toute_legalite.mp4 -i piste_audio.wav -codec:v:0 copy -codec:a:1 aac -ab 256k -strict experimental -map 0:1 -map 1:0 mon_beau_film_bien_synchronise.mp4

Explication : ajout des deux fichiers à multiplexer (fichier d’origine et .wav qu’on vient de créer), -codec:v:0 copy pour copier le flux video du fichier n°0 directement, -codec:a:1 aac pour encoder en aac le fichier n°1, -ab 256k pour retomber sur le bitrate d’origine, -strict experimental pour permettre dans CE cas l’utilisation de aac, et enfin les -map 0:1 et -map 1:0 qui specifient que le fichier de sortie est composé de la piste n°1 du fichier n°0 (video, cf log de avconv -i plus haut) et de la piste n°0 du fichier n°1 (notre wav)

Et voila 🙂

 


Ce que j’aime avec l’open source…

Ce matin, je regarde mon outil d’intégration continue favori, Jenkins, qui a subi une mise à jour toute récente… et là que vois-je ??

Ce qui m’a attiré l’œil, c’est la petite image de processeur en bas à gauche. D’habitude à cet endroit, y’a la bonne bouille du père Jenkins :

Alors, pourquoi ce processeur ?? Pour essayer d’en savoir plus, je file sur le changelog de Jenkins, peut-être qu’il y aura une info à ce sujet ? Et effectivemment, je peux y lire ceci :

Autrement dit (seul le passage surligné en magnifique rose nous intéresse, le reste n’est que diatribe technique sans poésie…) : « pour fêter la sortie de la version ‘486’, l’image de fond sera un processeur 80486 pour la semaine ». Woh !! Fallait pas le louper celui-là 😉 .

Et en effet, vous pouvez admirer pour quelques jours encore sur vos installations de Jenkins, si elles sont bien à jour, un magnifique processeur sur lequel on peut lire le fameux ‘486’… Pour rappel ce processeur est en quelques sorte l’ancêtre de tout ce qui se fait aujourd’hui en matière d’ordinateur personnel 😉 . On remarque au passage que l’image de Jenkins a été récupérée chez notre ami Wikipedia ! Longue vie au processeur ‘486’ (ou plutôt à sa descendance…) et longue vie à Jenkins.


Retrouver le type des variables génériques en Java

Voici une classe qui permet de retrouver les types utilisées pour les variables génériques sur une instance d’une interface.
Plus précisément, l’utilisation est la suivante : tout d’abord on a défini une interface appelée I, qui utilise une ou plusieurs variables génériques. Par exemple :

public interface I {}

Ensuite, on crée des instances qui implémentent cette interface, soit en créant une classe explicite, soit à la volée avec une classe anonyme :

public class B {}
public class C {}
public class A implements I<b> {}
I&lt;?&gt; a = new A();
I&lt;?&gt; b = new I {};</b>

Le but est de pouvoir retrouver, à partir de la classe A ou d’une instance comme a ou b, la valeur de la variable T définie dans I et spécifiée dans les écritures suivantes, soit la classe B pour A et a, et la classe C pour l’instance b.
Voici comment on procède :

Class&lt;?&gt; c1 = GenericsHelper.getInterfaceGenericType(A.class, I.class); // vaut B.class
Class&lt;?&gt; c2 = GenericsHelper.getInterfaceGenericType(a, I.class); // vaut B.class
Class&lt;?&gt; c3 = GenericsHelper.getInterfaceGenericType(b, I.class); // vaut C.class

Il est possible aussi de résoudre des variables sur des interfaces possédant plusieurs variables génériques, en spécifiant l’index de celle-ci (ordre de déclaration), exemple :

interface I&lt;T,U&gt; {}
public class B {}
public class C {}
public class A implements I&lt;B,C&gt; {}
Class&lt;?&gt; c1 = GenericsHelper.getInterfaceGenericType(A.class, I.class, 0); // vaut B.class
Class&lt;?&gt; c2 = GenericsHelper.getInterfaceGenericType(A.class, I.class, 1); // vaut C.class
Class&lt;?&gt; c3 = GenericsHelper.getInterfaceGenericType(A.class, I.class); // vaut B.class, n°0 par défaut

Sans plus attendre, voici le code source de la classe :

import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Stack;
 
/**
 * Classe helper pour déterminer les types concrets des variables génériques définies dans des interfaces.
 * @author fguerry
 */
public class GenericsHelper {
 
    // constructeur privé = class util
    private GenericsHelper() {
    }
 
    /**
     *

Détermine le type concret d’une variable générique, sur une instance * donnée, la variable étant la première définie dans l’interface donnée

     *

Exemple : soit interface I<T,U> et I<?,?> a = new I<B,C>{};
* Alors : getInterfaceGenericType(a, I.class) vaut B.class
*

     * @param instance
     * @param interf
     * @return 
     */
    public static Class&lt;?&gt; getInterfaceGenericType(Object instance, Class&lt;?&gt; interf) {
        return getInterfaceGenericType(instance.getClass(), interf, 0);
    }
 
    /**
     *

Détermine le type concret d’une variable générique, sur une instance * donnée, la variable étant initialement définie dans l’interface donnée, à la position donnée.

     *

Exemple : soit interface I<T,U> et I<?,?> a = new I<B,C>{};
* Alors : getInterfaceGenericType(a, I.class, 0) vaut B.class
* et getInterfaceGenericType(a, I.class, 1) vaut C.class *

     * @param instance
     * @param interf
     * @param typeNumber
     * @return 
     */
    public static Class&lt;?&gt; getInterfaceGenericType(Object instance, Class&lt;?&gt; interf, int typeNumber) {
        return getInterfaceGenericType(instance.getClass(), interf, typeNumber);
    }
 
    /**
     *

Détermine le type concret d’une variable générique, au sein d’une classe d’implementation * donnée, la variable étant la première définie dans l’interface donnée

     *

Exemple : soit interface I<T,U> et class A implements I<B,C>
* Alors : getInterfaceGenericType(A.class, I.class) vaut B.class
*

     * @param implementor
     * @param interf
     * @return 
     */
    public static Class&lt;?&gt; getInterfaceGenericType(Class&lt;?&gt; implementor, Class&lt;?&gt; interf) {
        return getInterfaceGenericType(implementor, interf, 0);
    }
 
    /**
     *

Détermine le type concret d’une variable générique, au sein d’une classe d’implementation * donnée, la variable étant initialement définie dans l’interface donnée, à la position donnée.

     *

Exemple : soit interface I<T,U> et class A implements I<B,C>
* Alors : getInterfaceGenericType(A.class, I.class, 0) vaut B.class
* et getInterfaceGenericType(A.class, I.class, 1) vaut C.class *

     * @param implementor
     * @param interf
     * @param typeNumber
     * @return 
     */
    public static Class&lt;?&gt; getInterfaceGenericType(final Class&lt;?&gt; implementor, Class&lt;?&gt; interf, int typeNumber) {
        if (implementor == null) {
            throw new NullPointerException("The given implementor class must not be null.");
        }
        if (interf == null) {
            throw new NullPointerException("The given generic interface must not be null.");
        }
        if (typeNumber &lt; 0) {
            throw new IllegalArgumentException("The given typeNumber must not be negative.");
        }
        if (implementor.isInterface()) {
            throw new IllegalArgumentException("The given implementor class " + implementor.getCanonicalName() + " is actually an interface !");
        }
        if (Modifier.isAbstract(implementor.getModifiers())) {
            throw new IllegalArgumentException("The given implementor class " + implementor.getCanonicalName() + " is actually abstract and cannot be looked for implemented interface generic types !");
        }
        if (!interf.isInterface()) {
            throw new IllegalArgumentException("The given interface " + interf.getCanonicalName() + " is actually NOT an interface !");
        }
        Stack&lt;Class&lt;?&gt;&gt; parentStack = new Stack&lt;Class&lt;?&gt;&gt;();
        TypeVariable&lt;?&gt; backSearch = null;
        Class&lt;?&gt; currentClass = implementor;
        implWhile:
        while (currentClass != null) {
            // première passe : on cherche si l'interface est effectivement implémentée dans la classe, et si la variable est spécifiée
            // directement dans la déclaration implements d'une des classes de la hiérarchie
            final Type[] interfaces = currentClass.getGenericInterfaces();
            for (int index = 0; index &lt; interfaces.length; index++) {
                ParameterizedType param = (ParameterizedType) interfaces[index];
                if (param.getRawType().equals(interf)) {
                    final Type[] actualTypeArguments = param.getActualTypeArguments();
                    if (typeNumber &gt;= actualTypeArguments.length) {
                        throw new IllegalArgumentException("The given interface " + interf.getCanonicalName() + " doesn't have a n°" + typeNumber + " parameterizd type, but has only " + actualTypeArguments.length + " of them");
                    }
                    final Type name = actualTypeArguments[typeNumber];
                    if (name instanceof Class) {
                        // la variable est définie à ce niveau directement, ça veut dire que la clause implements a spécifié des types concrets
                        return (Class) name;
                    } else if (name instanceof TypeVariable) {
                        // sinon, la variable a été transmise à la déclaration de la classe, on passe donc à la phase 2
                        backSearch = (TypeVariable) name;
                        break implWhile;
                    }
                }
            }
            parentStack.push(currentClass);
            currentClass = currentClass.getSuperclass();
        }
        while (backSearch != null) {
            // phase 2 : on redescend la hierarchie grâce à la stack afin de déterminer sur quelle classe la viariable est définie
            final int index = indexOfTypeVariable(currentClass, backSearch);
            if (parentStack.isEmpty()) {
                // si à un moment donné on ne peut plus descendre et que la variable n'est toujours pas définie, cela
                // signifie qu'elle est définie nulle part... on ne peut donc pas donner de résultat !
                throw new IllegalArgumentException("The generic parameter n°" + typeNumber + " of interface " + interf.getCanonicalName() + " is not bound anywhere into class " + implementor.getCanonicalName() + ". You should create a fully typed subclass of this class to be able to use this function !!");
            }
            currentClass = parentStack.pop();
            ParameterizedType superclassbound = (ParameterizedType) currentClass.getGenericSuperclass();
            final Type name = superclassbound.getActualTypeArguments()[index];
            if (name instanceof Class) {
                // si la variable est définie à ce niveau, on s'arrête
                return (Class) name;
            } else if (name instanceof TypeVariable) {
                // sinon on continue de descendre
                backSearch = (TypeVariable) name;
            }
        }
        throw new IllegalArgumentException("The given class " + implementor.getCanonicalName() + " doesn't implements the given interface " + interf.getCanonicalName());
    }
 
    /**
     * Retrouve l'index d'une variable générique donnée dans la déclaration d'une classe donnée.
     * @param implementor
     * @param var
     * @return 
     */
    public static int indexOfTypeVariable(Class&lt;?&gt; implementor, TypeVariable&lt;?&gt; var) {
        final TypeVariable&lt;?&gt;[] parameters = implementor.getTypeParameters();
        for (int index = 0; index &lt; parameters.length; index++) {
            if (parameters[index].equals(var)) {
                return index;
            }
        }
        return -1;
    }
}

Récupérer un extrait musical Youtube

Attention, c’est du dense et orienté Ubuntu :
si besoin, installer youtube-dl
sudo apt-get install youtube-dl
youtube-dl http://www.youtube.com/watch?v=nX1YzS_CYIw

si besoin installer avconv (remplaçant de ffmpeg)
sudo apt-get install libav-tools
avconv -i nX1YzS_CYIw.flv -vn -acodec copy nX1YzS_CYIw.aac

si le flux audio n’est pas en aac, adapter l’extension du fichier de sortie… (cf le log de avconv)
si besoin installer audacity
sudo apt-get install audacity
utiliser audacity pour récupérer l’extrait souhaité 🙂


Modifier un nom de partition FAT32 avec Linux et mtools

[en attente de traduction, repompe pure et simple de http://embraceubuntu.com/2006/03/01/editing-fat32-partition-labels-using-mtools/ ]

I wanted to rename the fat32 partitions that get automounted when they are plugged in to the USB drive. Two were exactly similar external hard disk drives, and one was an iPod. The exactly similar hard disk drives (one each at home and work) were both getting mounted at /media/sda1 or sda2 etc, and it was impossible to distinguish one from the other easily. Also, I found that it wasn’t that easy to edit the partition labels for FAT32 partitions. So I thought I would summarize how I named my fat32 partitions to have consistent names. This has the benefit that when these drives are automounted, they will be at the location /media/partition-label, where partition-label is the label that you give the partition.

Step by step instructions to re-label FAT partitions follow:

1) Install mtools:

$sudo apt-get install mtools

2) After the usb drive is automounted after plugging in, find out the device descriptor using:

$mount

and Note down where it says “sda1″ or similar

3) copy the mtools.conf to ~/.mtoolsrc

$cp /etc/mtools.conf ~/.mtoolsrc

4) Edit ~/.mtoolsrc to add one line at the very end:

drive i: file="/dev/sda2"

–you may have to change sda2 to something else depending on what you got in step 2 above.

5) Change to the “drive” i:

$mcd i:

6) Check what the label for the drive is currently:

$sudo mlabel -s i:

7) Change the label to something pretty:

$sudo mlabel i:my-ipod

8 ) Check if the label has changed:

$sudo mlabel -s i:

I got the following output –

Volume label is MY-IPOD

You’re all set!! The next time that partition gets automounted, it will be at /media/MY-IPOD


Ajouter un certificat CA à une JVM (Java)

D’abord se rendre dans le répertoire jre/lib/security de la JVM

Puis avec keytool :

keytool -import -file <file.crt> -alias <alias> -keystore cacerts

Le mot de passe du keystore nommé « cacerts » (dépôt par défaut des CA de la JVM) est :

changeit

L’alias sert à identifier le certificat de manière unique dans le fichier cacerts. Si vous ajoutez plusieurs certificats, il faut donc plusieurs alias.

Enjoy 😉


Recherche full text pour SVN

La fonction svn log est bien pratique, mais ne permet pas de choisir des critères bien définis… une chose qui manque notamment cruellement à ma connaissance, c’est la recherche par utilisateur… j’ai donc utilisé la ligne de commande suivante, qui n’est pas optimale à mon avis, mais qui a le mérite de marcher :

for rev in `svn log -r <xxx>:HEAD | grep <user> | 
cut -d " " -f 1 | cut -d "r" -f 2`; do svn log -r $rev; done;

Remarquez que le <user> peut être remplacé par n’importe quelle chaîne à chercher dans le log, y compris dans les commentaires…


Variables spéciales en shell Bash

Manipulation de variables simples

var=val ou var="a b" affectation de la variable « var »
$var ou ${var}   contenu de la variable « var »
${#var}   longueur de la variable « var »
export var ou declare -x var   exportation de la variable « var » vers les shells fils
set   affichage de l’ensemble des variables définies dans le shell
unset var   suppression de la variable « var »

Tableaux

tab[0]=val affectation du premier enregistrement du tableau « tab »
${tab[0]} ou $tab   contenu du premier enregistrement du tableau « tab »
${tab[11]}   contenu du douzième enregistrement du tableau « tab »
${tab[*]}   ensemble des enregistrements du tableau « tab »
${#tab[11]}   longueur du douzième enregistrement du tableau « tab »
${#tab[*]}   nombre d’enregistrements du tableau « tab »

Paramètres positionnels et arguments

$0 nom du script tel que saisi sur la ligne de commande
$(basename $0) nom du script sans répertoire
$(dirname $0) répertoire du script
$1 $2 ... ${10}   paramètres positionnels (1, 2 et 10)
$#   nombre de paramètres positionnels
$* ou $@   ensemble des paramètres positionnels, équivalant à $1 $2 ... ${n}
"$*"   ensemble des paramètres positionnels, équivalant à "$1 $2 ... ${n}"
"$@" ensemble des paramètres positionnels, équivalant à "$1" "$2" ... "${n}"
La commande shift permet de décaler les paramètres, on peut préciser shift <n> pour décaler de plusieurs rangs.

Variables spéciales

$$ PID du shell courant
$!   PID du dernier travail lancé en arrière plan
$?   code retour de la dernière commande

Variables d’environnement

$HOME chemin du répertoire personnel de l’utilisateur
$OLDPWD   chemin du répertoire précédent
$PATH   liste des chemins de recherche des commandes exécutables
$PPID   PID du processus père du shell
$PS1   invite principale du shell
$PS2   invite secondaire du shell
$PS3   invite de la structure shell « select »
$PS4   invite de l’option shell de débogage « xtrace »
$PWD   chemin du répertoire courant
$RANDOM   nombre entier aléatoire compris entre 0 et 32767
$REPLY   variable par défaut de la commande « read » et de la structure shell « select »
$SECONDS   nombre de secondes écoulées depuis le lancement du shell

Source : http://www.epons.org/shell-bash-variables.php