Compare commits

..

4 Commits

Author SHA1 Message Date
02d84da263 avec marqueurs et régions 2021-08-13 18:14:31 +02:00
2219b56ee0 readme add 2021-08-13 17:54:19 +02:00
0b86e12689 show wave on anitra's dance 2021-08-13 17:53:07 +02:00
af53a973f4 hop 2021-08-13 16:48:38 +02:00
11 changed files with 9088 additions and 30 deletions

View File

@ -2,12 +2,24 @@
lecteur audio pour l'émission Libre à vous
## Être débuté
servir le dossier local avec le package npm **serve** afin de ne pas avoir de problème de requête CORS,
```bash
serve .
```
et ouvrir localhost://5000
ou lancer index.html dans un navigateur.
Attention, il faut créer un objet surfer avec WaveSurfer et appliquer ensuite dessus les actions de play pause et etc, pas directement sur WaveSurver, mais bien ses instances.
On peut aussi faire plusieurs instances.
## liens
https://github.com/katspaugh/wavesurfer.js
démo du rendu recherché:
https://dev.to/jamland/audio-player-with-wavesurfer-js-react-1g3b
https://codesandbox.io/s/audio-player-with-wavesurferjs-react-bd499?from-embed
marqueurs pour chapitres
https://wavesurfer-js.org/plugins/markers.html
@ -16,4 +28,9 @@ rendu des vagues en avance côté serveur
https://wavesurfer-js.org/faq
https://521dimensions.com/open-source/amplitudejs/docs/fx/waveforms.html#displaying-waveform-elements
https://wavesurfer-js.org
https://wavesurfer-js.org
## génération de wave peaks
avec audiowaveforms

BIN
audio/demo.wav Normal file

Binary file not shown.

View File

@ -6,33 +6,83 @@
</title>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="style.css"/>
<script src="js/wavesurfer.min.js"></script>
<script type="application/javascript" src="js/wavesurfer.js"></script>
<script src="js/regions.min.js"></script>
<script src="js/markers.min.js"></script>
<script type="application/javascript" src="js/main.js"></script>
</head>
<body>
<h1> Example de lecteur audio enrichi</h1>
<blockquote>
Code de vincent:
<figure>
<figcaption>Écoute de l'émission intégrale</figcaption>
<audio id="player" controls preload="metadata">
<source src="https://media.april.org/audio/radio-cause-commune/libre-a-vous/emissions/20210622/libre-a-vous-20210622.ogg"
type="audio/ogg">
<source id="audio"
src="https://media.april.org/audio/radio-cause-commune/libre-a-vous/emissions/20210622/libre-a-vous-20210622.mp3"
type="audio/mp3">
Votre navigateur ne supporte pas l'élément <code>audio</code>
</audio>
</figure>
</blockquote>
<hr>
<audio src="audio/anitra.mp4" controls></audio>
<!-- a div where the div will be placed -->
<body onkeyup="silverSurfer.playPause()">
<h1> Example de lecteur audio enrichi pour Libre à vous</h1>
<section>
<h1> Rendu enrichi </h1>
<div id="waveform"></div>
<script>
const player = new Plyr('#player');
</script>
<!-- contient les audio peaks sera remplacé par WaveSurfer -->
<div id="wave_box">
<div id="waveform"></div>
</div>
<div class="controls">
<button class="clickable forward" onclick="silverSurfer.skip(-30)">⏩ -30s</button>
<button class="clickable play-pause" onclick="silverSurfer.playPause()">⏯️</button>
<button class="clickable forward" onclick="silverSurfer.skip(30)">⏩ +30s</button>
<button class="clickable forward" onclick="silverSurfer.stop()">stop</button>
<input type="range" id="volume" name="volume"
value="60" onchange="onVolumeChange"
min="0" max="100">
<label for="volume">Volume</label>
</div>
<h2>Sections</h2>
<ul>
<li class="clickable ">
intro
</li>
<li class="clickable " onclick="silverSurfer.play(60)">
01:00 chronique A
</li>
<li class="clickable ">
sujet principal
</li>
<li class="clickable ">
pause musicale 1
</li>
<li class="clickable ">
chronique B
</li>
<li class="clickable ">
clotûre
</li>
</ul>
<audio id="anitra" src="audio/anitra.mp4" controls></audio>
</section>
<section>
<blockquote>
Code de vincent:
<figure>
<figcaption>Écoute de l'émission intégrale</figcaption>
<audio id="player" controls preload="metadata">
<source src="https://media.april.org/audio/radio-cause-commune/libre-a-vous/emissions/20210622/libre-a-vous-20210622.ogg"
type="audio/ogg">
<source id="audio"
src="https://media.april.org/audio/radio-cause-commune/libre-a-vous/emissions/20210622/libre-a-vous-20210622.mp3"
type="audio/mp3">
Votre navigateur ne supporte pas l'élément <code>audio</code>
</audio>
</figure>
</blockquote>
<hr>
Anitra:
<audio id="to_pick" controls preload="metadata">
<source src="http://localhost:5000/audio/demo.wav"
type="audio/mp4">
Votre navigateur ne supporte pas l'élément <code>audio</code>
</audio>
</section>
</body>
</html>

109
js/main.js Normal file
View File

@ -0,0 +1,109 @@
let silverSurfer = {}
const handlePlayPause = () => {
silverSurfer.playPause();
};
const onVolumeChange = e => {
console.log(e)
const {target} = e;
const newVolume = +target.value;
if (newVolume) {
setVolume(newVolume);
WaveSurfer.current.setVolume(newVolume || 1);
}
};
window.addEventListener('DOMContentLoaded', (event) => {
console.log('page is fully loaded', WaveSurfer);
const refElement = document.querySelector('#waveform')
// const url = '/audio/anitra.mp4'
// const url = document.querySelector('#player source').src
const url = 'http://localhost:5000/audio/anitra.mp4'
// const url = 'https://media.april.org/audio/radio-cause-commune/libre-a-vous/emissions/20210622/libre-a-vous-20210622.ogg'
console.log('hello from main.js', refElement)
const waveoptions = {
// container: refElement,
container: document.querySelector('#waveform'),
// The color can be either a simple CSS color or a Canvas gradient
waveColor: '#ffa492',
progressColor: 'hsla(12,100%,43%,0.5)',
cursorColor: '#fff',
// This parameter makes the waveform look like SoundCloud's player
barWidth: 1,
barHeight: 10,
backend: 'MediaElement',
plugins: [
// rectangles de zones
WaveSurfer.regions.create({
regionsMinLength: 2,
regions: [
{
start: 50,
end: 70,
loop: false,
color: 'hsla(400, 100%, 30%, 0.25)'
},
{
start: 150,
end: 200,
loop: false,
color: 'hsla(200, 50%, 70%, 0.25)',
minLength: 1
}
],
dragSelection: {
slop: 5
}
}),
// marque pages avec texte
WaveSurfer.markers.create({
markers: [
{
time: 0,
label: "intro",
color: '#ff990a'
},
{
time: 10,
label: "chronique 1",
color: '#ff990a'
},
{
time: 50,
label: "une pause musicale",
color: '#00ffcc',
position: 'top'
},
{
time: 70,
label: "le sujet principal",
color: '#00ffcc',
position: 'top'
},
{
time: 200,
label: "la fin",
color: '#00ffcc',
position: 'top'
},
]
})
]
};
console.log('url', url);
silverSurfer = WaveSurfer.create(waveoptions)
silverSurfer.load(url)
console.log('silverSurfer', silverSurfer);
});

7
js/markers.min.js vendored Normal file
View File

@ -0,0 +1,7 @@
/*!
* wavesurfer.js markers plugin 5.1.0 (2021-06-20)
* https://wavesurfer-js.org
* @license BSD-3-Clause
*/
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("WaveSurfer",[],t):"object"==typeof exports?exports.WaveSurfer=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.markers=t())}(this,(function(){return(()=>{"use strict";var e={188:(e,t)=>{function r(e,t){for(var r=0;r<t.length;r++){var i=t[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var i=function(){function e(t,r){var i=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.params=t,this.wavesurfer=r,this.util=r.util,this.style=this.util.style,this.markerWidth=11,this.markerHeight=22,this._onResize=function(){i._updateMarkerPositions()},this._onBackendCreated=function(){i.wrapper=i.wavesurfer.drawer.wrapper,i.params.markers&&i.params.markers.forEach((function(e){return i.add(e)})),window.addEventListener("resize",i._onResize,!0),window.addEventListener("orientationchange",i._onResize,!0),i.wavesurfer.on("zoom",i._onResize)},this.markers=[],this._onReady=function(){i.wrapper=i.wavesurfer.drawer.wrapper,i._updateMarkerPositions()}}var t,i,a;return t=e,a=[{key:"create",value:function(t){return{name:"markers",deferInit:!(!t||!t.deferInit)&&t.deferInit,params:t,staticProps:{addMarker:function(e){return this.initialisedPluginList.markers||this.initPlugin("markers"),this.markers.add(e)},clearMarkers:function(){this.markers&&this.markers.clear()}},instance:e}}}],(i=[{key:"init",value:function(){this.wavesurfer.isReady?(this._onBackendCreated(),this._onReady()):(this.wavesurfer.once("ready",this._onReady),this.wavesurfer.once("backend-created",this._onBackendCreated))}},{key:"destroy",value:function(){this.wavesurfer.un("ready",this._onReady),this.wavesurfer.un("backend-created",this._onBackendCreated),this.wavesurfer.un("zoom",this._onResize),window.removeEventListener("resize",this._onResize,!0),window.removeEventListener("orientationchange",this._onResize,!0),this.clear()}},{key:"add",value:function(e){var t={time:e.time,label:e.label,color:e.color||"#D8D8D8",position:e.position||"bottom"};return e.markerElement&&(this.markerWidth=e.markerElement.width,this.markerHeight=e.markerElement.height),t.el=this._createMarkerElement(t,e.markerElement),this.wrapper.appendChild(t.el),this.markers.push(t),this._updateMarkerPositions(),t}},{key:"remove",value:function(e){var t=this.markers[e];t&&(this.wrapper.removeChild(t.el),this.markers.splice(e,1))}},{key:"_createPointerSVG",value:function(e,t){var r="http://www.w3.org/2000/svg",i=document.createElementNS(r,"svg"),a=document.createElementNS(r,"polygon");return i.setAttribute("viewBox","0 0 40 80"),a.setAttribute("id","polygon"),a.setAttribute("stroke","#979797"),a.setAttribute("fill",e),a.setAttribute("points","20 0 40 30 40 80 0 80 0 30"),"top"==t&&a.setAttribute("transform","rotate(180, 20 40)"),i.appendChild(a),this.style(i,{width:this.markerWidth+"px",height:this.markerHeight+"px","min-width":this.markerWidth+"px","margin-right":"5px","z-index":4}),i}},{key:"_createMarkerElement",value:function(e,t){var r=this,i=e.label,a=e.time,n=document.createElement("marker");n.className="wavesurfer-marker",this.style(n,{position:"absolute",height:"100%",display:"flex",overflow:"hidden","flex-direction":"top"==e.position?"column-reverse":"column"});var s=document.createElement("div");this.style(s,{"flex-grow":1,"margin-left":this.markerWidth/2-.5+"px",background:"black",width:"1px",opacity:.1}),n.appendChild(s);var o=document.createElement("div"),u=t||this._createPointerSVG(e.color,e.position);if(o.appendChild(u),i){var d=document.createElement("span");d.innerText=i,this.style(d,{"font-family":"monospace","font-size":"90%"}),o.appendChild(d)}return this.style(o,{display:"flex","align-items":"center",cursor:"pointer"}),n.appendChild(o),o.addEventListener("click",(function(t){t.stopPropagation(),r.wavesurfer.setCurrentTime(a),r.wavesurfer.fireEvent("marker-click",e,t)})),n}},{key:"_updateMarkerPositions",value:function(){for(var e=this.wavesurfer.getDuration(),t=0;t<this.markers.length;t++){var r=this.markers[t],i=this.wavesurfer.drawer.width/this.wavesurfer.params.pixelRatio,a=i*Math.min(r.time/e,1)-this.markerWidth/2;this.style(r.el,{left:a+"px","max-width":i-a+"px"})}}},{key:"clear",value:function(){for(;this.markers.length>0;)this.remove(0)}}])&&r(t.prototype,i),a&&r(t,a),e}();t.default=i,e.exports=t.default}},t={};return function r(i){var a=t[i];if(void 0!==a)return a.exports;var n=t[i]={exports:{}};return e[i](n,n.exports,r),n.exports}(188)})()}));
//# sourceMappingURL=wavesurfer.markers.min.js.map

7
js/regions.min.js vendored Normal file

File diff suppressed because one or more lines are too long

6463
js/wavesurfer.js Normal file

File diff suppressed because it is too large Load Diff

1
js/wavesurfer.js.map Normal file

File diff suppressed because one or more lines are too long

2367
js/wavesurfer.min.js vendored Executable file → Normal file

File diff suppressed because one or more lines are too long

1
js/wavesurfer.min.js.map Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,49 @@
body{
margin: 5em;
background: #ccc;
}
.clickable{
cursor:pointer;
color: white;
}
.clickable:hover{
background: #222
}
li.clickable{
padding: 1em;
}
button{
padding: 1em;
border-radius: 10em;
min-width: 2em;
min-height: 2em;
background: #222;
border-width: 0;
}
#media_player{
margin: 2em auto;
border: solid 1px grey;
padding: 2em;
}
meter{
background: black;
}
audio{
width: 100%;
}
#wave_box{
border-radius: 0.25em;
background: #222;
padding: 1em;
margin-bottom: 1em;
}
marker span{
color: white;
}
ul{
background: #111;
}