Categories We Write About

Build an audiobook player with bookmarks

Creating an audiobook player with bookmarks requires combining audio playback functionality with a user interface that allows adding, viewing, and managing bookmarks at specific timestamps. Below is a detailed guide and sample implementation using JavaScript (React) and HTML5 audio API. This example covers:

  • Audio playback controls (play/pause, seek)

  • Displaying current time and duration

  • Adding bookmarks at the current playback position

  • Listing bookmarks and allowing the user to jump to a bookmarked position


Audiobook Player with Bookmarks — React Example

jsx
import React, { useState, useRef, useEffect } from "react"; function AudiobookPlayer({ audioSrc }) { const audioRef = useRef(null); const [isPlaying, setIsPlaying] = useState(false); const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); const [bookmarks, setBookmarks] = useState([]); useEffect(() => { const audio = audioRef.current; const onLoadedMetadata = () => { setDuration(audio.duration); }; const onTimeUpdate = () => { setCurrentTime(audio.currentTime); }; audio.addEventListener("loadedmetadata", onLoadedMetadata); audio.addEventListener("timeupdate", onTimeUpdate); return () => { audio.removeEventListener("loadedmetadata", onLoadedMetadata); audio.removeEventListener("timeupdate", onTimeUpdate); }; }, []); const togglePlay = () => { const audio = audioRef.current; if (isPlaying) { audio.pause(); } else { audio.play(); } setIsPlaying(!isPlaying); }; const handleSeek = (e) => { const time = Number(e.target.value); audioRef.current.currentTime = time; setCurrentTime(time); }; const addBookmark = () => { // Avoid duplicates and round to seconds const time = Math.floor(currentTime); if (!bookmarks.find((b) => b.time === time)) { setBookmarks([...bookmarks, { time, label: `Bookmark at ${formatTime(time)}` }]); } }; const jumpToBookmark = (time) => { audioRef.current.currentTime = time; setCurrentTime(time); }; const formatTime = (seconds) => { const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${mins}:${secs < 10 ? "0" : ""}${secs}`; }; return ( <div style={{ maxWidth: 400, margin: "auto", fontFamily: "Arial, sans-serif" }}> <audio ref={audioRef} src={audioSrc} preload="metadata" /> <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 10 }}> <button onClick={togglePlay} style={{ padding: "8px 12px" }}> {isPlaying ? "Pause" : "Play"} </button> <input type="range" min={0} max={duration} value={currentTime} onChange={handleSeek} style={{ flexGrow: 1 }} /> <div style={{ minWidth: 60, textAlign: "right" }}> {formatTime(currentTime)} / {formatTime(duration)} </div> </div> <button onClick={addBookmark} style={{ marginBottom: 15, padding: "6px 10px" }}> Add Bookmark </button> <div> <h4>Bookmarks</h4> {bookmarks.length === 0 && <p>No bookmarks yet.</p>} <ul style={{ paddingLeft: 20 }}> {bookmarks.map(({ time, label }, index) => ( <li key={index} style={{ marginBottom: 6 }}> <button onClick={() => jumpToBookmark(time)} style={{ background: "none", border: "none", color: "blue", cursor: "pointer", textDecoration: "underline", padding: 0, fontSize: "1em", }} title={`Jump to ${formatTime(time)}`} > {label} </button> </li> ))} </ul> </div> </div> ); } export default AudiobookPlayer;

Explanation

  • The <audio> element plays the audiobook file.

  • currentTime and duration states track playback progress.

  • A slider (input type="range") lets the user seek within the track.

  • Add Bookmark saves the current playback time rounded to seconds if it’s not already bookmarked.

  • Bookmarks appear in a list, clickable to jump directly to that time in the audio.

  • formatTime converts seconds into mm:ss for user-friendly display.


How to Use

  • Import and use the component passing an audiobook URL:

jsx
<AudiobookPlayer audioSrc="https://example.com/audiobook.mp3" />

If you want, I can also provide a vanilla JavaScript + HTML version or a React Native example. Let me know!

Share This Page:

Enter your email below to join The Palos Publishing Company Email List

We respect your email privacy

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Categories We Write About