Tutorial: repetir clipes de áudio em loop com Transloadit & Uppy
Recentemente, fiquei me perguntando quais dos nossos Robots merecem um pouco mais de atenção. Um dos nossos verdadeiros heróis anônimos, uma ferramenta confiável para o trabalho pesado que costuma ser esquecida, é o Robot /audio/loop.
Hoje, vamos colocar em destaque o Robot /audio/loop, criando um site que repete um clipe de áudio em loop por uma duração definida. Para ajudar nisso, também vamos aproveitar a poderosa ferramenta de upload de arquivos Uppy.

Nossas Assembly Instructions
Antes de entrarmos nos detalhes da criação do site, vamos analisar as Assembly Instructions que usaremos para repetir nosso áudio em loop.
{
"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
}
}
}
Primeiro, codificamos o arquivo de áudio para padronizar nosso arquivo de saída em MP3. Em seguida,
passamos esse arquivo resultante para o Robot /audio/loop.
Quando enviamos as Assembly Instructions, o campo duration fornece o número
de segundos escolhido pelo usuário, com 60 selecionado inicialmente no formulário. Por fim, vamos
armazenar o resultado em um bucket S3 para podermos apresentar esse arquivo ao usuário. Se preferir,
você também pode usar um dos outros
serviços de exportação com os quais temos integração.
Substitua S3_CREDENTIALS pelo nome das suas
Credenciais de Template salvas; não cole segredos do S3 no exemplo.
Salve essas Instructions como um Template e use o ID dele no JavaScript abaixo. O navegador envia a duração como um campo, então não precisamos de uma segunda cópia das Instructions no nosso JavaScript. Nunca coloque um Auth Secret no código do navegador. Antes de colocar o site no ar publicamente, use assinaturas geradas no servidor e valide a duração solicitada no seu servidor; a validação no navegador, por si só, não autoriza o processamento.
A estrutura básica em HTML
Agora que temos nossas Assembly Instructions, vamos começar pela estrutura básica. Começaremos adicionando um pouco de HTML ao nosso site.
<!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>
O resultado fica assim:

Como você pode ver, é um site bem básico. Mas o estilo padrão é um pouco difícil de engolir, então vamos adicionar só uma pitada de CSS para deixar tudo mais bonito.
Dentro de um par de tags <style>, adicione o seguinte CSS:
.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;
}
Agora sim, ficou muito melhor!

O Dashboard do Uppy
Agora que o HTML e o CSS estão prontos, podemos voltar nossa atenção para o dashboard do Uppy.
Depois do HTML, adicione o seguinte JavaScript dentro de uma tag <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.'
})
Aqui, estamos adicionando os plugins Dashboard e
Transloadit do Uppy e definindo a div #dashboard
como destino do nosso componente de dashboard.
Também passamos o ID do nosso Template para o plugin Transloadit e definimos a
opção waitForEncoding como true, para podermos extrair o arquivo de
resultado do JSON da Assembly depois que nossa Assembly terminar a
codificação (e não quando nosso upload for concluído).
A versão fixada do Uppy usa getAssemblyOptions para ler a duração atual quando o upload
começa. O input nativo exige um número inteiro entre 1 e 300 segundos. O handler de conclusão lê a
URL do arquivo armazenado sob o Step produtor loop, e não sob o nome do Step
export, e trata a ausência de um resultado sem lançar exceção.
O resultado
Combine o HTML, o CSS e o script de módulo, configure seu próprio Template e abra a página a partir de um servidor HTTP local. As capturas de tela acima mostram o protótipo original; o código aqui inclui o tratamento atualizado do input e do resultado.
Ao fazer upload de um arquivo de áudio e definir a duração, você deve ver o arquivo de resultado no elemento de áudio de saída, com a duração definida no valor especificado.
Esperamos que isso tenha incentivado você a dar outra olhada no Robot /audio/loop, assim como no melhor uploader de arquivos do mundo. Se quiser receber avisos sobre futuras publicações do blog (e outras notícias de tecnologia relevantes!), assine nossa newsletter abaixo (English).
