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.
Artigos relacionados
Web Audio API com Claude Code: onda, gravação e medidor de volume
Implemente Web Audio API com Claude Code: onda, gravação, medidor, cleanup e testes em React/TypeScript.
Player de vídeo em React: legendas, velocidade e métricas de visualização
Crie um player de vídeo para cursos e mídia com o Claude Code: reprodução, legendas, acessibilidade e métricas, com código React real.
Guia completo de CORS com Claude Code: APIs cross-origin seguras
Configure CORS com Claude Code: preflight, credentials, allowlist de origin, comandos de teste e prompts de revisão.
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.