Use Cases (Atualizado: 02/06/2026)

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.

Como Construir um Player de Áudio com Claude Code

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">&#9834;</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">&#9198;</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 ? '&#9208;' : '&#9654;'}
          </button>
          <button onClick={playNext} className="text-2xl dark:text-white hover:text-blue-600">&#9197;</button>
        </div>

        {/* Volume */}
        <div className="flex items-center gap-2 mt-4">
          <span className="text-sm dark:text-gray-400">&#128266;</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 ? '&#9834;' : 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.

CamadaResponsabilidadeNota de produção
DadosTítulo, autor, URL, duração, capa, transcriçãoValidar que a playlist não está vazia
ReproduçãoHTMLAudioElement para play, pause, seek e volumeOuvir loadedmetadata, timeupdate, ended e erros
VisualizaçãoWeb Audio API para waveform ou espectroExigir CORS correto e AudioContext.resume() após ação do usuário
InterfaceBotões, sliders, lista, tempo atualAdicionar labels, foco visível e navegação por teclado
ProdutoAnalytics, progresso salvo, CTA, regras premiumMedir 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.

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.

#Claude Code #audio #Web Audio API #React #player
Grátis

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.

Masa

Sobre o autor

Masa

Engenheiro focado em workflows práticos com Claude Code.