Tutoriel : boucler des extraits audio avec Transloadit & Uppy
Récemment, je me posais une question : lequel de nos Robots mérite un peu plus d’attention ? L’un de nos véritables héros méconnus, un fidèle cheval de bataille souvent négligé, est le Robot /audio/loop.
Aujourd’hui, nous mettons en lumière le Robot /audio/loop en créant un site web qui lit un extrait audio en boucle pendant une durée donnée. Pour nous aider, nous utiliserons aussi le puissant outil d’envoi de fichiers Uppy.

Nos Assembly Instructions
Avant d’entrer dans le vif du sujet de la création du site, passons en revue les Assembly Instructions que nous utiliserons pour mettre notre audio en boucle.
{
"steps": {
"encode": {
"robot": "/audio/encode",
"use": ":original"
},
"loop": {
"robot": "/audio/loop",
"use": "encode",
"duration": "${fields.duration}"
},
"export": {
"robot": "/s3/store",
"use": "loop",
"credentials": "S3_CREDENTIALS",
"result": true
}
}
}
Nous encodons d’abord le fichier audio afin de normaliser notre fichier de sortie au format MP3.
Ensuite, nous transmettons le fichier obtenu au Robot /audio/loop.
Lorsque nous envoyons les Assembly Instructions, le champ duration fournit le nombre de
secondes choisi par l’utilisateur, la valeur 60 étant présélectionnée dans le formulaire. Enfin,
stockons le résultat dans un bucket S3 afin de pouvoir présenter ce fichier à l’utilisateur. Si vous
préférez, vous pouvez aussi utiliser l’un des autres
services d’exportation avec lesquels nous sommes intégrés.
Remplacez S3_CREDENTIALS par le nom de
l’ensemble d’informations d’identification de Template que vous avez
enregistré ; ne collez pas de secrets S3 dans l’exemple.
Enregistrez ces Instructions en tant que Template et utilisez son identifiant dans le JavaScript ci-dessous. Le navigateur envoie la durée sous forme de champ, nous n’avons donc pas besoin d’une seconde copie des Instructions dans notre JavaScript. Ne placez jamais d’Auth Secret dans du code exécuté par le navigateur. Avant tout déploiement public, utilisez des signatures générées côté serveur et validez la durée demandée sur votre serveur ; la validation dans le navigateur ne suffit pas, à elle seule, à autoriser le traitement.
La structure HTML
Maintenant que nous avons nos Assembly Instructions, attaquons la structure. Nous allons commencer par ajouter un peu de HTML pour notre site web.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://releases.transloadit.com/uppy/v3.3.1/uppy.min.css" rel="stylesheet" />
<title>Audio Looper</title>
</head>
<body>
<div class="banner">
<a href="https://uppy.io/"
><img src="https://transloadit.com/assets/images/artwork/logos-uppy-default-glyph.svg" alt="Uppy" width="48" height="48"
/></a>
<span id="cross">x</span>
<a href="https://transloadit.com/"
><img src="https://transloadit.com/assets/images/artwork/logos-transloadit-default-glyph.svg" alt="Transloadit" width="48" height="48"
/></a>
</div>
<h1 class="title">Audio Looper</h1>
<div class="input-container">
<label for="duration">Duration:</label>
<input type="number" id="duration" name="duration" min="1" max="300" step="1" value="60" required />
</div>
<div id="dashboard"></div>
<p class="label">Only accepts audio</p>
<div class="result-container">
<audio id="player" controls>
<source id="result" type="audio/mpeg" />
Your browser does not support the audio element.
</audio>
</div>
<p id="status" role="status"></p>
</body>
</html>
Ce qui donne le résultat suivant :

Comme vous pouvez le voir, il s’agit d’un site web assez basique. Le style par défaut est toutefois un peu difficile à supporter, alors ajoutons une pincée de CSS pour embellir tout cela.
Entre deux balises <style>, ajoutez le CSS suivant :
.title {
text-align: center;
font-size: 2rem;
font-weight: 600;
margin-top: 2rem;
font-family: 'Courier New', Courier, monospace;
}
.label {
text-align: center;
font-size: 1rem;
font-weight: 100;
font-style: italic;
margin-top: 1rem;
font-family: 'Segoe UI', sans-serif;
}
.banner {
display: flex;
justify-content: center;
align-items: center;
gap: 1rem;
margin-top: 2rem;
}
.result-container {
display: flex;
justify-content: center;
margin-top: 2rem;
}
.input-container {
display: flex;
justify-content: center;
padding: 1rem;
font-family: 'Segoe UI', sans-serif;
}
input {
border: none;
border-bottom: 2px solid #bcbcbc;
text-align: end;
}
input:focus {
outline: 2px solid currentColor;
outline-offset: 2px;
}
#cross {
font-family: 'Courier New', monospace;
font-size: 2rem;
font-weight: 600;
}
#dashboard {
display: flex;
justify-content: center;
}
Voilà qui est bien plus agréable !

Le Dashboard Uppy
Maintenant que le HTML et le CSS sont en place, nous pouvons nous concentrer sur le Dashboard Uppy.
Après le HTML, ajoutez le JavaScript suivant dans une balise <script type="module"> :
import {
Uppy,
Dashboard,
Transloadit,
} from 'https://releases.transloadit.com/uppy/v3.3.1/uppy.min.mjs'
const durationInput = document.getElementById('duration')
const status = document.getElementById('status')
const uppy = new Uppy({
restrictions: {
maxNumberOfFiles: 1,
allowedFileTypes: ['audio/*'],
},
onBeforeUpload: () => durationInput.reportValidity(),
})
.use(Dashboard, {
inline: true,
target: '#dashboard',
})
.use(Transloadit, {
waitForEncoding: true,
getAssemblyOptions: () => ({
params: {
auth: { key: 'YOUR_AUTH_KEY' },
template_id: 'YOUR_TEMPLATE_ID',
},
fields: { duration: durationInput.valueAsNumber },
}),
})
uppy.on('transloadit:complete', (assembly) => {
const url = assembly.results.loop?.[0]?.ssl_url
if (typeof url !== 'string') {
status.textContent = 'No audio was returned. Please try again.'
return
}
const source = document.getElementById('result')
source.src = url
document.getElementById('player').load()
status.textContent = 'Your looped audio is ready.'
})
uppy.on('upload', () => {
status.textContent = 'Processing audio.'
})
uppy.on('error', () => {
status.textContent = 'Audio processing failed. Please try again.'
})
Ici, nous ajoutons les plugins Uppy Dashboard et
Transloadit, et nous définissons la div #dashboard
comme cible de notre composant Dashboard.
Nous transmettons également l’identifiant de notre Template au plugin Transloadit et
définissons l’option waitForEncoding sur true, afin de pouvoir extraire le fichier
résultat du JSON de l’Assembly, une fois que notre Assembly a terminé
l’encodage (plutôt qu’à la fin de l’envoi).
La version d’Uppy épinglée utilise getAssemblyOptions pour lire la durée actuelle au démarrage de l’envoi.
Le champ natif exige un nombre entier compris entre 1 et 300 secondes. Le gestionnaire de fin lit
l’URL du fichier stocké sous le Step producteur loop, et non sous le nom du Step export, et
gère l’absence de résultat sans lever d’exception.
Le résultat
Combinez le HTML, le CSS et le script de module, configurez votre propre Template, puis ouvrez la page depuis un serveur HTTP local. Les captures d’écran ci-dessus montrent le prototype d’origine ; le code présenté ici inclut la gestion mise à jour du champ de saisie et du résultat.
Lorsque vous envoyez un fichier audio et définissez la durée, vous devriez voir le fichier résultat dans l’élément audio de sortie, avec une durée égale à la valeur indiquée.
Nous espérons que cela vous a incité à jeter un nouveau regard sur le Robot /audio/loop, ainsi que sur le meilleur outil d’envoi de fichiers au monde. Si vous souhaitez recevoir nos prochains articles de blog (et d’autres actualités tech pertinentes !), inscrivez-vous à notre newsletter ci-dessous (English).
