Outils pour utilisateurs

Outils du site


numeriser_jean_de_la_fontaine

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
numeriser_jean_de_la_fontaine [2022/03/04 14:24] – créée Simon Deplatnumeriser_jean_de_la_fontaine [2022/03/07 16:10] (Version actuelle) Simon Deplat
Ligne 1: Ligne 1:
 +====== Numériser Jean de La Fontaine ======
 +
 =====Contexte===== =====Contexte=====
  
-Dans le cadre du Bestiaire d'Intelligences Artificielles, nous avons décidé de ressusciter ce fameux [[https://fr.wikipedia.org/wiki/Jean_de_La_Fontaine|Jean de La Fontaine]].+Dans le cadre du **Bestiaire d'Intelligences Artificielles**, nous avons décidé de ressusciter ce fameux [[https://fr.wikipedia.org/wiki/Jean_de_La_Fontaine|Jean de La Fontaine]].
  
-C'est Serge qui a fait le plus gros du travail en défrichant la technologie [[https://github.com/minimaxir/aitextgen|aitextgen]], qui utilise Python et la [[https://datascience.sia-partners.com/fr/blog/gpt-2-dopenai-un-meilleur-outil-de-traitement-automatique-du-langage-et-les-questions-ethiques|GPT2]] afin de proposer une intelligence artificielle capable de produire du texte à partir d'un corpus de base, en imitant le style et le vocable de l'auteur original.+C'est Serge qui a fait le plus gros du travail en défrichant la technologie [[https://github.com/minimaxir/aitextgen|aitextgen]], qui utilise Python et la [[https://datascience.sia-partners.com/fr/blog/gpt-2-dopenai-un-meilleur-outil-de-traitement-automatique-du-langage-et-les-questions-ethiques|GPT2]] afin de **proposer une intelligence artificielle capable de produire du texte à partir d'un corpus de base, en imitant le style et le vocable** de l'auteur original.
  
 Dans notre cas, c'est donc l'auteur des fables qui a été choisi pour ce cruel exercice. Dans notre cas, c'est donc l'auteur des fables qui a été choisi pour ce cruel exercice.
  
-Je suis parti assez rapidement sur le projet, sans prendre trop le temps de me renseigner sur la suite des étapes. Vous pardonnerez donc les lacunes explicatives des étapes qui suivent.+Je suis parti assez rapidement sur le projet, sans prendre trop le temps de me renseigner sur les technologies manipulées. Vous pardonnerez donc les lacunes explicatives des étapes qui suivent.
  
 =====Installaton d'aitextgen===== =====Installaton d'aitextgen=====
  
-J'ai pour ce faire utilisé les instructions de Serge, présentes sur la page [[https://ressources.labomedia.org/bestiaire_ia_fables_de_la_fontaine|Bestiaire IA Fables de la Fontaine]].+J'ai pour ce faire utilisé **les instructions de Serge**, présentes sur la page [[https://ressources.labomedia.org/bestiaire_ia_fables_de_la_fontaine|Bestiaire IA Fables de la Fontaine]].
  
-Pour des raisons pratiques, on commence par mettre-à-jour pip et installer le module d'environnement virtuel de Python :+Pour des raisons pratiques, **on commence par mettre-à-jour //pip// et installer le module d'//environnement virtuel// de Python** :
  
 <code bash> <code bash>
Ligne 23: Ligne 25:
 </code> </code>
  
-pip permet d'installer de manière simple les différentes librairies Python. Quand à l'environnement virtuel, il permet de faire cohabiter plusieurs projets Python en parallèle dont les librairies seraient contradictoires (par exemple si deux versions différentes d'une même librairie sont nécessaires à deux projets). Plus d'info à ces sujets, en anglais, [[https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/|ici]].+**//pip// permet d'installer de manière simple les différentes librairies Python****Quand à l'//environnement virtuel//, il permet de faire cohabiter plusieurs projets Python en parallèle dont les librairies seraient contradictoires** (par exemple si deux versions différentes d'une même librairie sont nécessaires à deux projets). Plus d'info sur ces sujets, en anglais, [[https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/|ici]]
 + 
 +Après cela, une fois dans le bon dossier ( par exemple ///home/machin/projets// ), **nous clonons le répertoire** de Serge depuis //git//, ce qui nous facilite toute l'installation. Attention, il y a 2Go à télécharger, c'est un peu long : 
 +<code bash> 
 +git clone https://github.com/sergeLabo/La_Fontaine 
 +# Allez dans le dossier des sources 
 +cd ./La_Fontaine 
 +python3 -m venv mon_env 
 +source mon_env/bin/activate 
 +python3 -m pip install -r requirements.txt 
 +</code> 
 + 
 +Vous pouvez voir qu'après avoir récupéré le dossier, **nous mettons en place l'//environnement virtuel//**. De fait, à partir de maintenant, **nous n'utiliserons plus la commande Python de base, mais nous appellerons le binaire de l'environnement virtuel** : 
 + 
 +<code bash> 
 +./mon_env/bin/python3 mon_fichier.py 
 +</code> 
 + 
 +=====Entraîner l'intelligence artificielle à partir d'un corpus===== 
 + 
 +Vous pourrez trouver le corpus qui a servi de base d'entraînement pour ce projet : //fables.txt//
 +J'ai essayé à partir d'un autre corpus : l'[[http://palimpsestes.fr/textes_philo/spinoza/ethique.pdf|Éthique de Spinoza]]. Le résultat était aussi chiant que l'original. 
 + 
 +Il vous faudra donc **avoir un fichier texte qui contient le modèle textuel à calquer**. Attention, **plus celui-ci est grand, mieux cela fonctionne**. Et quand je dis grand, j'entends bien démesurément grand... Les modèles des //Fables//, ou de l'//Éthique//, qui fait pourtant 150 pages, sont beaucoup trop petit pour entraîner de manière correcte le modèle. C'est comme ça. 
 + 
 +Il sera souvent **nécessaire de retoucher le fichier texte avant l'entraînement**. Dans le cas de l'//Éthique//, **les numéros de pages étaient encore présent dans le fichier texte, je les ai donc supprimés**. Il y avait également des **césures** à la plupart des sauts de lignes... Je n'ai pas eu le courage de trouver l'algorithme pour les corriger. Il n'apparaissaient pas dans les textes générés mais je pense qu'ils ont limité l'apprentissage. De la même manière, il faut **supprimer les notes de bas de pages, les légendes des dessins, etc**. 
 + 
 +Une fois votre corpus enregistré en fichier texte dans le dossier, voici **le script python qui permet de ré-entraîner le modèle** : 
 + 
 +<code python text_training.py> 
 +from aitextgen.TokenDataset import TokenDataset 
 +from aitextgen.tokenizers import train_tokenizer 
 +from aitextgen.utils import GPT2ConfigCPU 
 +from aitextgen import aitextgen 
 + 
 +# The name of the downloaded text for training 
 +file_name = "fables.txt" 
 + 
 +# Train a custom BPE Tokenizer on the downloaded text 
 +# This will save one file: `aitextgen.tokenizer.json`, which contains the 
 +# information needed to rebuild the tokenizer. 
 +train_tokenizer(file_name) 
 +tokenizer_file = "aitextgen.tokenizer.json" 
 + 
 +# GPT2ConfigCPU is a mini variant of GPT-2 optimized for CPU-training 
 +# e.g. the # of input tokens here is 64 vs. 1024 for base GPT-2. 
 +config = GPT2ConfigCPU() 
 + 
 +# Instantiate aitextgen using the created tokenizer and config 
 +ai = aitextgen(tokenizer_file=tokenizer_file, config=config) 
 + 
 +# You can build datasets for training by creating TokenDatasets, 
 +# which automatically processes the dataset with the appropriate size. 
 +data = TokenDataset(file_name, tokenizer_file=tokenizer_file, block_size=64) 
 + 
 +# Train the model! It will save pytorch_model.bin periodically and after completion to the `trained_model` folder. 
 +ai.train(data, batch_size=8, num_steps=50000, generate_every=5000, save_every=5000) 
 +</code> 
 + 
 +Il faut **spécifier le fichier texte du corpus à la ligne 7** . 
 + 
 +**D'autres configurations sont possibles**, ici c'est la version qui utilise le CPU. Sur ma machine, équipée d'un Core I5 9th Gen, les entraînements pour les //Fables// et l'//Éthique// ont pris un peu plus d'une heure. 
 + 
 +=====Générer du texte à partir d'un modèle===== 
 + 
 +Voici maintenant **le fichier utilisé pour générer du texte à partir du modèle**. Je n'ai pas encore regardé comment modifier les paramètres, mais cela ne doit pas être trop difficile : 
 + 
 +<code python textgen.py> 
 +from aitextgen import aitextgen 
 + 
 +ai = aitextgen(model_folder="trained_model", 
 +                tokenizer_file="aitextgen.tokenizer.json"
 + 
 +ai.generate(1, prompt=""
 +</code> 
 + 
 +Pour l'utiliser, je n'affiche pas le texte dans le terminal, mais le **redirige** vers un fichier nommé //text.txt//
 + 
 +<code bash> 
 +./mon_env/bin/python3 textgen.py > text.txt 
 +</code> 
 + 
 +**Un exemple de texte généré** : 
 + 
 +<code> 
 +La Grenouille  - La Fontaine 
 + 
 + L'Aigle et le Singe aperçut 
 +De son ami-là : votre sens y prompt ; 
 +De quoi cette Science eut un fardeau pendu. 
 +</code> 
 + 
 +**C'est du grand portnawak, c'est parfait.** 
 + 
 +=====Vocalisation===== 
 + 
 +Maintenant que le  plus important est fait, à savoir, d'une certaine manière, avoir mis en place le contexte cérébral de ce petit Jean, il faut commencer à l'**incarner**. 
 + 
 +La première étape est de pouvoir **le faire dicter ses nouvelles fables**, en utilisant **un logiciel de synthèse sonore**, en anglais //Text To Speech//, souvent abrévié //TTS//. 
 + 
 +**La ressource principale** que j'ai trouvée, sur ce sujet et concernant les logiciels libres, est [[https://doc.ubuntu-fr.org/synthese_vocale|la documentation Ubuntu]]. Cependant, Manu a également trouvé un logiciel pertinent développé par une fondation bien connue : //[[https://github.com/mozilla/TTS|Mozilla TTS]]//. 
 + 
 +De manière succincte, voici les résultats auxquels j'ai abouti pour ces logiciels. Je n'ai pas essayé //festival//
 + 
 +Premièrement, //espeak//. C'est presque un artefact des anciens temps, tant **la voix est robotisée**. On n'y comprends pas grand chose et c'est **très moche** : 
 + 
 +<code> 
 +espeak -v fr -f text.txt 
 +</code> 
 + 
 +Concernant //svoxpico//, la voix est meilleure qu'//espeak//, ce qui n'est pas bien difficile au final. **Elle hoquette quelque peu mais cela lui confère un certain charme. Par contre elle est uniquement féminine** en langue française : 
 + 
 +<code> 
 +pico2wave -l fr-FR -w text.wav < text.txt && play text.wav 
 +</code> 
 + 
 +Avec //Mozilla TTS//, **les résultats sont plus probants**, même s'il y a quelques cafouillis par-ci par-là. Mais là encore, **seules des voix féminines sont disponibles** : 
 + 
 +<code> 
 +tts --text "$(cat text.txt)" --model_name tts_models/fr/mai/tacotron2-DDC --vocoder_name vocoder_models/universal/libri-tts/fullband-melgan && play tts_output.wav 
 +</code> 
 + 
 +**De fait, la solution que j'ai finalement retenue se sert d'//espeak// ! Mais en conjonction avec un autre logiciel, qui s'appelle //mbrola//.** Je l'ai installé, ainsi que l'ensemble des voix françaises, via cette commande : 
 + 
 +<code> 
 +sudo apt-get install mbrola mbrola-fr* 
 +</code> 
 + 
 +Cette fois-ci, **nous utilisons //espeak// pour générer un fichier de phonèmes, puis nous utilisons les vocoders de //mbrola// pour les lire** : 
 + 
 + 
 +<code> 
 +espeak -q -s 100 -v mb/mb-fr1 -f text.txt --pho --phonout=text.pho && mbrola /usr/share/mbrola/fr6/fr6 text.pho text.wav && play text.wav 
 +</code> 
 + 
 +Étrangement, cela ne marche pas avec l'argument //-v fr// d'//espeak//, il faut utiliser //-v mb/mb-fr1// à la place. 
 + 
 +**Pour changer de vocoder**, il faut **spécifier le chemin de celui-ci** dans la commande //mbrola//. Dans le cas précédent, c'est le chemin ///usr/share/mbrola/fr6/fr6// qui le spécifie. 
 + 
 +Cette fois-ci, nous avons **une voix masculine d'assez bonne qualité**, ce qui me satisfait. 
 + 
 +=====Quoi ma gueule ?===== 
 + 
 +Il faut maintenant associer la voix à un visage. Pour ce faire, **un petit tour sur le net et un copier-coller** d'un tableau représentatif de l'écrivain. 
 + 
 +Mais ce n'est pas tout, j'aimerai bien pouvoir **l'animer** un tantinet. Mon idée était de singer l'intelligence artificielle et la culture française **en transformant Jidéhéléf en pantin**. À l'aide de //[[https://www.gimp.org/|GIMP]]//, j'ai donc séparé le tableau original en plusieurs parties faciles à animer, **à la manière d'un système de calques** : 
 + 
 +{{ ::jdlfgimp.png?1000 |}} 
 + 
 +=====LaFontaine.exe===== 
 + 
 +Il est maintenant temps de regrouper ensemble les pensées, la voix et la frimousse de Jean ! 
 + 
 +J'avais en premier pensé utiliser le moteur de jeu vidéo libre //[[https://godotengine.org/|Godot]]// pour ce faire, car il intègre des outils d'animation simple à utiliser. Cependant, **j'ai finalement opté pour //[[https://tutos.labomedia.org/books/musique-assistee-par-ordinateur/page/quest-ce-que-supercollider|SuperCollider]]//** pour faire cela, notamment car c'est le logiciel le plus simple que je connaisse pour implémenter le déplacement de la mâchoire de Jean en fonction des conneries qu'il raconte. 
 + 
 +Voici le code du projet : 
 + 
 +<code> 
 +
 + 
 +var win = Window.new( 
 + "La Fontaine", 
 + Rect( 1000, 500, 200, 200 ) ); 
 + 
 +var filePath = thisProcess.nowExecutingPath.dirname ++ "/text.wav"; 
 + 
 +var lock = false; // Empêche de regénérer une fable tant que la précédente n'est pas finie 
 +var lockDelay = 1; // Délai supplémentaire de restriction 
 + 
 +var stringCmd; // Variable qui va stocker l'appel Bash à la génération du texte et du fichier son 
 + 
 +var view = UserView(); 
 + 
 +var imgJean = Image.new( 
 + thisProcess.nowExecutingPath.dirname ++ "/JEAN.png" ); 
 +var imgEmpty = Image.new( 
 + thisProcess.nowExecutingPath.dirname ++ "/emptyeyes.png" ); 
 +var imgChin = Image.new( 
 + thisProcess.nowExecutingPath.dirname ++ "/lafontaine_chin.png" ); 
 +var imgPupille = Image.new( 
 + thisProcess.nowExecutingPath.dirname ++ "/pupille.png" ); 
 + 
 +var textSpeed = 120; // Vitesse d'élocution 
 +var voiceTag = "fr3"; // Vocoder utilisé 
 + 
 +var jawOffset = 0; // Décalage de la mâchoire 
 + 
 +var eg = Point( 390, 512 ); // Position de l'oeil gauche 
 +var ed = Point( 385, 415 ); // Position de l'oeil droit 
 + 
 +var egtarget = Point( 390, 512 ); // Position de référence l'oeil gauche 
 +var edtarget = Point( 385, 415 ); // Position de référence l'oeil droit 
 + 
 +if( ~masterIn == nil, { // Bus master 
 + ~masterIn = Bus.audio( s, 1 ) } ); 
 + 
 +if( ~ampBus == nil, { // Bus de valeur d'amplitude 
 + ~ampBus = Bus.control( s, 1 ) } ); 
 + 
 + 
 +SynthDef( \master, { 
 + 
 + var sound = In.ar( ~masterIn, 1 ); 
 + var amp = Amplitude.kr( sound ); 
 + var panSound = Pan2.ar( sound ); 
 + 
 + Out.kr( ~ampBus, amp ); 
 + Out.ar( 0, panSound ); 
 + 
 +} ).play; 
 + 
 + 
 +// Construction de la commande Bash 
 +voiceTag = voiceTag ++ "/" ++ voiceTag; 
 + 
 +stringCmd = "cd ~/CNFS/bestiaireia/La_Fontaine/;"; 
 +stringCmd = stringCmd ++ "./mon_env/bin/python3 textgen.py > text.txt;"; 
 +stringCmd = stringCmd ++ "espeak -q -s " ++ textSpeed.asString ++ " -v mb/mb-fr1 -f text.txt --pho --phonout=text.pho;"; 
 +stringCmd = stringCmd ++ "mbrola /usr/share/mbrola/" ++ voiceTag ++ " text.pho text.wav"; 
 + 
 +// Fonction déclenchée à l'input 
 +win.view.keyDownAction = { arg view, char, modifiers, unicode,keycode; 
 + 
 + if( lock == false, { 
 + if( unicode == 32, { 
 + 
 + stringCmd.systemCmd; 
 + lock = true; 
 + 
 + b = Buffer.read( 
 + s, 
 + filePath, 
 + action: { { lock = false; }.defer( b.numFrames * ( 1.0 / b.sampleRate ) ) } 
 + ); 
 + 
 + SynthDef( "playbuf",
 + Out.ar( ~masterIn, 
 + PlayBuf.ar( 
 + numChannels: 1, 
 + bufnum: b.bufnum, 
 + rate: BufRateScale.kr( b.bufnum ) * 1, 
 + trigger: 1, 
 + startPos: 0, 
 + loop: 0, 
 + doneAction: Done.freeSelf ), 
 + 0.0 
 +
 + } ).play; 
 + } ); 
 + } ); 
 +}; 
 + 
 +win.view.layout_( HLayout() ); 
 + 
 +win.view.layout.add( view ); 
 + 
 +// Fonction d'affichage graphique : 
 +view.drawFunc = { 
 + Pen.drawImage( Point( 1920 - 1284 / 2 + 350, 1080 - 1000 / 2 + ( 1000 - 437 - 175 ) ), imgEmpty, operation: 'sourceOver', opacity:1); 
 + 
 + 
 + 
 + Pen.drawImage( Point( 1920 - 1284 / 2 + eg.x, 1080 - 1000 / 2 + eg.y ), imgPupille, operation: 'sourceOver', opacity:1); // Oeil droit 
 + 
 + Pen.drawImage( Point( 1920 - 1284 / 2 + ed.x, 1080 - 1000 / 2 + ed.y ), imgPupille, operation: 'sourceOver', opacity:1); // Oeil gauche 
 + 
 + Pen.drawImage( Point( 1920 - 1284 / 2, 1080 - 1000 / 2 ), imgJean, operation: 'sourceOver', opacity:1); 
 + Pen.drawImage( Point( 1920 / 2 - 132 + jawOffset, 1080 / 2 - 83 ), imgChin, operation: 'sourceOver', opacity:1); 
 +}; 
 + 
 + 
 +// Routine qui associe l'amplitude sonore à la position de la mâchoire : 
 +Routine( { 
 + 
 + var rand; 
 + var randN = 10; 
 + 
 + loop { 
 + 
 + ~ampBus.get( { | val | jawOffset = val.linlin( 0.0, 1.0, 0, 100 ); } ); 
 + jawOffset = jawOffset.asInteger; 
 + 
 + if( lock == true, { 
 + rand = randN.rand; 
 + if( rand == 0, { eg.x = eg.x + 1 } ); 
 + if( rand == 1, { eg.x = eg.x - 1 } ); 
 + if( eg.x < 385, { eg.x = 385 } ); 
 + if( eg.x > 410, { eg.x = 410 } ); 
 + 
 + rand = randN.rand; 
 + if( rand == 0, { eg.y = eg.y + 1 } ); 
 + if( rand == 1, { eg.y = eg.y - 1 } ); 
 + if( eg.y < 488, { eg.y = 488 } ); 
 + if( eg.y > 524, { eg.y = 524 } ); 
 + 
 + rand = randN.rand; 
 + if( rand == 0, { ed.x = ed.x + 1 } ); 
 + if( rand == 1, { ed.x = ed.x - 1 } ); 
 + if( ed.x < 380, { ed.x = 380 } ); 
 + if( ed.x > 395, { ed.x = 395 } ); 
 + 
 + rand = randN.rand; 
 + if( rand == 0, { ed.y = ed.y + 1 } ); 
 + if( rand == 1, { ed.y = ed.y - 1 } ); 
 + if( ed.y < 400, { ed.y = 400 } ); 
 + if( ed.y > 430, { ed.y = 430 } ); 
 + } ); 
 + 
 + if( lock == false, { 
 + if( eg.x < egtarget.x, { eg.x = eg.x + 1 } ); 
 + if( eg.x > egtarget.x, { eg.x = eg.x - 1 } ); 
 + if( eg.y < egtarget.y, { eg.y = eg.y + 1 } ); 
 + if( eg.y > egtarget.y, { eg.y = eg.y - 1 } ); 
 + 
 + if( ed.x < edtarget.x, { ed.x = ed.x + 1 } ); 
 + if( ed.x > edtarget.x, { ed.x = ed.x - 1 } ); 
 + if( ed.y < edtarget.y, { ed.y = ed.y + 1 } ); 
 + if( ed.y > edtarget.y, { ed.y = ed.y - 1 } ); 
 + } ); 
 + 
 + { view.refresh }.defer; 
 + 
 + (1/30).wait 
 + }; 
 +} ).play; 
 + 
 +win.background = Color.black; // Set main widow background as black 
 +win.fullScreen; 
 + 
 +win.front; 
 + 
 +// À la fermeture, libération de la mémoire : 
 +CmdPeriod.doOnce( { 
 + Window.closeAll; 
 + s.freeAll; 
 + imgChin.free; 
 + imgJean.free; 
 + imgEmpty.free; 
 + imgPupille.free; 
 +} ); 
 + 
 +
 +</code> 
 + 
 +Sans rentrer trop dans le détail, quelques points sont intéressants à aborder sur l'algorithme. 
 + 
 +===Corrélation de l'audio et de l'affichage graphique=== 
 + 
 +L'idée principale était d'**utiliser SuperCollider afin de relier le volume sonore ( l'amplitude ) du fichier son au déplacement de la mâchoire**. Pour mettre cela en place, j'ai d'abord décidé d'utiliser //espeak// et //mbrola// de telle manière qu'ils produisent non pas un son direct, mais **un enregistrement audio**. 
 + 
 +Au lancement du programme, **un synthé maître est créé**, qui utilise un //Ugen IN// afin de pouvoir bénéficier d'un son d'entrée créé //a posteriori//. Lors de la génération d'une fable, **le fichier son résultant est chargé dans SC**, puis **envoyé dans l'entrée du synthé maître**. **Important** : le synthé créé lors de la génération est supprimé lors de la fin de la lecture grâce au paramètre //doneAction: Done.freeSelf// du //PlayBuf//. Le cas échéant, les //UGens// créés pour jouer le sample resteraient présent en mémoire et risqueraient de rapidement saturer l'ordinateur. 
 + 
 +Dans le synthé maître, avant de **le passer en stéréo et de l'envoyer vers la carte son**, **le son est en premier lieu analysé grâce à l'//UGen Amplitude//, qui redirige son résultat d'analyse dans un //Bus//** créé au préalable. 
 + 
 +C'est **une //Routine// qui**, à intervalle régulier, **récupère la valeur d'amplitude au sein du //Bus//**, modifie la valeur de référence de la position de la mâchoire puis lance un appel de rafraîchissement de l'interface graphique. On utilise //{}.defer// car **la mise-à-jour graphique ne peut s'effectuer dans le contexte audio**. 
 + 
 +La méthode d'accès à une valeur présente dans un //UGen//, c'est-à-dire une information qui passe du serveur à //sclang//, [[https://scsynth.org/t/getting-values-out-of-ugens/489|est discutée dans ce post sur le forum de SC]], et [[http://modularbrains.net/dx490a/DX490A_su2010_02.1_%5BServer-language_communication%5D.html|approfondie dans ce tutoriel]]. 
 + 
 +===Commandes BASH depuis SC et synchronicité=== 
 + 
 +**Sous //Linux//, il est très simple d'envoyer des commandes //BASH// dans le terminal depuis //SC//.** Pour ce faire, **on utilise une méthode sur une chaîne de caractères qui contient la commande à exécuter.** Pour exécuter plusieurs commandes, on les sépare par des points virgules : 
 + 
 +<code> 
 +"ls".unixCmd 
 +</code> 
 + 
 + 
 +<code> 
 +"cd Dossier/;ls".systemCmd 
 +</code> 
 + 
 +Dans //SuperCollider//, on distingue **deux types de fonctions : les commandes //synchrones//, et les commandes //asynchrones//**. En règle générale, **une commande synchrone bloque l'éxecution du code dans //sclang// le temps que le serveur se mette à jour.** Cela permet par exemple d'éviter, après avoir ajouté une //SynthDef//, de l'appeler avant qu'il soit effectivement initialisé. 
 + 
 +Dans notre cadre, la génération de la fable, et dans une moindre mesure la génération du fichier audio, prend un peu de temps à l'ordinateur. **Nous utilisons donc .//systemCmd//, qui est la fonction synchrone d'accès au terminal.** 
 + 
 +Le cas échéant, en utilisant .//unixCmd//, le fichier audio est chargé par SuperCollider avant que la nouvelle fable soit générée, c'est donc la fable précédente qui est récitée... 
 + 
 +Ici, un problème posé est que la suspension d'activité dans //sclang// via **l'appel à la fonction synchrone .//systemCmd// arrête également la //Routine//** responsable de la mise-à-jour graphique, **ce qui bloque l'animation**. J'ai résolu ce problème en n'animant pas la partie d'attente au cours de laquelle aucune fable n'est récitée. Le blocage de la //Routine// est donc invisible à l'utilisateur, même s'il existe. 
 + 
 +Dans l'absolu, il aurait fallu plutôt utiliser .//unixCmd//, et mettre en place un retour depuis le terminal afin de lancer l'enregistrement audio après la génération du nouveau fichier. Tant qu'on y est, il est à noter que lorsque l'image est immobile, la //Routine// contiue de tourner, ce qui n'est pas optimal mais pas catastrophique par ailleurs. 
 + 
 +=====La Suite ?===== 
 + 
 +À ce stade, **le prototype est fonctionnel mais quelques améliorations sont possibles** : 
 + 
 +  * Refaire l'algorithme de Routine pour qu'il ne reste activé que le temps de l'animation. 
 +  * Mettre l'image de Jean de La Fontaine en plein écran, mais cela dépend de la résolution du moniteur que nous utiliserons pour l'installation. 
 +  * Ajouter un retour visuel de la fable générée, parce que la voix n'est pas toujours claire, et pour les publics malentendants. 
 +  * Réaliser le dispositif physique de l'installation, avec un joli cadre en bois, et tout le toutim. 
 +  * Trouver un moyen de générer des fables plus longues.
  
-[EN CONSTRUCTION]+{{tag> bestiaire_ia tal }}
numeriser_jean_de_la_fontaine.1646403895.txt.gz · Dernière modification : 2022/03/04 14:24 de Simon Deplat