commit 30e531e1e7495fbef59fb9d07576034e6a5da92f
parent 32011eee9916e8c028a7285b4191c43bed1329ed
Author: Pablo Murad <pblmrd@gmail.com>
Date: Fri, 1 May 2026 12:22:44 -0300
metadata
Diffstat:
2 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
@@ -103,13 +103,14 @@ The API returns **503** only when the in-memory track pool is **empty** (`trackC
4. Re-run `curl` until `tracksReady` is `true` and `trackCount` > 0.
-### Console: `content.js` and TensorFlow / WebGL kernel messages
+### Console: `content.js`, `classifier.js`, and TensorFlow / WebGL kernel messages
-Messages like **“The kernel '…' for backend 'webgl' is already registered”** in **`content.js`** come from a **browser extension** (not from MyMusics). To verify the site without that noise, use a **private/incognito window** with extensions disabled for that window, or temporarily disable extensions.
+Messages such as **“The kernel '…' for backend 'cpu' / 'webgl' is already registered”** (often under **`content.js`**) or **“Platform browser has already been set”** (under **`classifier.js`**) come from **browser extensions** that bundle TensorFlow.js — **not from MyMusics** (this repo does not ship TensorFlow). To confirm, open a **private/incognito** window with extensions disabled for that session, or turn extensions off temporarily.
## Playback notes
- The browser loads audio directly from `https://archive.org/download/...` URLs. First play may be slow while the Archive serves the file from inside large ZIPs.
+- **HTTP 503 (or other failures) on the MP3 URL** come from **Internet Archive** (overload, ZIP member extraction, etc.), not from this app’s API. The player may auto-skip to another random track a few times; use **Next** if streaming keeps failing.
- This is **not** DRM; users can still capture network traffic or use devtools.
## Scripts
diff --git a/src/App.tsx b/src/App.tsx
@@ -22,8 +22,11 @@ type HealthBody = {
trackCount?: number;
};
+const MAX_ARCHIVE_STREAM_ERRORS = 3;
+
export default function App() {
const audioRef = useRef<HTMLAudioElement>(null);
+ const archiveStreamErrorsRef = useRef(0);
const [track, setTrack] = useState<TrackInfo | null>(null);
const [status, setStatus] = useState<string>("");
const [history, setHistory] = useState<TrackInfo[]>([]);
@@ -67,6 +70,29 @@ export default function App() {
}
}, [playUrl]);
+ const handleAudioPlaying = useCallback(() => {
+ archiveStreamErrorsRef.current = 0;
+ setStatus("");
+ }, []);
+
+ const handleAudioError = useCallback(() => {
+ archiveStreamErrorsRef.current += 1;
+ const n = archiveStreamErrorsRef.current;
+ if (n >= MAX_ARCHIVE_STREAM_ERRORS) {
+ setStatus(
+ "Internet Archive could not stream several tracks in a row (e.g. 503). Try Next or wait.",
+ );
+ return;
+ }
+ setStatus("This track is not available from the Archive right now; trying another…");
+ if (autoPlay) void loadNext();
+ }, [autoPlay, loadNext]);
+
+ const requestNextTrack = useCallback(() => {
+ archiveStreamErrorsRef.current = 0;
+ void loadNext();
+ }, [loadNext]);
+
useEffect(() => {
void (async () => {
try {
@@ -145,10 +171,12 @@ export default function App() {
controlsList="nodownload noplaybackrate"
preload="metadata"
onEnded={onEnded}
+ onPlaying={handleAudioPlaying}
+ onError={handleAudioError}
/>
<div className="actions">
- <button type="button" className="btn primary" onClick={() => void loadNext()}>
+ <button type="button" className="btn primary" onClick={() => void requestNextTrack()}>
Next
</button>
<label className="check">