Numériser une K7 VHS sous Linux
Vous avez encore des VHS familiales ou de vos concerts de lycée au fond des placards ? Ne tardez pas à les numériser car le temps dégrade petit à petit ces supports analogiques et le matériel de lecture en état est de plus en plus rare à trouver.
J'ai longtemps utilisé une carte USB Pinnacle Dazzle dont les drivers fermés étaient restés en 32 bits, compatible WinXP uniquement, pas de Linux, pas de MacOS. Mes besoins de numérisation n'étant que très ponctuels, je n'ai pas gardé de machine dédiée mais je suis passé par la virtualisation et l'USB passthrough. Pas toujours pratique ni stable mais ça fonctionnait.
À la lecture de certains articles, je me suis rendu-compte que pour quelques dizaines d'euros, une clé USB de numérisation compatible Linux existait et pourrait moderniser et simplifier mon setup. Voici donc une synthèse de ma procédure de numérisation de VHS, en 2026.
Matériel utilisé
- 1 Magnétoscope BLUEsky TR-640 de la fin des 90's, toujours fonctionnel
- 1 câble péritel vers RCA (jaune, blanc, rouge)
- 1 Raspberry Pi 5 sous Raspberry Pi OS (basé sur Debian 13.6)
- 1 PC x86_64 un peu plus costaud, sous AlmaLinux 10
- 1 clé de capture audio/vidéo analogique August VGB100
Installation des dépendances nécessaires
Sous Debian 13 / Raspberry Pi OS
1apt install usbutils v4l-utils alsa-utils ffmpeg
Sous Almalinux 10, il faut passer par le kernel elrepo car la partie audio de la clé de capture n'est pas reconnue.
Ensuite, il faut ajouter le user aux groupes audio et video pour qu'il puisse accéder au périphérique.
1rpm --import https://www.elrepo.org/RPM-GPG-KEY-v2-elrepo.org
2dnf install https://www.elrepo.org/elrepo-release-10.el10.elrepo.noarch.rpm
3dnf --enablerepo=elrepo-kernel install kernel-ml # puis rebooter
4dnf install epel-release usbutils ffmpeg-free
5usermod -aG audio,video gus # puis se délogger/relogger
Mais avec ffmpeg-free, le codec x264 n'est pas intégré, je suis finalement passé par une compilation maison de ffmpeg avec le support de libx264 et d'alsa.
Vérifier si la clé USB est bien reconnue
1gus@rpi5:~ $ lsusb
2Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
3Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
4Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
5Bus 003 Device 002: ID 1f4d:0102 G-Tek Electronics Group Video Capture
6Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
G-Tek Electronics Group Video Capture correpond bien à la clé de capture. À savoir que le nom technique n'est pas toujours le même que le nom commercial.
Lister les périphériques de capture vidéo
1gus@rpi5:~ $ v4l2-ctl --list-devices
2(...)
3Geniatech OTG102 (usb-xhci-hcd.1-1):
4 /dev/video0
5 /dev/vbi0
6 /dev/media3
L'identifiant du périphérique de capture vidéo à utiliser est /dev/video0.
Lister les périphériques de capture audio
1gus@rpi5:~ $ arecord -L
2(...)
3hw:CARD=Cx231xxAudio,DEV=0
4 Cx231xx Audio, Conexant cx231xx Capture
5 Direct hardware device without any conversions
6plughw:CARD=Cx231xxAudio,DEV=0
7 Cx231xx Audio, Conexant cx231xx Capture
8 Hardware device with all software conversions
9sysdefault:CARD=Cx231xxAudio
10 Cx231xx Audio, Conexant cx231xx Capture
11 Default Audio Device
12dsnoop:CARD=Cx231xxAudio,DEV=0
13 Cx231xx Audio, Conexant cx231xx Capture
14 Direct sample snooping device
1gus@rpi5:~ $ arecord -l
2**** List of CAPTURE Hardware Devices ****
3card 2: Cx231xxAudio [Cx231xx Audio], device 0: Cx231xx Audio [Conexant cx231xx Capture]
4 Subdevices: 1/1
5 Subdevice #0: subdevice #0
On va utiliser le périphérique card 2, qu'on peut appeler par son index 2 ou par son nom Cx321xxAudio.
Lecture audio+vidéo
Note: ffplay nécessite une interface graphique. Dans l'absolu on peut faire toute la procédure en ligne de commande mais le fait d'avoir un retour visuel local permet plus simplement d'affiner en temps réel les réglages fins (voir paragraphe suivant).
Note: ffmpeg doit être compilé avec le support alsa (flag --enable-indev=alsa)
1ffmpeg -re -i /dev/video0 -f alsa -i hw:2 -c copy -f nut pipe: | ffplay -f nut pipe: -vf yadif=1:0
Note: nut est un format de containeur à faible surcharge intéressant à utiliser quand on chaine ffmpeg à ffplay.
Si les couleurs sont codées SECAM, ajouter -standard SECAM car par défaut elles seront interprétées en PAL.
Note: on utilise le filtre tee pour à la fois afficher sur l'écran et écrire sur le disque.
1ffmpeg -re \
2 -f v4l2 -standard SECAM -i /dev/video0 \
3 -f alsa -i hw:CARD=Cx231xxAudio \
4 -vf yadif=1:0 -c:v libx264 -b:v 5000k -r 50 -aspect 4:3 -pix_fmt yuv420p \
5 -c:a aac -b:a 192k \
6 -map 0 -map 1 \
7 -f tee "[f=mpegts]num-$(date +"%s").ts|[f=nut]pipe:" | ffplay -f nut pipe:
Le fichier de sortie aura une résolution de 720x576 ce qui correspond à la résolution communément admise pour numériser une VHS PAL/SECAM Le flux en entrée sera entrelacé, on peut choisir de le désentrelacer ou pas (mais ça sera au lecteur vidéo d'alors le désentrelacer).
Réglages fins de l'image:
Pour voir les paramètres actuels :
1gus@rpi5:~ $ v4l2-ctl --list-ctrls-menus
2
3User Controls
4
5 brightness 0x00980900 (int) : min=0 max=255 step=1 default=128 value=128 flags=slider
6 contrast 0x00980901 (int) : min=0 max=127 step=1 default=64 value=64 flags=slider
7 saturation 0x00980902 (int) : min=0 max=127 step=1 default=64 value=64 flags=slider
8 hue 0x00980903 (int) : min=-128 max=127 step=1 default=0 value=0 flags=slider
9 volume 0x00980905 (int) : min=0 max=65535 step=655 default=60928 value=60928 flags=slider
10 balance 0x00980906 (int) : min=0 max=65535 step=655 default=32768 value=32768 flags=slider
11 bass 0x00980907 (int) : min=0 max=65535 step=655 default=32768 value=32768 flags=slider
12 treble 0x00980908 (int) : min=0 max=65535 step=655 default=32768 value=32768 flags=slider
13 mute 0x00980909 (bool) : default=0 value=0
Pour changer les paramètres (non permanent, à adapter à chaque numérisation) :
1$ v4l2-ctl -c brightness=100
2$ v4l2-ctl -c saturation=50
3$ v4l2-ctl -c contrast=60
Exemples de commandes
Force frame rate constant pour MPEG-TS
1ffmpeg -re \
2 -f v4l2 -standard SECAM -i /dev/video0 \
3 -f alsa -i hw:CARD=Cx231xxAudio \
4 -vf yadif=1 -c:v libx264 -b:v 5000k -r 50 -aspect 4:3 -pix_fmt yuv420p -x264opts force-cfr \
5 -c:a aac -b:a 192k \
6 -map 0 -map 1 \
7 -f mpegts "num-$(date +"%s").ts"
fichier de sortie qu'on garde entrelacé
1ffmpeg -re \
2 -f v4l2 -standard SECAM -i /dev/video0 \
3 -f alsa -i hw:CARD=Cx231xxAudio \
4 -c:v libx264 -b:v 5000k -r 25 -aspect 4:3 -pix_fmt yuv420p -x264-params "force-cfr=1" -top 1 -flags:v +ilme+ildct \
5 -c:a aac -b:a 192k \
6 -map 0 -map 1 \
7 -f mpegts "num-$(date +"%s").ts"
Fichier en hevc
1ffmpeg -re \
2 -f v4l2 -standard SECAM -i /dev/video0 \
3 -f alsa -i hw:CARD=Cx231xxAudio \
4 -c:v libx265 -b:v 5000k -r 25 -aspect 4:3 -pix_fmt yuv420p -top 1 -flags:v +ilme+ildct \
5 -c:a aac -b:a 192k \
6 -map 0 -map 1 \
7 -f mpegts "num-$(date +"%s").ts"
x264, désentrelacé, 50fps
1ffmpeg -re \
2 -f v4l2 -standard SECAM -i /dev/video0 \
3 -f alsa -i hw:CARD=Cx231xxAudio \
4 -vf yadif=1 -c:v libx264 -b:v 5000k -aspect 4:3 -pix_fmt yuv420p -x264-params "force-cfr=1" \
5 -c:a aac -b:a 192k \
6 -map 0 -map 1 \
7 -f mpegts "num-$(date +"%s").ts"
Ressources
- https://www.amazon.fr/August-VGB100-Enregistreur-Convertisseur-Video/dp/B008F0SARC : la clé USB de capture VGB100
- https://github.com/aerogus/ffmpeg-compile : script de compilation pour
ffmpeg - https://elrepo.org/wiki/doku.php?id=start : le kernel Linux avec un meilleur support de pérophériques (que le noyau RehHat standard)
- https://ffmpeg.org/ : le couteau suisse de l'audio/vidéo