Skip to content

Add local zip sets and a source client to broadcast them - #1

Open
Andrey-Raspopov wants to merge 1 commit into
realbogart:masterfrom
Andrey-Raspopov:local-zip-sets
Open

Add local zip sets and a source client to broadcast them#1
Andrey-Raspopov wants to merge 1 commit into
realbogart:masterfrom
Andrey-Raspopov:local-zip-sets

Conversation

@Andrey-Raspopov

Copy link
Copy Markdown

A show can now be backed by a zip of mp3s plus an .m3u instead of a spotify playlist. zipset.js opens the archive, picks the m3u nearest the root and uses it for running order and display names, falling back to every mp3 sorted by name when there is none. Playlist lines are matched against archive entries tolerantly, since real m3u files arrive with backslashes, './' prefixes and inconsistent case. Entries are unpacked into zip_work_dir one at a time and asynchronously so a long set does not block the websocket server.

server.js gains /loadZip, /getPlaylist and /track (with range support so the browser can seek), and unpacks a set by itself when a show whose playlistLink names a zip goes on air. Requested paths are resolved against zip_root and anything pointing outside it is refused, so the endpoint cannot be used to unpack arbitrary files.

The page shows the current track, taken from the stream's ICY title, which a local set announces as "local:".

Nothing here produces audio on its own, so broadcast.js streams a loaded set into icecast as one continuous connection and updates the title as each track comes up. dev/icecast.xml runs an icecast locally to try the whole chain against.

Three fixes fell out of getting that working:

  • the ICY reader had the production host hardcoded and ignored stream_ip, so it read metadata from a different server than the page was playing
  • it parsed icy-metaint from responses it never checked, so a stream with no source connected left it wedged forever with no retry
  • connection errors were unhandled, which took the server down when icecast was unreachable

A show can now be backed by a zip of mp3s plus an .m3u instead of a
spotify playlist. zipset.js opens the archive, picks the m3u nearest the
root and uses it for running order and display names, falling back to
every mp3 sorted by name when there is none. Playlist lines are matched
against archive entries tolerantly, since real m3u files arrive with
backslashes, './' prefixes and inconsistent case. Entries are unpacked
into zip_work_dir one at a time and asynchronously so a long set does
not block the websocket server.

server.js gains /loadZip, /getPlaylist and /track (with range support so
the browser can seek), and unpacks a set by itself when a show whose
playlistLink names a zip goes on air. Requested paths are resolved
against zip_root and anything pointing outside it is refused, so the
endpoint cannot be used to unpack arbitrary files.

The page shows the current track, taken from the stream's ICY title,
which a local set announces as "local:<track index>".

Nothing here produces audio on its own, so broadcast.js streams a loaded
set into icecast as one continuous connection and updates the title as
each track comes up. dev/icecast.xml runs an icecast locally to try the
whole chain against.

Three fixes fell out of getting that working:

* the ICY reader had the production host hardcoded and ignored
  stream_ip, so it read metadata from a different server than the page
  was playing
* it parsed icy-metaint from responses it never checked, so a stream
  with no source connected left it wedged forever with no retry
* connection errors were unhandled, which took the server down when
  icecast was unreachable

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant