67c701f85a9a76fe0d0cccdeb6df993e3661fdaa
- Volume propagé en direct sur l'élément audio (le slider ne faisait que persister) ; volume 0 respecté (?? 1) ; slider masqué sur iOS (can_set_volume) ; mute synchronisé store/élément, persistant entre pistes - Race condition loadedmetadata, USER_PROGRESS borné à 200 entrées, erreurs radio affichées avec bouton Réessayer - Mobile : barre de progression avec zone tactile 44 px (tap + scrub au doigt), boutons 48 px, contrôles wrap, listes paginées 50×50 + content-visibility - PWA : manifest + icônes 192/512 (any+maskable), service worker manuel (shell + pochettes, streams exclus), Media Session API (metadata + 4 handlers) - SEO : Seo.svelte (canonical, OG, Twitter), footer fédéré OKI + flag-bar - Mesuré puppeteer 390x844 : seek tactile OK, scrollWidth OK, SW actif
Radyobòkaz Player
Lecteur audio web pour la radio Radyobòkaz, hébergée sur l'instance Funkwhale mizik.o-k-i.net (~2000 titres).
Construit sur une version modifiée de svelte-podcast
(librairie headless de lecteur audio, voir src/lib).
Utilitaires RSS (SSR)
La librairie inclut des utilitaires pour consommer des flux RSS de podcasts,
compatibles SSR (pas de DOMParser, parsing via fast-xml-parser) :
// src/routes/podcast/+page.ts
import { fetch_podcast_feed } from '$lib/rss';
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ fetch }) => ({
// passer le `fetch` de SvelteKit : SSR, cache et hydration
feed: await fetch_podcast_feed('https://feed.syntax.fm/rss', fetch),
});
fetch_podcast_feed(url, fetcher?)— télécharge et parse un flux (RSS 2.0 + tags iTunes)parse_podcast_feed(xml)— parse une chaîne XML déjà récupérée- Types exportés :
PodcastFeed,PodcastEpisode(titre, guid, date ISO, durée en secondes, enclosure, pochette, numéros d'épisode/saison, explicit…)
Les durées itunes:duration sont acceptées aux formats 3723, 62:03 et 1:02:03.
Les épisodes sans enclosure audio sont ignorés. Voir la route /podcast pour un
exemple complet (flux chargé côté serveur, épisodes joués dans le lecteur).
Fonctionnalités
- 📻 Mode radio aléatoire : file de lecture infinie de titres piochés au hasard
- 🎵 Écoute à la carte : liste complète des titres avec recherche (titre, artiste, album)
- 🎙️ Flux RSS de podcasts : parsing SSR + lecture des épisodes (démo sur
/podcast) - ⏭️ Passage automatique au titre suivant en fin de piste
- 🎛️ Contrôles : lecture/pause, précédent/suivant, volume, mute, seek
- 🖼️ Pochette, titre, artiste et album du morceau en cours
- 🔃 L'audio continue de jouer lors de la navigation entre pages
Développement
yarn install
yarn dev # serveur de dev
yarn build # build statique (adapter-static) dans build/
yarn run check # svelte-check
Comment ça marche
L'API publique de Funkwhale est utilisée côté client, sans authentification :
GET /api/v1/radios/radios/7/tracks/?page=N&page_size=50— liste des titres de la radioGET /api/v1/listen/<uuid>/— flux audio du titre (CORS ouvert, supporteRange)
Structure du code :
| Fichier | Rôle |
|---|---|
src/lib/ |
Librairie svelte-podcast (store audio, composants headless) |
src/lib/rss.ts |
Utilitaires SSR pour flux RSS de podcasts (parse + fetch) |
src/radio/funkwhale.ts |
Client de l'API Funkwhale |
src/radio/playable.ts |
Type PlayableTrack (titre jouable, quelle que soit la source) |
src/radio/radio-store.ts |
File de lecture : mode radio aléatoire / liste, suivant/précédent |
src/radio/library-store.ts |
Chargement progressif de la liste complète des titres |
src/radio/radio-player.svelte |
Barre de lecture (pochette, contrôles, progression) |
src/radio/track-list.svelte |
Liste des titres avec recherche |
src/routes/+page.svelte |
Page radio Radyobòkaz |
src/routes/podcast/ |
Démo des utilitaires RSS (flux chargé en SSR, épisodes jouables) |
Description
Languages
TypeScript
54.6%
Svelte
37.9%
JavaScript
6.4%
HTML
0.9%
CSS
0.2%