fix(musik): perbaiki timing dan rounding pada seek slider
- Gunakan durasi dari database sebagai acuan utama (bukan dari audio metadata) - Ganti Math.floor dengan Math.round untuk smoothing currentTime - Tambahkan validasi seek time: Math.min(Math.max(0, v), duration) - Tambahkan debug logging untuk tracking seek behavior - Hapus override duration di onLoadedMetadata untuk menghindari konflik Root cause: - Duration dari database (string 'MM:SS' → seconds) berbeda dengan audio.duration (float) - Math.floor menyebabkan lompatan kasar dan kehilangan presisi - onLoadedMetadata override duration dengan audio.duration yang tidak exact Fix: - Database duration = source of truth - Math.round untuk smoothing tanpa kehilangan presisi - Validasi bounds untuk mencegah seek negatif atau melebihi durasi Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -5,10 +5,14 @@ export function seekTo(
|
|||||||
) {
|
) {
|
||||||
if (!audioRef.current) return;
|
if (!audioRef.current) return;
|
||||||
|
|
||||||
|
// Set waktu audio
|
||||||
audioRef.current.currentTime = time;
|
audioRef.current.currentTime = time;
|
||||||
|
|
||||||
// Update state jika provided
|
// Update state jika provided
|
||||||
if (setCurrentTime) {
|
if (setCurrentTime) {
|
||||||
setCurrentTime(time);
|
setCurrentTime(Math.round(time));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug log (bisa dihapus nanti)
|
||||||
|
console.log('[seekTo] Seek to:', time, 'seconds');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ const MusicPlayer = () => {
|
|||||||
// Update duration when song changes
|
// Update duration when song changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentSong && audioRef.current) {
|
if (currentSong && audioRef.current) {
|
||||||
|
// Gunakan durasi dari database sebagai acuan utama
|
||||||
const durationParts = currentSong.durasi.split(':');
|
const durationParts = currentSong.durasi.split(':');
|
||||||
const durationInSeconds = parseInt(durationParts[0]) * 60 + parseInt(durationParts[1]);
|
const durationInSeconds = parseInt(durationParts[0]) * 60 + parseInt(durationParts[1]);
|
||||||
setDuration(durationInSeconds);
|
setDuration(durationInSeconds);
|
||||||
@@ -199,12 +200,22 @@ const MusicPlayer = () => {
|
|||||||
src={currentSong.audioFile.link}
|
src={currentSong.audioFile.link}
|
||||||
muted={isMuted}
|
muted={isMuted}
|
||||||
onLoadedMetadata={() => {
|
onLoadedMetadata={() => {
|
||||||
if (!audioRef.current) return;
|
// Jangan override duration dari database
|
||||||
setDuration(Math.floor(audioRef.current.duration));
|
// Audio element duration bisa berbeda beberapa ms
|
||||||
|
if (audioRef.current) {
|
||||||
|
audioRef.current.currentTime = 0;
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onTimeUpdate={() => {
|
onTimeUpdate={() => {
|
||||||
if (!audioRef.current || isSeeking) return;
|
if (!audioRef.current || isSeeking) return;
|
||||||
setCurrentTime(Math.floor(audioRef.current.currentTime));
|
// Gunakan pembulatan yang lebih smooth
|
||||||
|
const time = audioRef.current.currentTime;
|
||||||
|
const roundedTime = Math.round(time);
|
||||||
|
// Debug: log jika ada perbedaan besar antara time dan state
|
||||||
|
if (Math.abs(time - roundedTime) > 0.5) {
|
||||||
|
console.log('[onTimeUpdate] Time:', time, 'Rounded:', roundedTime);
|
||||||
|
}
|
||||||
|
setCurrentTime(roundedTime);
|
||||||
}}
|
}}
|
||||||
onEnded={handleSongEnd}
|
onEnded={handleSongEnd}
|
||||||
/>
|
/>
|
||||||
@@ -269,7 +280,10 @@ const MusicPlayer = () => {
|
|||||||
}}
|
}}
|
||||||
onChangeEnd={(v) => {
|
onChangeEnd={(v) => {
|
||||||
setIsSeeking(false);
|
setIsSeeking(false);
|
||||||
seekTo(audioRef, v, setCurrentTime);
|
// Validasi: jangan seek melebihi durasi
|
||||||
|
const seekTime = Math.min(Math.max(0, v), duration);
|
||||||
|
seekTo(audioRef, seekTime, setCurrentTime);
|
||||||
|
console.log('[Slider Atas] Seek end:', seekTime, 'Duration:', duration);
|
||||||
}}
|
}}
|
||||||
color="#0B4F78"
|
color="#0B4F78"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -411,7 +425,10 @@ const MusicPlayer = () => {
|
|||||||
}}
|
}}
|
||||||
onChangeEnd={(v) => {
|
onChangeEnd={(v) => {
|
||||||
setIsSeeking(false);
|
setIsSeeking(false);
|
||||||
seekTo(audioRef, v); // commit - update audio player
|
// Validasi: jangan seek melebihi durasi
|
||||||
|
const seekTime = Math.min(Math.max(0, v), duration);
|
||||||
|
seekTo(audioRef, seekTime, setCurrentTime);
|
||||||
|
console.log('[Slider Bawah] Seek end:', seekTime, 'Duration:', duration);
|
||||||
}}
|
}}
|
||||||
color="#0B4F78"
|
color="#0B4F78"
|
||||||
size="xs"
|
size="xs"
|
||||||
|
|||||||
Reference in New Issue
Block a user