Como Construir um Player de Áudio com Claude Code
Aprenda a construir um player de áudio usando o Claude Code. Inclui exemplos práticos de código e orientação passo a passo.
Construindo um Player de Áudio com Claude Code
Existem muitos cenários onde um player de áudio personalizado é necessário - serviços de streaming de música, podcasts, conteúdo educacional e mais. Com o Claude Code, você pode construir um player completo com exibição de forma de onda e funcionalidade de playlist.
Implementação do Player Básico
> Crie um player de áudio personalizado.
> Com reprodução/pausa, barra de busca, volume e alteração de velocidade de reprodução.
> Implemente também função de playlist e exibição de forma de onda.
// src/components/AudioPlayer.tsx
'use client';
import { useRef, useState, useEffect } from 'react';
interface Track {
id: string;
title: string;
artist: string;
src: string;
duration: number;
coverArt?: string;
}
interface AudioPlayerProps {
tracks: Track[];
initialTrackIndex?: number;
}
export function AudioPlayer({ tracks, initialTrackIndex = 0 }: AudioPlayerProps) {
const audioRef = useRef<HTMLAudioElement>(null);
const [currentTrackIndex, setCurrentTrackIndex] = useState(initialTrackIndex);
const [isPlaying, setIsPlaying] = useState(false);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0);
const [volume, setVolume] = useState(0.8);
const currentTrack = tracks[currentTrackIndex];
useEffect(() => {
const audio = audioRef.current;
if (!audio) return;
const onTimeUpdate = () => setCurrentTime(audio.currentTime);
const onLoadedMetadata = () => setDuration(audio.duration);
const onEnded = () => playNext();
audio.addEventListener('timeupdate', onTimeUpdate);
audio.addEventListener('loadedmetadata', onLoadedMetadata);
audio.addEventListener('ended', onEnded);
return () => {
audio.removeEventListener('timeupdate', onTimeUpdate);
audio.removeEventListener('loadedmetadata', onLoadedMetadata);
audio.removeEventListener('ended', onEnded);
};
}, [currentTrackIndex]);
const togglePlay = () => {
const audio = audioRef.current;
if (!audio) return;
if (audio.paused) {
audio.play();
setIsPlaying(true);
} else {
audio.pause();
setIsPlaying(false);
}
};
const playNext = () => {
const nextIndex = (currentTrackIndex + 1) % tracks.length;
setCurrentTrackIndex(nextIndex);
setTimeout(() => {
audioRef.current?.play();
setIsPlaying(true);
}, 100);
};
const playPrevious = () => {
if (currentTime > 3) {
// Se mais de 3 segundos, volta ao início
audioRef.current!.currentTime = 0;
} else {
const prevIndex = (currentTrackIndex - 1 + tracks.length) % tracks.length;
setCurrentTrackIndex(prevIndex);
setTimeout(() => {
audioRef.current?.play();
setIsPlaying(true);
}, 100);
}
};
const formatTime = (sec: number) => {
const m = Math.floor(sec / 60);
const s = Math.floor(sec % 60);
return `${m}:${s.toString().padStart(2, '0')}`;
};
return (
<div className="bg-white dark:bg-gray-800 rounded-2xl shadow-lg overflow-hidden max-w-md mx-auto">
<audio ref={audioRef} src={currentTrack.src} preload="metadata" />
{/* Capa do álbum */}
<div className="aspect-square bg-gray-200 dark:bg-gray-700 relative">
{currentTrack.coverArt ? (
<img src={currentTrack.coverArt} alt={currentTrack.title} className="w-full h-full object-cover" />
) : (
<div className="w-full h-full flex items-center justify-center text-6xl text-gray-400">♪</div>
)}
</div>
{/* Informações da faixa */}
<div className="p-6">
<h3 className="text-lg font-bold dark:text-white truncate">{currentTrack.title}</h3>
<p className="text-gray-500 dark:text-gray-400 text-sm">{currentTrack.artist}</p>
{/* Barra de busca */}
<div className="mt-4">
<input
type="range"
min={0}
max={duration || 0}
value={currentTime}
onChange={(e) => {
const time = Number(e.target.value);
audioRef.current!.currentTime = time;
setCurrentTime(time);
}}
className="w-full h-1 accent-blue-600"
/>
<div className="flex justify-between text-xs text-gray-400 mt-1">
<span>{formatTime(currentTime)}</span>
<span>{formatTime(duration)}</span>
</div>
</div>
{/* Controles */}
<div className="flex items-center justify-center gap-6 mt-4">
<button onClick={playPrevious} className="text-2xl dark:text-white hover:text-blue-600">⏮</button>
<button
onClick={togglePlay}
className="w-14 h-14 rounded-full bg-blue-600 text-white text-2xl flex items-center justify-center hover:bg-blue-700"
>
{isPlaying ? '⏸' : '▶'}
</button>
<button onClick={playNext} className="text-2xl dark:text-white hover:text-blue-600">⏭</button>
</div>
{/* Volume */}
<div className="flex items-center gap-2 mt-4">
<span className="text-sm dark:text-gray-400">🔊</span>
<input
type="range"
min={0}
max={1}
step={0.05}
value={volume}
onChange={(e) => {
const vol = Number(e.target.value);
audioRef.current!.volume = vol;
setVolume(vol);
}}
className="flex-1 h-1 accent-blue-600"
/>
</div>
</div>
{/* Playlist */}
<div className="border-t dark:border-gray-700 max-h-60 overflow-y-auto">
{tracks.map((track, index) => (
<button
key={track.id}
onClick={() => {
setCurrentTrackIndex(index);
setTimeout(() => { audioRef.current?.play(); setIsPlaying(true); }, 100);
}}
className={`w-full flex items-center gap-3 p-3 text-left hover:bg-gray-50 dark:hover:bg-gray-700 ${
index === currentTrackIndex ? 'bg-blue-50 dark:bg-blue-900/30' : ''
}`}
>
<span className="text-xs text-gray-400 w-6 text-right">
{index === currentTrackIndex && isPlaying ? '♪' : index + 1}
</span>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium dark:text-white truncate">{track.title}</p>
<p className="text-xs text-gray-500 truncate">{track.artist}</p>
</div>
<span className="text-xs text-gray-400">{formatTime(track.duration)}</span>
</button>
))}
</div>
</div>
);
}
Exibição de Forma de Onda com Web Audio API
Como funcionalidade avançada, você também pode pedir ao Claude Code a exibição em tempo real da forma de onda usando a Web Audio API. Combinando AudioContext e AnalyserNode, é possível desenhar a forma de onda do áudio em reprodução em um Canvas.
Artigos Relacionados
Para implementação de player de vídeo, consulte o guia de construção de player de vídeo. Para adaptação responsiva, consulte design responsivo.
Para detalhes sobre a Web Audio API, consulte a MDN (developer.mozilla.org/Web/API/Web_Audio_API).
Upgrade de produção em 2026: transformar reprodução em UI de áudio
Um player de áudio não é apenas um botão de play. Ele mostra ao usuário o que está tocando, quanto falta, como voltar alguns segundos, como ajustar volume e qual deve ser o próximo passo. Em cursos, podcasts, bibliotecas de mídia e páginas de venda, o audio player também precisa salvar progresso, lidar com erros, respeitar acessibilidade, enviar eventos de analytics e conduzir o usuário para inscrição, compra ou consultation.
O componente React/TypeScript acima é uma base executável: o HTMLAudioElement fica guardado em useRef, enquanto o React controla faixa atual, estado de reprodução, tempo e volume. Para usar em um projeto real, passe uma lista tracks não vazia, use URLs de áudio reais em src e renderize o componente no cliente. Depois disso, fica mais simples adicionar waveform, progresso de curso, paywall e CTA sem reescrever a estrutura.
HTMLAudioElement ou Web Audio API
HTMLAudioElement é o objeto do navegador por trás do elemento audio. Ele cuida de carregamento, decodificação, play, pause, volume, posição atual, duração, metadados e eventos de mídia. Para aula, episódio de podcast ou amostra de produto, comece por ele. A referência oficial da MDN para o elemento audio ajuda a revisar atributos como preload, fontes e controles.
A Web Audio API é uma camada mais baixa. Com AudioContext, MediaElementAudioSourceNode, AnalyserNode e GainNode, você cria um grafo para forma de onda, espectro, equalizador, fades e interfaces reativas ao som. Ela não substitui os controles de reprodução; ela complementa o player quando você precisa de análise ou efeitos. Consulte a documentação da Web Audio API e a referência do React para useRef.
| Camada | Responsabilidade | Nota de produção |
|---|---|---|
| Dados | Título, autor, URL, duração, capa, transcrição | Validar que a playlist não está vazia |
| Reprodução | HTMLAudioElement para play, pause, seek e volume | Ouvir loadedmetadata, timeupdate, ended e erros |
| Visualização | Web Audio API para waveform ou espectro | Exigir CORS correto e AudioContext.resume() após ação do usuário |
| Interface | Botões, sliders, lista, tempo atual | Adicionar labels, foco visível e navegação por teclado |
| Produto | Analytics, progresso salvo, CTA, regras premium | Medir início, 50%, conclusão, replay e clique |
Use case reais para aprendizado e mídia
Primeiro use case: conteúdo educacional. Em cursos de idioma, programação ou onboarding, o aluno precisa controlar velocidade, voltar 10 segundos, marcar capítulos, acompanhar transcrição e retomar de onde parou. A utilidade está em facilitar revisão, não em mostrar animação decorativa.
Segundo use case: podcast e mídia editorial. Um player próprio pode mostrar capa, capítulos, episódios relacionados, cadastro em newsletter e oferta de assinatura. Ao terminar um áudio gratuito, o próximo passo deve ser claro: outro episódio, assinatura, download ou página de training.
Terceiro use case: loja de criadores. Músicos, locutores, designers de som e criadores de cursos podem oferecer uma amostra curta antes da compra. Uma waveform simples e um link para Gumroad ou checkout reduzem a dúvida do comprador.
Quarto use case: treinamento interno. Scripts de vendas, exemplos de suporte, pronúncia e compliance funcionam bem como filas curtas de áudio. Nesse contexto, persistência de progresso, mensagens de erro e relatórios administrativos valem mais que efeitos visuais.
Pitfalls e falhas concretas
O pitfall mais comum é confiar em autoplay. Navegadores modernos podem rejeitar audio.play() quando não houve clique ou toque do usuário. Como play() retorna uma Promise, código de produção deve capturar rejeições e mostrar uma instrução clara.
Outra falha é usar duration cedo demais. Antes de loadedmetadata, a duração pode ser NaN ou zero. A barra de progresso precisa de valor máximo protegido e o texto de tempo deve aceitar um estado de carregamento.
Waveform também falha por CORS. Se o áudio vem de CDN ou domínio externo, o servidor precisa enviar cabeçalhos corretos para que a Web Audio API analise o sinal. Teste sempre no domínio final, não apenas em localhost.
Em React, trocar faixa e chamar play() com setTimeout pode funcionar na demo, mas falhar em rede lenta. Em produção, espere canplay ou loadedmetadata antes de iniciar a próxima faixa.
Links, documentação e monetization CTA
Para estado e componentes React, leia Claude Code React development. Para análise de áudio e waveform, siga para Claude Code Web Audio API. Para botões acessíveis, teclado e leitores de tela, use Claude Code accessibility.
Se o áudio faz parte de curso, podcast pago ou página de venda, defina a monetization CTA desde o início. Um fluxo prático é: amostra gratuita, cadastro por e-mail, produto pago e depois consultation para times que precisam implementar em um repositório real. A ClaudeCodeLab pode organizar regras de Claude Code, CLAUDE.md, eventos de analytics e revisão técnica na página de training / consultation.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Workflow Obsidian para CLAUDE.md com Claude Code
Transforme notas de trabalho do Obsidian em notas operacionais CLAUDE.md para preservar contexto.
Claude Code Revenue CTA Routing: artigos para PDF, Gumroad e consultoria
Um fluxo com Claude Code para levar leitores ao PDF grátis, Gumroad ou consultoria conforme intenção.
Regras de handoff para equipes com Claude Code: evidências, permissões, rollback e receita
Formato prático para entregar trabalho do Claude Code com prova, permissões, rollback, PDF grátis, Gumroad e consultoria.