Use Cases (Actualizado: 2/6/2026)

Como construir un reproductor de audio con Claude Code

Aprende a construir un reproductor de audio con Claude Code. Incluye ejemplos de codigo practicos y guia paso a paso.

Como construir un reproductor de audio con Claude Code

Construir un reproductor de audio con Claude Code

Hay muchas situaciones donde se necesita un reproductor de audio personalizado: servicios de streaming de musica, podcasts, contenido educativo, etc. Con Claude Code puedes construir un reproductor completo con visualizacion de forma de onda y funcionalidad de lista de reproduccion.

Implementacion del reproductor basico

> Crea un reproductor de audio personalizado.
> Compatible con reproduccion/pausa, barra de avance, volumen y cambio de velocidad de reproduccion.
> Implementa tambien la funcionalidad de lista de reproduccion y visualizacion 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) {
      // Si han pasado mas de 3 segundos, volver al inicio
      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" />

      {/* Caratula */}
      <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">&#9835;</div>
        )}
      </div>

      {/* Informacion de la pista */}
      <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 avance */}
        <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>

        {/* Volumen */}
        <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>

      {/* Lista de reproduccion */}
      <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 ? '&#9835;' : 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>
  );
}

Visualizacion de forma de onda con Web Audio API

Como funcionalidad avanzada, tambien puedes solicitar a Claude Code la visualizacion en tiempo real de la forma de onda usando Web Audio API. Combinando AudioContext y AnalyserNode, puedes dibujar la forma de onda del audio en reproduccion sobre un Canvas.

Articulos relacionados

Para la implementacion de un reproductor de video, consulta la guia de construccion de reproductor de video; para diseno responsive, consulta diseno responsive.

Para mas detalles sobre Web Audio API, consulta MDN (developer.mozilla.org/Web/API/Web_Audio_API).

Actualizacion 2026 para produccion: convertirlo en una interfaz de audio

Un reproductor de audio no es solo un boton de play. Es la interfaz que permite escuchar, pausar, volver atras, cambiar volumen, entender el progreso y decidir el siguiente paso. En un curso, podcast, newsletter premium o pagina de producto, el audio player tambien puede guardar avance, medir eventos, mostrar una muestra gratuita y llevar al usuario hacia una compra, una suscripcion o una consulta.

El componente React/TypeScript de arriba es una base ejecutable porque mantiene el HTMLAudioElement dentro de useRef y deja que React controle la interfaz: pista actual, estado de reproduccion, tiempo y volumen. Para copiarlo en un proyecto real, pasa un arreglo tracks no vacio, usa URLs de audio reales en src y renderiza el componente como cliente. A partir de ahi puedes sumar waveform, analitica, accesibilidad y CTA sin reescribir todo.

HTMLAudioElement frente a Web Audio API

HTMLAudioElement es el objeto del navegador que hay detras del elemento audio. Sirve para cargar, reproducir, pausar, cambiar volumen, leer duracion, mover la posicion y escuchar eventos de medios. Si el objetivo es reproducir una clase, una entrevista o una muestra de producto, empieza por aqui. La referencia oficial de MDN sobre el elemento audio cubre atributos como preload, fuentes y comportamiento de controles.

Web Audio API es una capa mas baja. Permite crear un grafo con AudioContext, MediaElementAudioSourceNode, AnalyserNode y GainNode para dibujar formas de onda, espectros, ecualizadores, fades y efectos. No reemplaza el boton de play ni la barra de progreso; normalmente se conecta al elemento de audio cuando necesitas analisis o visualizacion. Revisa la documentacion oficial de Web Audio API y la referencia de React para useRef antes de mezclar DOM, Canvas y estado.

CapaResponsabilidadNota de produccion
DatosTitulo, autor, URL, duracion, portada, transcripcionValidar que la playlist no este vacia
Motor de reproduccionHTMLAudioElement para play, pause, seek y volumenEscuchar loadedmetadata, timeupdate, ended y errores
VisualizacionWeb Audio API para waveform o espectroNecesita CORS correcto y AudioContext.resume() tras accion del usuario
InterfazBotones, sliders, lista, texto de progresoAgregar etiquetas, foco visible y soporte de teclado
ProductoAnalitica, progreso guardado, paywall, CTAMedir inicio, 50%, finalizacion, repeticion y clics

Casos reales de producto (use case)

Primer use case: contenido educativo. En cursos de idiomas, programacion o onboarding, el alumno necesita velocidad, retroceso de 10 segundos, capitulos, transcripcion y continuar donde se quedo. La utilidad no esta en una animacion llamativa, sino en poder repasar sin friccion.

Segundo use case: podcast y medios editoriales. Un reproductor propio puede mostrar portada, capitulos, episodios relacionados, registro a newsletter y oferta de membresia. Cuando termina una pieza gratuita, el siguiente paso deberia ser claro: otro episodio, suscripcion, descarga o pagina de training.

Tercer use case: tienda de creadores. Musicos, locutores, autores de efectos y creadores de cursos pueden ofrecer una muestra corta antes de vender en Gumroad o en una tienda propia. Escuchar el producto reduce la duda antes del pago.

Cuarto use case: formacion interna. Guiones de ventas, ejemplos de soporte, pronunciacion y compliance suelen funcionar mejor como listas cortas de audio. Aqui importan mas la persistencia de progreso, los mensajes de error y los informes para administradores que el aspecto visual.

Pitfalls y fallos concretos

El pitfall mas comun es confiar en la reproduccion automatica. Los navegadores modernos pueden rechazar audio.play() si no hay una accion del usuario. Como play() devuelve una Promise, el codigo de produccion debe capturar el rechazo y mostrar una instruccion clara.

Otro fallo es usar duration antes de que exista. Antes de loadedmetadata, la duracion puede ser NaN o cero. La barra de progreso debe tener un valor maximo protegido y el texto de tiempo no deberia prometer una duracion definitiva demasiado pronto.

La visualizacion tambien falla por CORS. Si el audio esta en un CDN o dominio externo, Web Audio API requiere cabeceras adecuadas para que AnalyserNode pueda leer la senal. Prueba siempre con el dominio final, no solo con archivos locales.

En React aparece otro riesgo: cambiar de pista y llamar a play() con un setTimeout puede parecer suficiente, pero en redes lentas el archivo aun no esta listo. Para un producto, espera canplay o loadedmetadata antes de iniciar la reproduccion.

Enlaces, documentacion y monetization CTA

Para profundizar en el estado de React, lee Claude Code React development. Para formas de onda y analisis, sigue con Claude Code Web Audio API. Para botones accesibles, teclado y lectores de pantalla, revisa Claude Code accessibility.

Si el audio forma parte de un curso, podcast premium o pagina de venta, define la monetization CTA desde el inicio. Un flujo practico es: muestra gratuita, registro por email, producto de pago y despues una oferta de consultation para equipos que necesitan implementarlo en un repositorio real. ClaudeCodeLab puede ayudar a ordenar reglas de Claude Code, CLAUDE.md, analitica y revisiones tecnicas desde la pagina de training / consultation.

#Claude Code #audio #Web Audio API #React #player
Gratis

PDF gratis: cheatsheet de Claude Code

Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.

Cuidamos tus datos y no enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero enfocado en workflows prácticos con Claude Code.