{"id":11141,"date":"2025-12-11T10:00:56","date_gmt":"2025-12-11T09:00:56","guid":{"rendered":"https:\/\/spgoo.org\/?page_id=11141"},"modified":"2025-12-12T10:54:28","modified_gmt":"2025-12-12T09:54:28","slug":"librairie-wavesurfer","status":"publish","type":"page","link":"https:\/\/spgoo.org\/?page_id=11141","title":{"rendered":"Librairie WaveSurfer"},"content":{"rendered":"\n<h2 class=\"wp-block-heading has-text-align-center\">Librairie WaveSurfer <\/h2>\n\n\n\n<p>Dans le cadre du projet PASSY-DPFV et FRAP\u00e9OR nous avons d\u00fb mettre en place et utiliser une librairie pour visualiser les enregistrements sous diff\u00e9rentes formes :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>sous le forme de melspectrogrammes<\/li>\n\n\n\n<li>sous la forme de FFT<\/li>\n<\/ul>\n\n\n\n<p>Pour ce faire nous avons mis en place la librairie Wavesurfer qui nous permet de r\u00e9pondre \u00e0 ce type de besoin. <\/p>\n\n\n\n<p>Illustrations sur SPGoO voir  <a href=\"https:\/\/spgoo.org\/?page_id=6630\">https:\/\/spgoo.org\/?page_id=6630<\/a> <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"422\" src=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/wavesurfer_illus_spgoo-1024x422.png\" alt=\"\" class=\"wp-image-11148\" srcset=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/wavesurfer_illus_spgoo-1024x422.png 1024w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/wavesurfer_illus_spgoo-300x124.png 300w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/wavesurfer_illus_spgoo-768x316.png 768w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/wavesurfer_illus_spgoo.png 1102w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-vivid-cyan-blue-color has-text-color has-link-color has-medium-font-size wp-elements-9dca1f7ac39547f16f5c698afe8dd548\">Mise en oeuvre et utilisation de cette librairie : <\/p>\n\n\n\n<p>sources : <a href=\"https:\/\/wavesurfer.xyz\/\">https:\/\/wavesurfer.xyz\/<\/a> <\/p>\n\n\n\n<p>Insertion des diff\u00e9rentes inclusions pour permettre l&#8217;acc\u00e8s aux diff\u00e9rents objets :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/personnalisation\/scripts\/wavesurfer.min.js\n\/personnalisation\/scripts\/plugins\/regions.min.js\n\/personnalisation\/scripts\/plugins\/timeline.min.js\n\/personnalisation\/scripts\/plugins\/spectrogram.min.js<\/code><\/pre>\n\n\n\n<p>Pour permettre de r\u00e9actualiser la graphe en fonction du mode de melspectrogramme (mel, linear, logarithmic &#8230;) il a fallu passer par l&#8217;appel de la fonction zoom de l&#8217;objet pour forcer la r\u00e9actulisation car l&#8217;objet lui m\u00eame ne dispose pas de m\u00e9thode update. <\/p>\n\n\n\n<p>Comment s&#8217;impl\u00e9mente l&#8217;appel \u00e0 ce type de librairie :<\/p>\n\n\n\n<p>Il faut cr\u00e9er un conteneur html pour accueillir cette repr\u00e9sentation <\/p>\n\n\n\n<p>Il faut instancier les objets de cette repr\u00e9sentation qui est compos\u00e9e de plusieurs \u00e9l\u00e9ments :<br>Regions, Timeline, Spectrogram et les associer \u00e0 la repr\u00e9sentation graphique.<\/p>\n\n\n\n<p>Repr\u00e9sentation Graphique :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div style=\"width:550px;border-style:inset;border-width: 3px; background:grey;\"&gt;\n  &lt;p style=\"text-align:center;color:#5cb85c\"&gt;Locuteur : IA-alloy&lt;\/p&gt;\n  &lt;div id=\"waveform_ref1\" style=\"width:540px; height:360px;\" &gt;&lt;\/div&gt;\n  &lt;p style=\"display:flex;justify-content:space-evenly;\"&gt;\n    &lt;label&gt;&lt;input type=\"radio\" name=\"MOD_ref7\" id=\"mel\" checked \/&gt;mel&lt;\/label&gt;\n    &lt;label&gt;&lt;input type=\"radio\" name=\"MOD_ref7\" id=\"linear\"  \/&gt;linear&lt;\/label&gt;\n    &lt;label&gt;&lt;input type=\"radio\" name=\"MOD_ref7\" id=\"logarithmic\" \/&gt;logarithmic&lt;\/label&gt;\n    &lt;label&gt;&lt;input type=\"radio\" name=\"MOD_ref7\" id=\"bark\" \/&gt;bark&lt;\/label&gt;\n    &lt;label&gt;&lt;input type=\"radio\" name=\"MOD_ref7\" id=\"erb\" \/&gt;erb&lt;\/label&gt;\n &lt;\/p&gt;\n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Regions plugin\nconst regions_ref1 = WaveSurfer.<strong>Regions<\/strong>.create(); \n\t\nconst bottomTimeline_1 = WaveSurfer.<strong>Timeline<\/strong>.create({\n  height: 15,\n  timeInterval: 0.1,\n  primaryLabelInterval: 0.2,\n  style: {\n    fontSize: '12px',\n    color: '#6A3274',\n  },\n})<\/code><\/pre>\n\n\n\n<p>Cr\u00e9ation de l&#8217;objet WaveSurfer  et du spectrogramme <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Create a WaveSurfer instance\nconst ws_ref1 = WaveSurfer.create({\n  height: 80,\n  minPxPerSec: 1,\n  barWidth: 2,\n  barRadius: 2,\n  barGap: 1,\n  container: '#waveform_ref1',\n  waveColor: 'rgb(200, 0, 200)',\n  progressColor: 'rgb(100, 0, 100)',\n  mediaControls: true,\n  interact: false,\n  url: '\/personnalisation\/frapeor\/tmpreqv8p6t_alloy_ref1.mp3',\n  plugins: &#91;regions_ref1,bottomTimeline_1],\n})\n\n\nconst creation_spectro=function(mode) {\n  return WaveSurfer.<strong>Spectrogram<\/strong>.create({\n    labels: true,\n    labelsColor :\"yellow\",  \n    height: 200,\n    splitChannels: false,\n    \/\/scale: 'mel', \/\/ or 'linear', 'logarithmic', 'bark', 'erb'\n    scale: mode,\n    frequencyMax: 8000,\n    frequencyMin: 0,\n    fftSamples: 512,\n    labelsBackground: 'rgba(25, 25, 25, 0.1)',\n\t windowFunc :\"lanczoz\", \n  });\n}\n\nvar spectro_ref1=null; \n\/\/ Initialize the Spectrogram plugin\nws_ref1.registerPlugin(\n\tspectro_ref1=creation_spectro(\"mel\")\n)<\/code><\/pre>\n\n\n\n<p>Si on veut modifier en direct le type de spectrogramme (mel, linear ou autre) il faut reconstruire le spectrogramme. Exemple d&#8217;utilisation <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ ----------------------------------------------------------------\n\/\/ Evenementiel pour la changement de type de spectrogramme\n\/\/ ----------------------------------------------------------------\ndocument.querySelectorAll('&#91;name^=\"mode_ref1_app1\"]').forEach(elem=&gt; \n  elem.addEventListener(\"click\",function(e) {\n      ws_ref1_app1.plugins.splice(1,1);\n      spectro_ref1_app1.destroy();\n      const mode=e.srcElement.id.split(\"_\")&#91;0];\n      ws_ref1_app1.registerPlugin(\n          spectro_ref1_app1=creation_spectro(mode)\n      )\n      \/\/ important ce zoom car il reconstruit et affiche la diagramme \n      ws_ref1_app1.zoom(1);\n  })\n) <\/code><\/pre>\n\n\n\n<p>Ce qui nous donne le r\u00e9sultat suivant :<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"921\" height=\"487\" src=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/wavesurfer_detail.png\" alt=\"\" class=\"wp-image-11195\" srcset=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/wavesurfer_detail.png 921w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/wavesurfer_detail-300x159.png 300w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/wavesurfer_detail-768x406.png 768w\" sizes=\"auto, (max-width: 921px) 100vw, 921px\" \/><\/figure>\n<\/div>\n\n\n<p>Si on veut ajouter des r\u00e9gions suppl\u00e9mentaires pour les syllabes : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ --------------------------------------------------------------\n\/\/ Avec en param\u00e8tres les syllabes a positionner sur le graphe\n\/\/ --------------------------------------------------------------\nconst ajoute_regions=function(WS, Regions, syllabes=null) {\n  const duration=WS.getDuration(); \/\/ Duree total du signal\n  let debut=0;\n  const pas=2.0\/(syllabes.length+2);\n  console.log(duration,pas, syllabes);\n  let i=1;\n  WS.on('decode', ()=&gt; {\n    syllabes.forEach(syll =&gt; {\n     const p=document.createElement(\"span\");\n     p.innerHTML=syll;\n     p.setAttribute(\"style\",\"font-size:10px;color:lightgreen;margin:5px;\");\n     Regions.addRegion({\n          start: debut,\n          end: debut+pas,\n          content: p,\n          color: randomColor(),\n          drag: true,\n          resize: true,\n     })\n     debut=debut+pas;\n     i++;   \n    })\n  })\n}\nconst active_region=function(WS,Regions){\n{\n  let activeRegion = null\n  Regions.on('region-in', (region) =&gt; {\n    activeRegion = region\n  })\n  Regions.on('region-out', (region) =&gt; {\n    if (activeRegion === region) {\n      if (loop) {\n        region.play()\n      } else {\n        activeRegion = null\n      }\n    }\n  })\n  Regions.on('region-clicked', (region, e) =&gt; {\n    e.stopPropagation() \/\/ prevent triggering a click on the waveform\n    activeRegion = region\n    region.play(true)\n    region.setOptions({ color: randomColor() })\n  })\n  \/\/ Reset the active region when the user clicks anywhere in the waveform\n  WS.on('interaction', () =&gt; {\n    activeRegion = null\n  })\n}\n}\n\/\/ a charger quand le doucment est charg\u00e9 \ndocument.addEventListener(\"DOMContentLoaded\",function(event){\n  ajoute_regions(ws_ref1, regions_ref1,&#91;\"un\",\"grand\",\"vent\",\"souffle\"]);\n  active_region(ws_ref1,regions_ref1);\n});\t<\/code><\/pre>\n\n\n\n<p>Attention une petite pr\u00e9caution \u00e0 prendre lorsqu&#8217;on souhaite cr\u00e9er des spectrogrammes de fa\u00e7on dynamique, voir l&#8217;exemple <a href=\"https:\/\/spgoo.org\/?page_id=6873\">https:\/\/spgoo.org\/?page_id=6873<\/a>. Dans cette r\u00e9alisation, nous avons d\u00e9velopp\u00e9 une page qui permet de cr\u00e9er \u00e0 la vol\u00e9e le spectrogramme et l&#8217;effacer. Dans ce cas pr\u00e9cis, lors de l&#8217;effacement il faut d\u00e9truire l&#8217;objet spectrogram avant de l&#8217;enlever de la DOM, sinon le navigateur conserve l&#8217;objet ce qui lui pose des probl\u00e8mes pour la suite. Pour ce faire on peut proc\u00e9der de la mani\u00e8re suivante :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (visible) {\n\tconst obj=document.getElementById(\"ZE_\"+ind+\"_spectrogramme\")\n\tconst spectro=obj.spectro;\n\tspectro.destroy();\n\tZanno.remove();\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"657\" height=\"142\" src=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/img2025_1.png\" alt=\"\" class=\"wp-image-11202\" srcset=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/img2025_1.png 657w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/img2025_1-300x65.png 300w\" sizes=\"auto, (max-width: 657px) 100vw, 657px\" \/><\/figure>\n\n\n\n<p>Clique que annotation pour g\u00e9n\u00e9rer le visuel ou si il existe le supprimer. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"400\" src=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/img_2025_2-1024x400.png\" alt=\"\" class=\"wp-image-11201\" srcset=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/img_2025_2-1024x400.png 1024w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/img_2025_2-300x117.png 300w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/img_2025_2-768x300.png 768w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/img_2025_2.png 1043w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Mod\u00e8le de classes\/objets <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"821\" height=\"750\" src=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/graphe_wavesurfer.drawio-1.png\" alt=\"\" class=\"wp-image-11206\" srcset=\"https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/graphe_wavesurfer.drawio-1.png 821w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/graphe_wavesurfer.drawio-1-300x274.png 300w, https:\/\/spgoo.org\/wp-content\/uploads\/2025\/12\/graphe_wavesurfer.drawio-1-768x702.png 768w\" sizes=\"auto, (max-width: 821px) 100vw, 821px\" \/><\/figure>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Librairie WaveSurfer Dans le cadre du projet PASSY-DPFV et FRAP\u00e9OR nous avons d\u00fb mettre en place et utiliser une librairie pour visualiser les enregistrements sous diff\u00e9rentes formes : Pour ce faire nous avons mis en place la librairie Wavesurfer qui nous permet de r\u00e9pondre \u00e0 ce type de besoin. Illustrations sur SPGoO voir https:\/\/spgoo.org\/?page_id=6630 Mise [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-11141","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages\/11141","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spgoo.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11141"}],"version-history":[{"count":31,"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages\/11141\/revisions"}],"predecessor-version":[{"id":11207,"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages\/11141\/revisions\/11207"}],"wp:attachment":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11141"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}