[FFMPEG] ScreenCast/ScreenRecorder comme OBS (Tuto)

Applications multimedia / jeux
Avatar de l’utilisateur
Joan31
Chu Ko Nu
Messages : 355
Inscription : mer. 27 mai 2015, 09:37

[FFMPEG] ScreenCast/ScreenRecorder comme OBS (Tuto)

Message par Joan31 »

Bonjour,

Je partage une astuce, si vous souhaitez passer par la ligne de commande et avoir un résultat similaire à OBS (c'est à dire partager écran, webcam en overlay et le son).

La commande :

Code : Tout sélectionner

ffmpeg -y -f x11grab -s 1920x1080 -r 60 -i :0.0+1920,0 -f v4l2 -i /dev/video0 -f alsa -i pulse -filter_complex '[1:v]scale=240:-1, fps, setpts=PTS-STARTPTS [webcam]; [0:v][webcam]overlay=W-w-12:H-h-12' -vcodec libx264 -crf 20 -preset ultrafast -minrate 150k -maxrate 500k -s 1920x1080 -acodec aac -ar 44100 -ab 96000 -threads 0 -f mp4 record.mp4
Pour une meilleur visibilité, dans un script record.sh :

Code : Tout sélectionner

ffmpeg -y -f x11grab -s 1920x1080 -r 60 -i :0.0+1920,0 \
-f v4l2 -i /dev/video0 \
-f alsa -i pulse \
-filter_complex '[1:v]scale=240:-1, fps, setpts=PTS-STARTPTS [webcam]; [0:v][webcam]overlay=W-w-12:H-h-12' \
-vcodec libx264 -crf 20 -preset ultrafast -minrate 150k -maxrate 500k -s 1920x1080 \
-acodec aac -ar 44100 -ab 96000 \
-threads 0 -f mp4 record.mp4
Remarque : J'ai passé pas mal de temps à tester. J'avais un soucis de synchro entre le son micro et la vidéo webcam.
Tout simplement, il fallait juste placer l'input du son à la fin des deux inputs vidéos (3e ligne dans le fichier).

Pour avoir, à la fois le son système et micro, on peut créer un périphérique virtuel de cette façon (pulseaudio) :

Code : Tout sélectionner

pactl load-module module-null-sink sink_name=inputs
Ensuite les retours (appelés loopback) nécessaires. Dans notre mise en oeuvre nous en aurons besoin de deux, un pour le micro et un autre pour le système :

Code : Tout sélectionner

pactl load-module module-loopback sink=inputs
pactl load-module module-loopback sink=inputs
Puis à l'aide d'un mixer (pulsemixer, pavucontrol), on affecte les retours (loopbacks) sur chaque périphérique d'entrées qu'on souhaite avoir sur notre vidéo.
Donc, un sur l'input de l'entrée micro de la carte son, et l'autre sur l'input appelé "Monitor" (c'est le rebouclage de la sortie audio de la carte son).

Puis au lancement de ffmpeg lors de l'enregistrement, on l'affecte sur le périphérique virtuel input qu'on à créée en premier.

Si vous avez tout suivi ffmpeg devrait pouvoir recevoir les deux sons (micro et monitoring de la sortie audio).

Explication de la commande (vous pouvez adapter suivant le besoin):

ffmpeg -y -f x11grab -s 1920x1080 -r 60 -i :0.0+1920,0
Le -y c'est pour dire oui automatiquement lorsqu'il demande à écraser le fichier record.mp4 si celui-ci est présent.
Ensuite viennent les paramètres correspondants à l'input à enregistrer.
Donc le premier input correspond au serveur d'affichage X11 -f x11grab.
Le -s résolution, -r le framerate.
Le -i si vous avez un seul écran 0.0 suffis. Sinon si vous avez un deuxième écran (par exemple sur la droite) et que vous souhaitez enregistrer celui-ci il faut rajouter +1920,0.

-f v4l2 -i /dev/video0
Ici on choisi un deuxième input qui correspond à la webcam.

-f alsa -i pulse
Notre troisième input c'est l'audio, donc on passe par le driver ALSA et on récupère le "périphérique" pulse. Il faut le paquet pulseaudio-alsa installé.

-filter_complex '[1:v]scale=240:-1, fps, setpts=PTS-STARTPTS [webcam]; [0:v][webcam]overlay=W-w-12:H-h-12'
Ce paramètre de filtre, est celui qui va "composer" l'ensembe des entrées vidéos afin d'obtenir l'overlay souhaité.

[0:v] correspond au première paramètre d'input, c'est à dire l'écran = -f x11grab -s 1920x1080 -r 60 -i :0.0+1920,0
[1:v] correspond au deuxième paramètre d'input, c'est à dire la webcam = -f v4l2 -i /dev/video0

Sur la webcam [1:v], on va lui appliquer une résolution et mise à l’échelle de 240:-1 (à changer suivant vos besoins).

fps et setpts=PTS-STARTPTS sont des options pour que la vidéo webcam soit au bon timing par rapport à l'input vidéo de base (ici notre écran/bureau).
[webcam], c'est le nom (vous pouvez le changer), que l'on donne à l'ensemble des options affectés à la webcam [1:v].

Dernière partie de ce paramètre un peu complexe, c'est la composition de l'overlay.
On commence par déclarer la base est l'écran, le fond principal où va se reposer la webcam.
On débute donc par [0:v] suivi de [webcam] (si vous avez changé le nom précédemment, faut le modifier), on rajoute l'option overlay, et les coordonnées en pixel.
overlay=W-w-12:H-h-12 correspond à la vidéo webcam placé en bas à droite avec un espace par rapport au bord de l’écran (vertical et horizontal) de 12 pixels.

-vcodec libx264 -crf 20 -preset ultrafast -minrate 150k -maxrate 500k -s 1920x1080
Derniere partie, la sortie.

Ici on utilise l'encodage h264, avec un contrôle CRF de 20.
Un preset rapide "ultrafast". La compression sera moins importante, donc moins de charge CPU. Cependant, le fichier prendra plus de place.
On peut définir une fourchette de rate (ceci est optionnel). Et la résolution de sortie (je reste fidèle à la résolution HD de mon écran).

-acodec aac -ar 44100 -ab 96000
Encodage audio, en AAC avec un rate de 44,1kHz et bitrate de 96k.

-threads 0 -f mp4 record.mp4
Dernier point, le nombre de threads à 0, pour utiliser tout les cœurs du CPU.
-f mp4 pour choisir le format de sortie donc mp4.
Et finalement le fichier de sortie record.mp4.

Voilà, je tenez à partager tout ceci, ça pourra en aider certains.
S'il y a des choses qui peuvent être amélioré je suis preneurs :)
Arch Linux | Sway
AMD Ryzen 5800X @4.7Ghz | AMD Radeon RX 5700 XT
▹ 32Go DDR4 @3200Mhz | NVMe 1To

Joan31
lemust83
yeomen
Messages : 206
Inscription : ven. 11 déc. 2015, 21:20

Re: [FFMPEG] ScreenCast/ScreenRecorder comme OBS (Tuto)

Message par lemust83 »

bonjour
Pour être franc, je n'ai tout simplement pas testé ta procédure, mais j'avais déjà évoqué ici la possibilité de faire une capture vidéo de l'écran avec cet alias qui m'est propre évidement:

Code : Tout sélectionner

alias moteur='ffmpeg -f alsa -ac 2 -i pulse -f x11grab -s 1920x1080 -i :0.0 -acodec flac -vcodec libx264 -preset veryfast CapVideo.mkv'
Vu le peu de retour, je me suis dis que ça n’intéressait que peu de gens .
J'apprécie beaucoup que tu aies partagé ton expérience et surtout pris le temps de détailler ta procédure :)
Tour: Arch (Xfce) 64 Testing: 6-Core: AMD Ryzen 5 2600X type: MT MCP speed: 2152 MHz min/max: 2200/3600 MH
UEFI: American Megatrends v: 3803 date: 01/22/2018
Graphics:
Device-1: AMD Baffin [Radeon RX 460/560D / Pro
450/455/460/555/555X/560/560X]
driver: amdgpu v: kernel
Display: server: X.Org 1.20.8 driver: amdgpu,ati unloaded: modesetting
resolution: 1920x1080~60Hz
OpenGL: renderer: Radeon RX 560 Series
Manjaro en Dual (grub).
Avatar de l’utilisateur
Joan31
Chu Ko Nu
Messages : 355
Inscription : mer. 27 mai 2015, 09:37

Re: [FFMPEG] ScreenCast/ScreenRecorder comme OBS (Tuto)

Message par Joan31 »

Merci pour ton retour. Et avec plaisir, je crois que c'est intéressant de partager ce que l'on apprend et ça permet de s'enrichir mutuellement ;)

Je pense que cela peut intéresser pas mal de monde, vu le nombre de fois que le sujet est abordé sur le net en general.
J'ai cherché et testé un moment avant de trouver la bonne commande avec les bons paramètres. Surtout que je suis resté pas mal de temps sur le problème de désynchronisation du son micro et la webcam. Il y avait un légé retard de quelque milliseconde et cela m'agaçait. Et tout simplement il fallait passer les paramètres audio, après les paramètres vidéo....

Dans ta solution, on enregistre uniquement l’écran. Sur ce que j'ai posté, on a en plus la webcam en overlay. Ce qui se rapproche beaucoup de la solution OBS Studio, mais en plus light.
OBS est excellent cela dit en passant, mais je voulais une solution entièrement en ligne de commande pour les environnements minimalistes et puis parce que c'est fun d'essayer de réduire la consommation des ressources système :D

Evidemment je pense que cela est perfectible. L'usage d'un alias est une bonne idée, mais je préfère qu'il pointe sur le script (ça fais plus propre à mon sens, et meilleur visibilité de l'ensemble des commandes).
D'ailleurs, tu utilise un paramètre audio en plus -ac 2, ce qui permet d'avoir un son stéréo.

Je vais donc le rajouter. Cela devrait donner ça pour un seul écran :

Code : Tout sélectionner

ffmpeg -y -f x11grab -s 1920x1080 -r 60 -i :0.0 \
-f v4l2 -i /dev/video0 \
-f alsa -ac 2 -i pulse \
-filter_complex '[1:v]scale=240:-1, fps, setpts=PTS-STARTPTS [webcam]; [0:v][webcam]overlay=W-w-12:H-h-12' \
-vcodec libx264 -crf 20 -preset ultrafast -minrate 150k -maxrate 500k -s 1920x1080 \
-acodec aac -ar 44100 -ab 96000 \
-threads 0 -f mp4 record.mp4
Pour deux écrans (écran principal à droite du secondaire) :

Code : Tout sélectionner

ffmpeg -y -f x11grab -s 1920x1080 -r 60 -i :0.0+1920,0 \
-f v4l2 -i /dev/video0 \
-f alsa -ac 2 -i pulse \
-filter_complex '[1:v]scale=240:-1, fps, setpts=PTS-STARTPTS [webcam]; [0:v][webcam]overlay=W-w-12:H-h-12' \
-vcodec libx264 -crf 20 -preset ultrafast -minrate 150k -maxrate 500k -s 1920x1080 \
-acodec aac -ar 44100 -ab 96000 \
-threads 0 -f mp4 record.mp4
Arch Linux | Sway
AMD Ryzen 5800X @4.7Ghz | AMD Radeon RX 5700 XT
▹ 32Go DDR4 @3200Mhz | NVMe 1To

Joan31
Avatar de l’utilisateur
Joan31
Chu Ko Nu
Messages : 355
Inscription : mer. 27 mai 2015, 09:37

Re: [FFMPEG] ScreenCast/ScreenRecorder comme OBS (Tuto)

Message par Joan31 »

Une différente approche avec la solution ci-dessous, on a la visu direct de la webcam sur l'écran.
L'inconvénient c'est que "l'overlay" dans cette solution, peut gêner.

Code : Tout sélectionner

#!/bin/bash

location_dir=$HOME/Desktop

T="$(date +%d-%m-%Y-%H-%M-%S)".mkv

video_window_title="$T"

ffplay -window_title "$video_window_title" /dev/video0 &

ffmpeg -y -f alsa -i pulse \
-f x11grab -s 1920x1080 -i :0.0+1920,0 \
$HOME/$T
Ou si on ne veut pas utiliser ffplay pour l'overlay, on peut utiliser mpv à la place :

Code : Tout sélectionner

mpv av://v4l2:/dev/video0 --profile=low-latency --untimed
Arch Linux | Sway
AMD Ryzen 5800X @4.7Ghz | AMD Radeon RX 5700 XT
▹ 32Go DDR4 @3200Mhz | NVMe 1To

Joan31
Répondre