213 lines
8.2 KiB
Markdown
213 lines
8.2 KiB
Markdown
# rkt-web-player
|
|
|
|
Een audioplayer met webinterface, gebouwd op de bestaande Racket-pakketten:
|
|
|
|
- `racket-audio` voor lokale weergave en metadata;
|
|
- `racket-upnp` en `racket-sonos` voor ontdekking van netwerkspelers;
|
|
- `racket-audio-dlna` voor het publiceren en afspelen van lokale bestanden;
|
|
- `racket-mimetypes`, `simple-ini` en `simple-log` voor ondersteunende taken.
|
|
|
|
## Starten
|
|
|
|
De gekoppelde ontwikkelpackages kunnen direct worden gebruikt:
|
|
|
|
```console
|
|
racket main.rkt D:\Muziek
|
|
```
|
|
|
|
Standaard opent de speler `http://127.0.0.1:8080/`. Iedere opgegeven map wordt
|
|
een afzonderlijke muziekbibliotheek. Bij het starten wordt alleen de inhoud van
|
|
de eerste rootmap gelezen; er vindt geen recursieve bibliotheekscan plaats.
|
|
|
|
```console
|
|
racket main.rkt --port 8090 --no-browser D:\Muziek D:\Podcasts
|
|
```
|
|
|
|
Met een klein INI-bestand zijn vaste defaults mogelijk:
|
|
|
|
```ini
|
|
[server]
|
|
listen-ip=127.0.0.1
|
|
port=8080
|
|
|
|
[player]
|
|
dlna-port=8734
|
|
|
|
[libraries]
|
|
muziek=D:\Muziek
|
|
podcasts=D:\Podcasts
|
|
|
|
[playback-agents]
|
|
7b4776ef27104e8eb9f7ea2c622ce76ca23de4260b0f94e6880d321017b32a0e4=true
|
|
|
|
[authentication]
|
|
local-networks=127.0.0.0/8;::1/128;10.0.0.0/8;172.16.0.0/12;192.168.0.0/16
|
|
trusted-proxies=127.0.0.0/8;::1/128
|
|
session-seconds=43200
|
|
|
|
[users]
|
|
hans=$argon2id$v=19$m=19456,t=2,p=1$...
|
|
```
|
|
|
|
Start dat bestand met `racket main.rkt --config rkt-web-player.ini`. Iedere key
|
|
onder `[libraries]` is de zichtbare bibliotheeknaam; de waarde is de lokale of
|
|
UNC-rootmap. Het oudere `[library] paths=D:\Muziek;D:\Podcasts` blijft eveneens
|
|
ondersteund.
|
|
|
|
Zodra `[users]` minstens één gebruiker bevat, toont de webinterface voor
|
|
niet-lokale clients een eigen loginvenster. Wachtwoorden staan uitsluitend als
|
|
Argon2id-hash in de INI. Maak zo'n hash vanuit Racket:
|
|
|
|
```racket
|
|
#lang racket/base
|
|
|
|
(require rkt-web-player/users)
|
|
|
|
(displayln (make-password-hash "een lang en uniek wachtwoord"))
|
|
```
|
|
|
|
`local-networks` bepaalt welke clients zonder login mogen werken.
|
|
`trusted-proxies` bepaalt uitsluitend van welke directe peers de laatste
|
|
`X-Forwarded-For`-waarde wordt geaccepteerd. Laat die lijst zo klein mogelijk;
|
|
bij Apache op dezelfde machine zijn loopbackadressen voldoende. Zonder
|
|
gebruikers is authenticatie uitgeschakeld en blijft het oude gedrag behouden.
|
|
|
|
## Werking
|
|
|
|
De interface volgt de informatiearchitectuur van `rktplayer`, maar is
|
|
responsive en geschikt voor muis, toetsenbord en touch. Links staat de lazy
|
|
mappenbrowser met trackinformatie; rechts staan playlisttabs en de huidige
|
|
playlist. Een map wordt pas recursief gelezen wanneer die met **afspelen** of
|
|
**toevoegen** wordt gekozen. Trackmetadata wordt eveneens pas op dat moment
|
|
geladen. Bij de huidige track toont de webinterface embedded album-art uit de
|
|
audio-tags. Als die ontbreekt, worden naast het audiobestand ook `cover`,
|
|
`folder` en `front` met een JPEG- of PNG-extensie geprobeerd.
|
|
|
|
De webinterface praat met een kleine JSON-API onder `/api`. Lokale weergave
|
|
wordt pas geïnitialiseerd bij het eerste afspeelcommando. De knop naast de
|
|
uitvoerkeuze start UPnP-discovery; gevonden Sonos-zones worden als logische
|
|
groepen aangeboden en niet nogmaals als losse UPnP-renderers.
|
|
|
|
Playlisttabs kunnen worden toegevoegd, geselecteerd, hernoemd door dubbel te
|
|
klikken en verwijderd. Tracks kunnen worden afgespeeld, verwijderd en met
|
|
drag-and-drop verplaatst. De tabs zijn in deze versie alleen in het geheugen
|
|
aanwezig en worden niet na een herstart hersteld.
|
|
|
|
De server luistert standaard alleen op localhost. Geef alleen bewust een
|
|
LAN-adres aan `--listen-ip`. Configureer gebruikersauthenticatie voordat de
|
|
webinterface via een publiek bereikbare reverse proxy wordt aangeboden.
|
|
|
|
Externe gebruikers krijgen na succesvolle aanmelding een willekeurige 256-bit
|
|
sessiecookie met `Secure`, `HttpOnly` en `SameSite=Strict`. Sessies verlopen na
|
|
de ingestelde inactiviteitsduur en worden niet over een serverherstart heen
|
|
bewaard. Na vijf mislukte pogingen vanaf hetzelfde clientadres wordt aanmelden
|
|
vijf minuten geblokkeerd. De `/api/agent/*`-routes gebruiken geen
|
|
gebruikerssessie: daarvoor blijft de afzonderlijke playback-agent-allowlist
|
|
gelden.
|
|
|
|
## Windows playback agent
|
|
|
|
Een lichte playback agent kan op een Windows-laptop draaien en meldt zichzelf
|
|
via HTTP bij de centrale RKT Web Player aan. De agent opent geen inkomende
|
|
netwerkpoort. Hij pollt de server voor opdrachten en rapporteert daarbij zijn
|
|
actuele afspeelstatus.
|
|
|
|
Start vanuit de broncode:
|
|
|
|
```console
|
|
racket player-agent.rkt
|
|
```
|
|
|
|
Dezelfde GUI kan vanuit een ander Racket-programma worden gestart:
|
|
|
|
```racket
|
|
#lang racket/base
|
|
|
|
(require rkt-web-player/player-agent)
|
|
|
|
(run-player-agent)
|
|
```
|
|
|
|
De GUI bewaart de server-URL, de gekozen naam en een eenmalig gegenereerde
|
|
256-bit applicatie-ID in `rkt-web-player-agent.ini` in de gebruikersspecifieke
|
|
Racket-configuratiemap. Vul als server bijvoorbeeld `http://192.168.1.10:8080`
|
|
in. De naam wordt in dezelfde agent-GUI ingesteld. Na registratie verschijnt
|
|
de agent met die naam als uitvoer van type `AGENT`; de server volgt latere
|
|
naamswijzigingen bij registratie en polling. De server laat een agent alleen
|
|
toe wanneer zijn volledige applicatie-ID vooraf als key onder
|
|
`[playback-agents]` staat en de waarde niet `false` is. Een onbekende ID krijgt
|
|
HTTP 403 en wordt niet als uitvoerpunt aangemaakt. De agent toont in dat geval
|
|
zijn ID en meldt dat de serverbeheerder deze eerst aan de INI moet toevoegen.
|
|
|
|
Onder **Afspelen** toont de agent het playlistnummer, de huidige track en
|
|
bestandsnaam, afspeeltoestand, verstreken en totale tijd, bitdiepte,
|
|
samplefrequentie, kanaalaantal en decoderformaat.
|
|
|
|
Een geselecteerde track wordt volledig naar een tijdelijk bestand gedownload
|
|
voordat `racket-audio` de weergave start. Tijdens het afspelen stuurt de server
|
|
al een `prefetch`-opdracht voor de volgende playlisttrack. De agent bewaart
|
|
daardoor maximaal het huidige en het volgende bestand lokaal. Bij de overgang
|
|
opent de agent het vooraf opgehaalde bestand direct bij decoder-EOF. Daardoor
|
|
blijven polling en netwerkvertraging buiten het tijdkritische audiopad en kan
|
|
`racket-audio` de volgende track achter de nog uitspelende uitvoerbuffer zetten.
|
|
De server wordt bijgewerkt zodra het nieuwe music-id werkelijk hoorbaar is en
|
|
stuurt vervolgens de daaropvolgende prefetch. Tijdelijke bestanden worden
|
|
opgeruimd zodra ze niet meer nodig zijn en bij afsluiten van de agent.
|
|
|
|
### Systeemvak
|
|
|
|
De GUI gebruikt optioneel de open-source SDL3-tray-API. Als zowel het Racket-
|
|
pakket `sdl3` als de native SDL3-, SDL3_image- en SDL3_ttf-libraries aanwezig
|
|
zijn, sluit de vensterknop de agent naar het systeemvak. Het menu bevat
|
|
**RKT Web Player Agent openen** en **Afsluiten**. Zonder SDL3 blijft de agent
|
|
gewoon werken en sluit de vensterknop het proces af. Er wordt geen PowerShell-
|
|
proces of externe tray-helper gestart.
|
|
|
|
```console
|
|
raco pkg install sdl3
|
|
```
|
|
|
|
SDL3 is bewust geen verplichte package-dependency: de agent blijft daardoor
|
|
klein voor gebruikers die geen systeemvak nodig hebben. Op Windows moeten de
|
|
bijbehorende native DLL's daarnaast vindbaar zijn, bijvoorbeeld naast het
|
|
gebouwde executable of via `PATH`.
|
|
|
|
### CLI playback agent
|
|
|
|
De headless agent gebruikt exact dezelfde polling-, download-, audio- en
|
|
gapless-prefetchkern als de GUI-agent:
|
|
|
|
```console
|
|
racket player-agent-cli.rkt
|
|
racket player-agent-cli.rkt --server https://muziek.example.nl --name "Werkkamer"
|
|
```
|
|
|
|
GUI en CLI gebruiken standaard hetzelfde gebruikersspecifieke
|
|
`rkt-web-player-agent.ini`, dus ook hetzelfde application-ID. Met `--config`
|
|
kan de CLI een afzonderlijk INI-bestand en daarmee een afzonderlijke identiteit
|
|
gebruiken. Bij het starten worden naam, server en application-ID afgedrukt;
|
|
stoppen gaat met `Ctrl+C`.
|
|
|
|
Vanuit Racket is de headless variant eveneens beschikbaar:
|
|
|
|
```racket
|
|
(require rkt-web-player/player-agent)
|
|
|
|
(run-player-agent-cli #:server-url "https://muziek.example.nl"
|
|
#:name "Werkkamer")
|
|
```
|
|
|
|
De allowlist voorkomt dat een onbekende agent zich als uitvoerpunt registreert
|
|
of opdrachten en tijdelijke media ontvangt. Het applicatie-ID is een gedeeld
|
|
toegangstoken en vervangt geen transportbeveiliging of gebruikersauthenticatie.
|
|
Gebruik de agent en server alleen op een vertrouwd LAN zolang de HTTP-server
|
|
geen TLS heeft.
|
|
|
|
## Controleren
|
|
|
|
```console
|
|
raco test private/users.rkt private/library.rkt private/player.rkt \
|
|
private/player-agent-config.rkt
|
|
raco setup --check-pkg-deps rkt-web-player
|
|
```
|