Vidéo sur vinyle : essai

Si l’on considère qu’un vinyl sait monter à 22 kHz en stéréo, on peut déduire qu’on peut envoyer un fichier numérique en 44 kbps, en mettant 1 bit par signal, soit 2 en stéréo. Et si l’on pousse un peu plus loin, en en mettant 2 par signal (soit 4 valeurs possibles), on peut monter à 88 kbps…

Étape 1 : encodage de la vidéo

De ce fait, voici un script pour convertir une vidéo en son mono et en débit souhaité (largeur : 320px) :

ffmpeg -i input.mp4 -c:v libx264 -b:v 66150 -b:a 22050 -ac 1 -maxrate 88200 -bufsize 88200 -vf scale=320:-1 output_88k.mp4

Voici un exemple de qualité de vidéo avec la commande ci-dessus :

Court-métrage Wings encodé en H.264, 66 kbps, son mono 22kbps

Une amélioration notable de la qualité, en utilisant le codec AV1 (après recomplilation de FFMpeg), beaucoup plus long à l’encodage (je passe de 2 minutes à presque deux heures) :

ffmpeg -i input.mp4 -c:v libaom-av1 -strict -2 -b:v 66150 -b:a 22050 -ac 1 -maxrate 88200 -bufsize 88200 -vf scale=640:-1 output_88k_av1.mp4

Wings, codec AV1

Et voici la requête de conversion la plus optimisée, notamment pour les films à hauts contrastes lumineux , en 2 passes (limitée à 30 secondes, ce qui prend déjà 25 minutes de temps de conversion sur mon i5) :

ffmpeg -i input.mp4 \
-pass 1 \
-ss 00:01:00 -t 00:00:30 \
-c:v libaom-av1 -strict -2 -b:v 60k \
-c:a libfdk_aac -ar 22050 -b:a 22050 -ac 2 \
-minrate 45k -maxrate 75k -bufsize 33075 \
-vf scale=-1:360 -movflags +faststart -threads 1 -f mp4 \
-y /dev/null && _
ffmpeg -i input.mp4 \
-pass 2 \
-ss 00:01:00 -t 00:00:30 \
-c:v libaom-av1 -strict -2 -b:v 60k \
-c:a libfdk_aac -ar 22050 -b:a 22050 -ac 2 \
-minrate 45k -maxrate 75k -bufsize 33075 \
-vf scale=-1:360 -movflags +faststart -threads 1 -f mp4 \
-y output.mp4

Cosmos Laundromat, extrait

On se rend compte des limites sur les scènes d’action, même en baissant les paramètres (et encore, on est à plus de 100 kbps…) ; cette solution n’est dont pas adaptée aux amoureux du Marvel Cinematic Universe !

Avengers, l’ère d’Ultron, extrait en 106 kbps

Étape 2 : transcription audio

Ensuite, pour convertir le code binaire en son WAV pour la gravure sur vinyle, on s’inspire de la structure d’un WAV (Wikipedia) et on ajoute les données. C’est faisable en PHP, à condition d’allouer un max de mémoire dans php.ini.

J’ai choisi de ne pas avoir de valeur de son à 0, afin de distinguer le manque de signal (début de piste) au signal lui-même. J’ai donc, sur chaque piste, 4 valeurs d’intensité sonore :

  • +50% = valeur binaire 00
  • +100% = valeur binaire 01
  • -50% = valeur binaire 10
  • -100% = valeur binaire 11

Il me faut donc 2 cycles de lecture, sur les 2 pistes, pour obtenir un octet (8 valeurs binaires). Ce qui fait 11025 octets/secondes, soit 88200 bps, ou 88 kbps.

Problème possiblement lié au signal

Divers essais ont montré que le signal généré est davantage triangulaire que rectangulaire, ce qui pour sa relecture risque d’être un casse-tête.

Le palliatif :

  • Changer la base de 11025 à 12000 Hz, ce qui permet une vidéo à 96kbps au lieu de 88kbps
  • Multiplier l’enregistrement d’une donnée par 4
  • Sauver le fichier audio à 96000 Hz au lieu de 22050 Hz

Problème lié à la stéréophonie

Si l’on inverse la gauche et la droite (simplement en inversant le branchement des RCA), les données ne peuvent plus être proprement décodées. Un palliatif possible serait d’avoir le signal du bit 1 en positif sur un des canaux, et du bit 2 en négatif sur l’autre. Est-ce que le graveur de vinyle saura gérer ?

Signal stéréophonique où chaque piste possède des valeurs strictes.
Même signal, pistes permutées.

Étape 3 : décodage audio en vidéo

Enfin, lors de la lecture du vinyle, il faut décoder en 3 étapes :

  1. Transformer l’audio en buffer vidéo
  2. Créer un composant de capture (style webcam virtuelle) qui val lire ce buffer et transmettre le flux
  3. Lire le flux du composant virtuel dans VLC via la capture d’un flux

Je pense que je travaillerai sur un système de lecture audio haute fréquence (192 kHz), pour déterminer la meilleure valeur depuis la transcription analogique. Je pars du postulat que ce n’est pas parce que j’enregistre un signal carré que j’aurai un signal carré sur le disque.

Pour mes tests, je lis le fichier “binaire” depuis mon ordinateur, et du même ordinateur, par un câblé jack-jack, j’écoute le son joué.

arecord

Une solution serait de créer un script sur la base du programme arecord de ALSA Audio, qui permet un enregistrement en continu :

arecord -t raw -r 192000 --max-file-time 1 -c 2 --use-strftime /tmp/%Y%m%d%H%M%S%v.raw

Cela crée un fichier brut d’1 seconde de capture audio.

La comparaison entre la source et l’enregistrement fait apparaître 2 points importants :

  1. L’intensité des courbes est inversée, mais la stéréophonie est respectée
  2. Au bout d’un moment, le son ne reste plus sur un des côtés du neutre, et je perds la spécificité de lecture (si je prends un vinyle depuis le milieu, je ne sais pas quelle sera la stéréophonie)…
A gauche : la source générée par les données binaires
A droite : la lecture analogique du même signal.
A croire que le son va chercher de lui-même à jongler de part et d’autre du neutre… ?

En refaisant le test avec un signal de part et d’autre, on se rend compte qu’il y a une tendance à chercher un point d’équilibre qui fausse l’interprétation, et je ne sais pas encore si ce problème est au niveau de la lecture du son ou de son enregistrement, ni si je rencontrerai un problème similaire depuis un vinyle…

Son enregistré depuis source binaire répartie de part et d’autre du neutre.

Enfin, en alternant un bit positif et un bit négatif, j’obtiens une cohérence bien meilleure… Je dois déterminer, étant donné qu’un octet est divisé en 4, quelle onde correspond au début de l’octet, chose qui sera facilitée par l’alternance d’un “duet” montant et d’un “duet” descendant.

Gauche : binaire / Droite : enregistrement

On pourra imaginer un bouton Switch stéréo sur le préampli-décodeur.

Autre approche : Photosounder

Photosounder, comme son nom l’indique, transforme les images en son. L’idée est de créer un fichier son où on associe un bit à une fréquence donnée. On génère ainsi un son comportant un nombre fini de fréquences, que l’on a à relire à intervalles réguliers.

Exemple de fichier de fréquences, entre 2 kHz et 10 kHz.
Le son est retranscrit sur la ligne bleue en haut.
Ceci doit représenter 1 seconde…

On se rend rapidement compte que, même si l’on exploite un large spectre de fréquences, on ne peut décemment pas stocker énormément de données par seconde (si l’on part sur 2400 pixels/seconde, et 32 fréquences entre 2 et 10 kHz, on obtient 76kbps, soit 1.3x moins d’informations que le minimum)…

A voir si ceci est aisément et fiablement déchiffrable…
Et à plus forte raison ainsi (64 fréquences entre 2 et 10 kHz, 2400 pixels/secondes)

Buffer vidéo

Ensuite, on peut lire le fichier correspondant au temps t-1 seconde, pour décrypter son contenu et l’inclure dans un buffer vidéo.

Extraction des données binaires

Afin d’assurer le décryptage, et en tenant compte que tous les tourne-disques ne tournent pas précisément à la même vitesse, il me faut déterminer la fréquence porteuse du signal :

sox arecord.wav -r 30k -n rate spectrogram

On constate bien que la fréquence porteuse ici est 12 kHz.

Autre approche, indépendante de la fréquence, déterminer les valeurs des seuils (points rouges) :

Note importante : le son nouvellement enregistré est en 8 bits non signés (valeurs de 0 à 255) et non en 8 bits signés (valeurs de -128 à 127). L’algorithme de test en PHP semble bien retranscrire en binaire les données analogiques. L’idéal serait de créer un interpréteur compilé appelable de la sorte :

wav2binary /tmp/201910051437300001.wav /tmp/binarybuffer

Lecture par un lecteur vidéo

On pourrait exploiter la fonction SMEM (Stream to Memory) de VLC, pour injecter les données binaires directement extraites.

Réalisation technique

Interfaces externes :

  • Entrée : 2 RCA mono
  • Switch : pré-ampli ou non
  • Switch : audio ou vidéo
  • Sortie : 2 RCA mono pour la sortie pur audio
  • Switch d’inversion de signal (inverser le positif du négatif)
  • Switch d’inversion de la stéréophonie
  • Sortie : HDMI pour la vidéo
  • Alimentation : 5V / 12V / 220V (à voir selon le pré-ampli)
  • Prise terre pour le pré-ampli

Composants internes :

  • Pré-ampli, alimenté en 5V, 12V ou 220V
  • Raspberry Pi, voire Zero
  • Vu-mètres stéréo (optionnel)
  • Adaptateur mini-HDMI vers HDMI à intégrer
  • Adaptateur alimentation Raspberry Pi
  • Fils électriques
  • Transformateur de modulation pour jeux de lumière (inversion de polarité) ou transfo micro adaptateur d’impédance

Schéma de principe prévu :

Schéma des composants

Laisser un commentaire