Fedora-Fr - Communauté francophone Fedora - Linux

Planet de Fedora-Fr : la communauté francophone autour de la distribution Linux Fedora

A propos

Cette page est actualisée toutes les heures.

Cette page est une sélection de blogs autour de Fedora. Fedora-Fr.org décline toute responsabilité au sujet des propos tenus par les auteurs des blogs de ce planet. Leurs propos sont leur entière responsabilité.

Le contenu de ce planet appartient à leurs auteurs respectifs. Merci de consulter leur blogs pour obtenir les licences respectives.

Mot-clefs : ffmpeg

Catpure vidéo écran screencast sous Fedora avec ffmpeg

Patrice Ferlet

La capture vidéo d'écran est un sujet maintes fois soulevé sous Linux et il existe de jolis services fais pour ça. Mais quand ça ne marche pas on a du mal à trouver des solutions simples... Istanbul, gtk-recordMyDesktop, je les ai essayé... mais à chaque fois un souci apparait, soit avec le son, soit avec la vidéo. Alors pourquoi ne pas passer par la ligne de commande ? ffmpeg est juste parfait ! alors on se lance. Encore une fois, si je trouve pas ce qui me plait, je le code :)" class="smiley donc vous aurez un script en bas de billet qui fait tout ça.

En premier lieu, le but est d'avoir: une vidéo de bonne qualité, capture du son depuis un micro, et un contrôle possible de la zone à sauver. Bref, il nous faut chercher tout ça dans les documentations. Comme je suis gentil, je vous donne au fur et à mesure la méthode, et même un petit script qui va vous aider.

Permière tâche à effecturer: capturer l'écran. ffmpeg à un format d'entré nommé "x11grab". Ce format d'entrée permet d'utiliser un port X de capture. Dans la majeur partie des cas on utilise "0.0"

Il faut par contre définir une taille obligatoirement, mon écran est de résoltion 1366x768. On trouve facilement la configuration de cette manière:

xrandr
creen 0: minimum 320 x 200, current 1366 x 768, maximum 1600 x 1600
LVDS connected 1366x768+0+0 (normal left inverted right x axis y axis) 344mm x 193mm
   1366x768       60.0*+
   1360x768       60.0  
   1280x768       60.0  
   1280x720       60.0  
   1024x768       60.0  
   1024x600       60.0  
   800x600        60.0  
   800x480        60.0  
   640x480        60.0  
DFP1 disconnected (normal left inverted right x axis y axis)
CRT1 disconnected (normal left inverted right x axis y axis)

Il faut aussi spécifier la fréquence de frame par seconde, 15 est un minimum, mais 25 ou 30 images par seconde est plus fluide. Bref...

Donc, pour capturer l'écran:

ffmpeg -f x11grab -i 0.0 -s 1366x768 -r 25 -y /tmp/out.avi

Cela fonctionne bien, en pressant "q" dans la console on coupe la capture, voyez ensuite la vidéo:

ffplay /tmp/out.avi

Niveau qualité... moyen... on ajoute alors un débit de lecture pour s'assurer d'un bon rendu. Personnellement j'ai trouvé que 7000kb/s est pas mal du tout:

ffmpeg -f x11grab -i 0.0 -s 1366x768 -r 25 -b 7000k -y /tmp/out.avi

Voilà. Pour le moment on a bien une manière de capturer la vidéo. Reste à capturer du son. ffmpeg sait très bien capturer le son depuis votre interface alsa.

Tout le problème est de savoir quel est l'identifiant alsa à capturer... personnellement j'ai une webcam avec micro, une carte hdmi qui peut sortir du son et une interface interne pour sortir du son sur mes enceintes... bref, 3 cartes...

L'investigation est en fait très simple, Linux a cet avantage de tout faire dans des fichiers ou pseudo fichiers. Nos cartes sons sont en fait interrogeables depuis /proc/asound qui nous donne un paquet d'informations.

Regardons:

D'abords je cherche ma webcam... ne vous fiez pas au nom complètement batard que vous allez voir, c'est juste que cette webcam envoit un nom bien affreux. Dans les autres cas vous verrez certainement des choses plus lisibles.

cat /proc/asound/cards
 0 [U0x46d0x825    ]: USB-Audio - USB Device 0x46d:0x825
                      USB Device 0x46d:0x825 at usb-0000:00:1d.0-1.2, high speed
 1 [Intel          ]: HDA-Intel - HDA Intel
                      HDA Intel at 0xb4100000 irq 44
 2 [Generic        ]: HDA-Intel - HD-Audio Generic
                      HD-Audio Generic at 0xb4020000 irq 45

donc ici on voit mes 3 cartes, La Intel, la Generic et ma webcam avec ce fameux nom "U0x46d0x825". Ce qui nous intéresse ici c'est surtout l'index, le permier chiffre qui apparait sur la première colone. Ma webcam (ou du moins son interface de son) est "0". Cela va vouloir dire que nous utiliserons ce chiffre pour définir la carte à utiliser.

Attention, un carte peut avoir plusieurs interfaces de capture, par exemple une entrée "line in" et "mic"... il faut donc trouver quel est l'interface qui nous convient. Cela se passe dans un second fichier:

cat /proc/asound/devices 
  2:        : timer
  3:        : sequencer
  4: [ 1- 0]: digital audio playback
  5: [ 1- 0]: digital audio capture
  6: [ 1- 0]: hardware dependent
  7: [ 1]   : control
  8: [ 2- 3]: digital audio playback
  9: [ 2- 0]: hardware dependent
 10: [ 2]   : control
 11: [ 0- 0]: digital audio capture
 12: [ 0]   : control

Ce qui est intéressant ici, c'est la seconde colonne, elle spécifie l'index de la carte suivi de l'index d'interface. Dans notre cas, pour ma webcam, je cherche l'index 0, c'est à dire les ligne préfixées par 11 et 12. On voit que l'interface 0-0 est une entré de capture de son... parfait !

La notation alsa est simple: "hw:" suivit de l'index, une virgule, le numéro d'interface. Ma webcam est représentée par "hw:0,0"

ainsi, ffmpeg me permet d'enregistrer du son depuis mon micro de cette manière:

ffmpeg -f alsa -i hw:0,0 -y /tmp/out.ogg

Et de ce fait, /tmp/out.ogg est un fichier son qui a enregistré ma voix depuis ma webcam. Bon, et bien allons y maintenant, on va utiliser les deux flux (vidéo et audio) et on les envoit dans un fichier:

ffmpeg -f x11grab -i 0.0 -s 1366x768 -r 25 -b 7000k -f alsa -i hw:0,0 -y /tmp/out.avi

Evidamment, vous pouvez utiliser d'autres formats de sortie, comme le webm, libx264, ogv, etc...

C'est bien gentil mais chercher ma carte son, etc... pas cool hein ? et bien on va simplifier tout ça via du bash avec zenity... comme ça ce sera plus simple.

On va utiliser un petit programme que j'ai trouvé sur le net qui permet de faire une sélection sur X:

wget https://github.com/lolilolicon/ffcast/raw/master/xrectsel.c --no-check-certificate
$(grep -Eo "gcc(.*)" xrectsel.c)
su -c "install xrectsel /usr/local/bin/"

Cela a installé une commande nommé xrectsel sur votre système, dans /usr/local/bin

Reste à faire un script pour lire les coordonnées, choisir le périphérique de capture et enfin lancer la capture...

Plutôt que de chercher les infos dans /proc/asound/devices et cards, je vais utiliser une autre méthode, plus adapté au scripting, qui consiste à chercher les cartes et leur capacité dans /proc/asound/cardN où N est un numéro. En lisant les fichiers pcmNc/info, j'aurais toutes les informations nécessaires. Par exemple:

cat /proc/asound/card0/pcm0c/info
card: 0
device: 0
subdevice: 0
stream: CAPTURE
id: USB Audio
name: USB Audio
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 1

Voici le script, moins de 100 lignes:

#!/bin/bash
#author Patrice Ferlet - Metal3d@gmail.com - http://www.metal3d.org
#Licence: GPLv3
 
#get Desktop dir for user
DESKTOP=$HOME/Desktop
if [[ -f ~/.config/user-dirs.dirs ]]; then
    source ~/.config/user-dirs.dirs
    DESKTOP=$XDG_DESKTOP_DIR
fi
 
getCards(){
    ## this function seeks every sound card that can be use to capture sound (mic, line in...)
 
    #find cards directory
    i=0
    capdevices=""
    while [[ -d /proc/asound/card$i ]]
    do
        #find pcmNc
        capdevices=$capdevices" "$(find /proc/asound/card$i -name "pcm*c" -type d)
        i=$((i+1))
    done
 
    for cap in $capdevices
    do
        #get options... index, subdevice etc...
        card=$(awk '/^card: /{print $2}' $cap/info)
        dev=$(awk '/^device: /{print $2}' $cap/info)
        subdev=$(awk '/^subdevice: /{print $2}' $cap/info)
        name=$(awk -F":" '/^name: /{print $2}' $cap/info)
        name=$(echo $name | sed 's/ /\-/g')
        echo "hw:$card,$dev,$subdev" "$name"''    
        echo
    done
 
}
 
__ffcast(){
    #lauch ffmpeg with options
    winsize=$1
    off=$2
    asound=$3
    options=$4
    file=$(echo "$options" | awk '{print $NF}')
 
    #run ffpmeg and get pid
    ffmpeg -f x11grab -s $winsize -r 30 -i :0.0+$off  -f alsa -i $asound $options &
    pid=$!
    zenity --notification \
        --window-icon /usr/share/icons/gnome/scalable/actions/media-record-symbolic.svg \
        --text "to stop ffcast, press icon" 2>/dev/null
    kill $pid
    zenity --info --title "Screencast stopped" --text "$file has been saved" 
}
 
chooseFFopts(){
    #this function allows you to choose output formats; it returns options + filename
    file=$DESKTOP/"screencast-"$(date +"%Y.%m.%d-%H:%M")
    ogv="-b 9000k $file.ogv"
    webm="-b 9000k $file.webm"
    avi="-b 9000k $file.avi"
    response=$(zenity --list --column "Format" avi x264 ogv) || exit 1
    echo ${!response}
}
 
main(){
    #main function
 
    captures=$(getCards)
    interface=$(zenity --title "Choose a sound device to capture" \
            --list --column "Port" \
            --column "Interface name" $captures) || exit 1
 
    #run xrectset to get a X rect selection made with mouse
    coords=$(xrectsel | sed 's/\+/ /')
    win=$(echo $coords | awk '{print $1}')
    offset=$(echo $coords | awk '{print $2}' | sed 's/\+/,/')
 
    #get ffmpeg options
    opts=$(chooseFFopts)
 
    #prepare screencast
    zenity --question \
        --title "Capture will begin after you press OK" \
        --text "An icon will appear in notification, press it to stop screencast"\
        --ok-label "Start screencast"\
        --cancel-label "Cancel" || exit 1
 
    #run screencast
    __ffcast $win $offset $interface "$opts"
}
 
#run main function
main

Sauvez ce fichier dans /usr/local/bin/ffmpeg-screencast (en root) et rendez le exécutable

su -c "chmod +x /usr/local/bin/ffmpeg-screencast"

Créez vous un lanceur dans le bureau, c'est plus sympa je trouve...

Vous le lancez, on vous propose de capturer l'audio sur ce qu'on trouve, puis vous faites une boite de sélection... reste ensuite à lancer le screencast. Une icone ronde apparait dans barre de notification, si vous cliquez dessus alors la capture s'arrête. Dans votre bureau apparait alors la capture vidéo que vous vouliez.