PROJET AUTOBLOG


®om's blog

Site original : ®om's blog

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

screex264 : réencodez vos captures d'écran vidéos (screencasts) sous Ubuntu

vendredi 12 septembre 2008 à 10:11

Vous connaissez sans doute l’outil gtk-recordmydesktop, qui permet de faire une capture vidéo (un screencast) de votre écran.

Pour obtenir une bonne qualité, dans les options vidéos, il faut vérifier que “compression nulle” est bien sur l’option “Activé” (malheureusement, la compression à la volée utilisée provoque quand même une légère perte de qualité).

Mais une telle vidéo prend un peu de place. Je vous propose donc de la réencoder, dans le format x264 (issu du projet VideoLAN, ayant donné naissance à VLC), multiplexé dans le conteneur MKV.

Le fichier ainsi généré sera lisible par exemple avec VLC.

Disons-le tout de suite, le x264 est actuellement LE meilleur codec de compression vidéo, proposant un rapport qualité/taille impressionnant. Le mkv permet, par exemple, de contenir une piste vidéo, plusieurs pistes audio dans différentes langues, des sous-titres, des chapitres, des pièces jointes… Ici, ce qui nous intéresse, c’est qu’il est libre, et qu’à contenu égal, il prend moins de place que les autres conteneurs (l’overhead est quasi-nul).

Voici comment utiliser le script.

Pour encoder la vidéo mavideo.ogg en mavideo.mkv, avec un débit de 400Kbps :

screex264 mavideo.ogg mavideo.mkv 400

Pour encoder la vidéo mavideo.ogg en mavideo.mkv, avec un débit de 400Kbps avec une meilleure qualité (plus lent) :

screex264 mavideo.ogg mavideo.mkv 400 -hq

Pour encoder la vidéo mavideo.ogg en mavideo.mkv, avec un débit de 400Kbps avec une qualité maximale (très lent) :

screex264 mavideo.ogg mavideo.mkv 400 -vhq

Il est également possible d’utiliser n’importe quels paramètres de mencoder. Ainsi, pour encoder la vidéo mavideo.ogg en mavideo.mkv, avec un débit de 400Kbps, à partir de la 10e seconde et pour une durée de 20 secondes :

screex264 mavideo.ogg mavideo.mkv 400 -ss 10 -endpos 20

Ce script peut également permettre à réencoder les petites vidéos enregistrées grâce à un appareil photo, et diviser leur taille d’un facteur 15.

Passons donc aux choses sérieuses. Tout d’abord, ce script nécessite x264, mencoder et mkvtoolnix pour fonctionner.

#!/bin/sh
# screex264 : screencast encoding script
#
# 11th september 2008 - Romain Vimont (®om)
#
# v0.2 (26th june 2009)
#
# Converts input video (ignoring audio) to x264 video, muxed in mkv.
#
# Syntax:
#   screex264 input_file output_mkv bitrate [quality_preset]
#     [mencoder_options [...]]
#
# quality_preset must be one of :
#   -std : (default) standard quality (good quality, normal)
#   -hq  : high quality (very good quality, slow)
#   -vhq : very high quality (best quality, very slow)
#
# mencoder_options are appended to command line of mencoder call.
# For example :
#   -ss 10 -endpos 56 : trim the video from 10s to 66s.
#
# (of course, there are no options -std, -hq nor -vhq)
#

# Syntax error detected.
# Exits the program with return code 1.
syntax_error() {
   printf '%s%sn' "Syntaxe : $0 input_file output_mkv bitrate " 
     '[quality_preset] [mencoder_options [...]]' >&2
   exit 1
}

# Indicates whether the argument represents an integer.
# Returns the integer if the argument represents an integer, an empty string if
#   it doesn't.
#
# $1: value to test
is_integer() {
   local value="$1"
   printf %s "$1" | grep -o '^[[:digit:]]+$'
}

# Gets a unique id, based on the clock (seconds + nanoseconds).
# Returns a unique id.
uid() {
   date +'%s%N'
}

# Returns the command line arguments for the selected preset.
#
# $1: preset
# return: command line arguments
x264_preset() {
   local preset="$1"
   case "$preset" in
   '-std')
       printf '%s%s%s' "bitrate=$bitrate:frameref=8:mixed_refs:" 
         "bframes=3:b_adapt:b_pyramid:weight_b:partitions=all:8x8dct:" 
         "me=hex:subq=5:trellis=2:threads=auto" ;;
   '-hq')
       printf '%s%s%s' "bitrate=$bitrate:frameref=16:mixed_refs:" 
         "bframes=3:b_adapt:b_pyramid:weight_b:partitions=all:8x8dct:" 
         "me=umh:subq=6:trellis=2:threads=auto" ;;
   '-vhq')
       printf '%s%s%s' "bitrate=$bitrate:frameref=16:mixed_refs:" 
         "bframes=3:b_adapt:b_pyramid:weight_b:partitions=all:8x8dct:" 
         "me=esa:subq=7:trellis=2:threads=auto" ;;
   *)
       printf '%s%sn' 'Quality preset must be one of {-std,-hq,-vhq} : ' 
         "$preset" >&2
       exit 4
   esac
}

# error when less than 3 arguments
[ $# -ge 3 ] || syntax_error

# reads the arguments
in=$1; shift
out=$1; shift
bitrate=$1; shift

# input file must exist
if [ ! -f "$in" ]
then
   printf '%sn' "Input file doesn't exist : $in" >&2
   exit 2
fi

# bitrate value must be integer
if [ ! $(is_integer "$bitrate") ]
then
   printf '%sn' "Bitrate value must be integer : $bitrate" >&2
   exit 3
fi

# choose the quality preset
quality='-std'
if [ "$1" = '-std' -o "$1" = '-hq' -o "$1" = '-vhq' ]
then
   quality="$1"
   shift
fi

# gets the x264 options
opts=$(x264_preset $quality)

# gets a unique filename, in order to avoid collisions when encoding two video
# at the same time
uid=$(uid)
tmp_x264=$(printf '%s' "/tmp/$uid.avi")
tmp_log=$(printf '%s' "/tmp/$uid.log")

# encodes the first pass
mencoder "$in" -o /dev/null -passlogfile $tmp_log -ovc x264 -x264encopts 
 "$opts:pass=1" -nosound $@ &&

# encodes the second pass
mencoder "$in" -o $tmp_x264 -passlogfile $tmp_log -ovc x264 -x264encopts 
 "$opts:pass=2" -nosound $@ &&

# muxes the result in a mkv
mkvmerge -o "$out" -d 0 -A -S "$tmp_x264" --track-order 0:0

Vous pouvez maintenant faire chauffer le processeur !

Optimiser la taille des fichiers png

samedi 30 août 2008 à 11:02

L’outil optipng permet d’optimiser les fichiers png : les compresser davantage sans aucune perte de qualité.

Pour l’utiliser, c’est très simple :

optipng image.png

Très pratique pour les captures d’écran que l’on veut poster sur Internet.

Voici un exemple de résultat :

$ optipng screenshot.png
OptiPNG 0.5.5: Advanced PNG optimizer.
Copyright (C) 2001-2007 Cosmin Truta.

** Processing: screenshot.png
1196x688 8-bit RGB-alpha non-interlaced
The image is losslessly reduced to 8-bit RGB
Input IDAT size = 117762 bytes
Input file size = 118005 bytes
Trying...
  zc = 9  zm = 8  zs = 0  f = 0  IDAT size = 81686
  zc = 9  zm = 8  zs = 1  f = 0  IDAT too big
  zc = 1  zm = 8  zs = 2  f = 0  IDAT too big
  zc = 9  zm = 8  zs = 3  f = 0  IDAT too big
  zc = 9  zm = 8  zs = 0  f = 5  IDAT too big
  zc = 9  zm = 8  zs = 1  f = 5  IDAT too big
  zc = 1  zm = 8  zs = 2  f = 5  IDAT too big
  zc = 9  zm = 8  zs = 3  f = 5  IDAT too big

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0  IDAT size = 81686

Output IDAT size = 81686 bytes (36076 bytes decrease)
Output file size = 81761 bytes (36244 bytes = 30.71% decrease)

Un peu plus de 30% de gain, ça n’est pas négligeable.

Et pour en faire un script nautilus, mettez ce script dans ~/.gnome2/nautilus-scripts/optipng que vous rendez exécutable :

#!/bin/sh
# Optimizes PNG files.
#
# 30th august 2008 - Romain Vimont (®om)
#

# Use only n as field separator
IFS='
'

# Calls optipng with all args
optipng $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS

Combiné avec imagup, c’est très pratique pour poster des captures d’écran sur un forum.

imagup : uploader une image en 2 clics

vendredi 29 août 2008 à 14:27

J’ai écrit un petit script pour uploader en ligne de commande une image sur imagup, et récupérer le lien (pratique pour poster sur les forums).

Voici comment l’utiliser :

imagup monimage.jpg

Les extensions jpg, jpeg, png et gif sont autorisées.

Voici un exemple de résultat :

$ imagup rom-avatar.png
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                               Dload  Upload   Total   Spent    Left  Speed
100 28706    0 14129  100 14577   3638   3754  0:00:03  0:00:03 --:--:--  5059
rom-avatar.png : http://uploads.imagup.com/05/1220023287_rom-avatar.png

Il est possible d’uploader plusieurs images en une seule ligne :

imagup image1.png image2.jpg

Avec l’option -open, une fois l’image uploadée, elle est ouverte dans le navigateur par défaut.

(curl doit être installé.)

Voici le script :

#!/bin/sh
# IMAGUP script
#
# 29th august 2008 - Romain Vimont (®om)
#
# Uploads images to www.imagup.com, and returns the http:// link.
#
# Syntax:
#   imagup [-open] fichier1 [fichier2 [...]]
#
# If -open is specified, the link is opened in the default associated program
# (the default browser).
#

# Syntax error detected
# Exits the program with return code 1.
syntax_error() {
    printf '%sn' "Syntaxe : $0 [-open] fichier1 [fichier2 [...]]" >&2
    exit 1
}

# Bad extension detected. Prints messages on stderr.
#
# $1: bad extension
bad_extension() {
    local extension="$1"
    printf '%sn' "Extension not supported: $extension" >&2
    printf '%sn' "Must be one of {png, jpg, jpeg, gif}." >&2
}

# Returns the canonical name of the file, from its (full) path.
#
# $1: (full) path of the file
# return: canonical name of the file
#
# example: get_filename 'a/b.c/d.e.f.jpg' returns 'd.e.f.jpg'
get_filename() {
    local path="$1"
    printf %s "$path" | grep -o '[^/]+$'
}

# Returns the radical of a filename (its name without the extension), from its
# (full) path.
#
# $1: (full) path of the file
# return: radical of the file
#
# example: get_radical 'a/b.c/d.e.f.jpg' returns 'd.e.f'
get_radical() {
    local path="$1"
    local filename="$(get_filename "$path")"
    printf %s "$filename" | sed 's/.[^.]*$//'
}

# Returns the extension of a file, from its (full) path.
#
# $1: (full) path of the file
# return: extension of the file
#
# example: get_extension 'a/b.c/d.e.f.jpg' returns 'jpg'
get_extension() {
    local path="$1"
    local filename="$(get_filename "$path")"
    printf %s "$filename" | grep -o '[^.]+$'
}

# Converts a String to lower case.
#
# $1: input text
# return: lower cased text
#
# example: to_lower_case 'AbCdE' returns 'abcde'
to_lower_case() {
    local text="$1"
    printf %s "$text" | tr -s [A-Z] [a-z]
}

# error when no arguments
[ $# -ge 1 ] || syntax_error

if [ "$1" = '-open' ]
then
    # -open is enabled
    open=true
    shift
    # should remain other arguments
    [ $# -ge 1 ] || syntax_error
fi

# for each argument (a file to upload)
for path
do
    extension=$(get_extension "$path")
    ext=$(to_lower_case "$extension")
    # extention must be one of {png, jpg, jpeg, gif}
    if [ "$ext" = png -o "$ext" = jpg -o "$ext" = jpeg -o "$ext" = gif ]
    then
        filename=$(get_filename "$path")
        radical=$(get_radical "$path")
        # uploads and gets the url back
        url=$(curl www.imagup.com -F 
          "fichier=@$path;filename=$radical.$ext;type=image/$ext" |
        grep image-upload |
        grep -o "http://[[:alpha:]]+.imagup.com/[^"]+.(png|jpg|jpeg|gif)")
        if [ "$url" ]
        then
            # if it worked, prints the url
            printf '%sn' "$path : $url"
            # if -open is selected, open-it in the default application
            [ $open ] && xdg-open "$url"
        else
            # it didn't work
            printf '%sn' "Problem while uploading $path" >&2
        fi
    else
        # file extension is bad
        bad_extension "$extension"
    fi
done

Une fois installé, vous pouvez également l’utiliser comme script nautilus. Mettez le script suivant dans ~/.gnome2/nautilus-script/imagup-wrapper et rendez-le exécutable :

#!/bin/sh
# nautilus IMAGUP script wrapper
#
# 29th august 2008 - Romain Vimont (®om)
#
# Needs "imagup" core script to be installed.
#

# Use only \n as field separator
IFS='
'

# Calls imagup with all args
imagup -open $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS

Ensuite, dans nautilus, il est possible d’envoyer l’image en cliquant sur Script → imagup-wrapper. Les images ainsi envoyées s’ouvriront dans le navigateur par défaut.

Cependant, en écrivant ce script, je me suis aperçu de trois problèmes dans nautilus : un problème de proxy, un problème de vue liste et un problème avec le lancement de scripts à partir du bureau.

Les deux derniers problèmes sont contournés avec le script imagup-wrapper (le dernier script).

Si, au lieu d’appeler une fois imagup avec tous les arguments, on voulait l’appeler n fois avec un seul argument (utile lorsque le programme appelé ne boucle pas sur les arguments), on aurait pu utiliser :

printf %s "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" |
while read -r arg
do
    imagup -open "$arg"
done

ou encore :

IFS='
'
for arg in $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
do
    imagup -open "$arg"
done

J’en ai profité pour écrire une section les pièges à éviter sur la doc ubuntu-fr de nautilus-scripts.

rsync : ayez une vraie politique de backup !

jeudi 28 août 2008 à 21:07

Ça vous est déjà arrivé de perdre un disque dur ?

Eh bien moi non, pas encore (trop chanceux!). Et pour éviter que ça se produise, j’ai mis en place une petite politique de backup, très simple.

Alors évidemment, j’avais déjà fait des “backups” : quand un répertoire est important, je le copie autre part. Et quand il est modifié, je supprime l’ancien backup et je le recopie de nouveau (ou j’écrase l’ancien par le nouveau). Mais par exemple pour le répertoire de photos ou autre, quand ça prend plus de 5Gio, c’est beaucoup trop long.

Voici donc comment faire un backup “incrémental” : seuls les fichiers modifiés, ajoutés ou supprimés seront modifiés côté “backup”. Et en plus, ça marche aussi à distance (on peut backuper un répertoire dans un autre sur la même machine, mais également sur une machine différente, par ssh).

Voici par exemple le script que j’utilise pour faire un backup de mon portable dans un répertoire de mon fixe :

#!/bin/sh
cmd='rsync -rpltv --del'

backup_dir='rom-desktop:/media/gnu/backup/rom-laptop'
$cmd \
/home/rom/work \
/home/rom/java \
/home/rom/docs \
/home/rom/.thunderbird \
/home/rom/.mozilla \
/home/rom/sh \
$backup_dir

(.mozilla et .thunderbird, c’est la configuration de firefox et thunderbird, ainsi que tous les favoris, mails, comptes…)

Et du fixe vers le fixe (d’un disque dur vers un autre) :

#!/bin/sh
cmd='rsync -rpltv --del'

backup_dir='/media/gnu/backup/rom-desktop'
$cmd \
/media/tux/photos \
$backup_dir

Plus d’infos sur les paramètres de rsync :

$cmd c’est la commande rsync avec ses paramètres.

$backup_dir c’est la destination :

Ensuite, vous pouvez lancer le script de temps en temps, manuellement (ce que je fais) ou programmé (la nuit ?).

Recompresser ses photos en masse de manière incrémentale

mercredi 27 août 2008 à 18:45

Mon appareil photo possède 3 réglages de “qualité” (niveau de compression JPEG) :

Mais lorsque l’on choisit un réglage, les photos font à peu près toutes la même taille, qu’elles soient simples ou complexes. Par exemple, en réglage fin, leur taille est quasiment toujours comprise entre 2,8Mio et 2,9Mio.

Or, une photo uniforme devrait prendre beaucoup moins de place qu’une photo très complexe, avec beaucoup de contours.

D’ailleurs, on s’en rend compte lorsqu’on recompresse ces photos sur un ordinateur :

photos-tree

Sur cette capture d’écran, les photos contenues à la racine (les 5 dernières) sont les photos originales, prises par l’appareil photo.

Les photos contenues dans les répertoires convertXX sont les photos converties avec :

convert image.jpg -quality XX convertXX/image.jpg

(imagemagick doit être installé)

On se rend compte que les photos ont une taille beaucoup plus variable, ce qui est une bonne chose. Sur l’ensemble de mes albums, j’ai des photos à 500Kio et d’autres à 1,8Mio : c’est la qualité finale de la photo qui est prise en compte, et non la taille à atteindre.

J’ai donc décidé de prendre les photos en qualité maximale sur l’appareil photo, et de les recompresser à l’importation.

J’utilise digiKam pour gérer mes photos, qui possède une fonctionnalité pour recompresser les photos (utilisant exacement le même algorithme que imagemagick).

Le problème, c’est que je veux éviter, par inattention, de recompresser plusieurs fois les mêmes photos (perte de qualité inutile). Par exemple, lorsqu’on importe les photos d’une carte mémoire, qu’on les recompresse, puis qu’on importe les photos d’une seconde carte mémoire, difficile de différencier les photos déjà recompressées des autres (pour les photos se trouvant dans le même dossier).

J’ai donc écrit un petit script, qui garde dans un fichier la liste des photos déjà recompressées, et qui compresse toutes celles qui ne sont pas présentes dans le fichier.

Ainsi, après une importation de photos, j’exécute le script, seules les nouvelles seront recompressés.

#!/bin/sh
#
# Mogrifie tous les fichiers jpeg non encore mogrifiés (recompressés en jpeg)
#

# le fichier "mogrified" doit exister, si ce n'est pas le cas, faire
# touch mogrified" avant de lancer le script
if [ ! -f mogrified ]
then
    echo 'mogrified file not found.'
    exit 1
fi

# liste tous les fichiers .jpg dans les répertoires décrivant une année
# (2005, 2006...)
find -iname '*.jpg' | grep ^./20 | sort > filelist &&

# supprime de cette liste tous les fichiers déjà mogrifiés
comm -23 filelist mogrified |
while read photo
do
    # mogrifie ces fichiers
    echo "$photo"
    mogrify -quality 90 "$photo"
done

# les fichiers mogrifiés sont maintenant les fichiers de la liste complète
mv filelist mogrified

L’outil mogrify fait la même chose que convert, sauf qu’il modifie le fichier sur place (et écrase donc la source).

Cela permet d’avoir un très bon rapport qualité/taille, sans provoquer des pertes visibles sur les photos très complexes, ni utiliser de l’espace inutilement sur les photos simples.

Error happened! 0 - Call to undefined function simplexml_load_string() In: /var/www/Projet-Autoblog/autoblogs/autoblog.php:364 http://www.couturat.fr/Projet-Autoblog/autoblogs/blogrom1vcom_4af8d17d34d978843ff2ff40339aa5760e6458bc/?27 #0 /var/www/Projet-Autoblog/autoblogs/autoblog.php(932): VroumVroum_Blog->update() #1 /var/www/Projet-Autoblog/autoblogs/blogrom1vcom_4af8d17d34d978843ff2ff40339aa5760e6458bc/index.php(1): require_once('/var/www/Projet...') #2 {main}