Cara Membuat Audio Player dengan Claude Code
Pelajari cara membuat audio player menggunakan Claude Code. Dilengkapi contoh kode praktis dan panduan langkah demi langkah.
Membangun Audio Player dengan Claude Code
Ada banyak situasi yang membutuhkan custom audio player seperti layanan streaming musik, podcast, konten edukasi, dan lainnya. Dengan Claude Code, kamu bisa membangun player profesional yang dilengkapi tampilan waveform dan fungsionalitas playlist.
Implementasi Player Dasar
> Buat custom audio player.
> Dukung play/pause, seek bar, volume, dan perubahan kecepatan pemutaran.
> Implementasikan juga fungsionalitas playlist dan tampilan waveform.
// 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) {
// Jika lebih dari 3 detik, kembali ke awal
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" />
{/* Cover Art */}
<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>
{/* Informasi Track */}
<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>
{/* Seek Bar */}
<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>
{/* Kontrol */}
<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>
);
}
Tampilan Waveform dengan Web Audio API
Sebagai fitur lanjutan, tampilan waveform real-time menggunakan Web Audio API juga bisa diminta ke Claude Code. Dengan menggabungkan AudioContext dan AnalyserNode, waveform audio yang sedang diputar bisa digambar ke Canvas.
Artikel Terkait
Untuk implementasi video player, lihat Panduan Membangun Video Player, dan untuk dukungan responsif, lihat juga Responsive Design.
Untuk detail Web Audio API, lihat MDN (developer.mozilla.org/Web/API/Web_Audio_API).
PDF Gratis: Cheatsheet Claude Code dalam 5 Menit
Cukup masukkan emailmu dan kami akan langsung mengirim cheatsheet PDF A4 satu halaman.
Kami menjaga data pribadimu dengan aman dan tidak pernah mengirim spam.
Tentang Penulis
Masa
Engineer yang aktif menggunakan Claude Code. Mengelola claudecode-lab.com, media teknologi 10 bahasa dengan lebih dari 2.000 halaman.
Artikel Terkait
7 pemeriksaan sebelum menerbitkan artikel Claude Code multibahasa setiap hari
Checklist praktis agar artikel Claude Code multibahasa yang diterbitkan setiap hari tidak kehilangan locale, tidak merusak CTA, dan tidak meninggalkan halaman lama di production.
Apa itu Codex Automations? Membiarkan AI mengurus konten saat kamu tidur
Panduan praktis memakai Codex Automations untuk analytics, artikel, CTA, deploy, dan monetisasi.
Claude Code × GCP Cloud Functions Panduan Lengkap | Pengembangan Serverless Super Cepat
Optimalkan GCP Cloud Functions dengan Claude Code. Implementasikan trigger HTTP/Pub/Sub/Firestore, pengujian lokal, dan otomatisasi deployment dengan contoh kode nyata dari pengalaman Masa.