Skip to content

bytebraid/lobsters

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

26 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

THE LOBSTER TANK

Internet Radio, Community Dubplates

React version License

🦞 What's all this then?

Welcome Lobsters. The tank is web portal that delivers live audio streaming via HLS. Independently broadcast your personal content or restream any other media from a URL. The tank is fully contained and primed for self-hosting on cloud or low-cost VPS. Manifest your internet presence with 24/7 internet radio, share the sounds you love or stream live and direct to your audience.

The magical Lobster Bisque web portal serves up your curated music, podcasts and playlists. The container exposes an SSL-secured port for IceCast, so you can interrupt regular broadcasting with a live radio show! We like Butt for streaming live audio to the Lobster Tank.

Novel features provided from the Bisque Kitchen interface allow skipping over content, interrupting the stream with anything from your configured catalogue and muxing text-to-speech shout outs over your airwaves.

Powered by LiquidSoap and nginx via SWAG

Tacky UI design comes for free, by courtesy of React.js - built with react-scripts and npm.

πŸ€¦β€β™€ The "situation"

This was a personal adventure into the briar and wetlands surrounding modern web development and the saturated landscape of tooling and frameworks, whatever happened to be vogue at the time. It is currently unmaintained and reliant on deprecated dependencies. This is not likely to change. See the license.

If you want to actually use this software in earnest, be my willing guest, however do prepare yourself with a little patience, and expect to grind through some basic data entry to get off the ground.

🐧 Penguins only, please

Currently no Windows / Docker Desktop support.

If you have cygwin + python3 + jinja2 locally you might be able to run docker.sh for the pre-build config/templates. I wish you much success.

πŸ”΄ Prerequisites for Docker setup

  • Your flavour of Linux...
  • ...about 5-6GB of free space
  • ...at least 2GB of RAM
  • ...with python3 (3.12 or above), jinja2, docker and docker compose packages installed
  • ...connected to the internet i.e. an externally routable IP address
  • ...with public DNS records i.e. yourdomain.com can be resolved by CNAME, A or AAAA records set for yourdomain.com
  • ...port 80 on the docker host machine must be free -> to conduct letsencrypt ACME challenges for domain ownership verification
  • ...and if you don't have a personal domain that's fine, SWAG will self-sign a certificate. Your favourite web browsers will then manifest ballache upon you for all the reasons.
  • ...finally you must procure a Google API key (client ID) for OAuth login to the admin portal

✨ Install

⏭ Use Docker

Clone this repo.

$ git clone https://github.com/bytebraid/lobsters.git
  • You must edit templates/config.yaml. Replace all mandatory values

    • Change https_port to 443 if it is free on your host
    • Provide your public domain name, set your Google API key (client ID) for OAuth2
      • Specify https://yourdomain.com:8443 NOTE the 8443 port in your Authorised JavaScript origins and Authorised redirect URIs in your client ID configuration. You can only omit the port if you set https_port to 443.
    • Set privileged email accounts (for access to admin features)
  • Optionally

    • Provide your own TLS certificates
    • Set playlist_mode to your preference
    • Customize limits and messages

🎢 Add your content (OPTIONAL)

# Run csv2liquid.py
$ cd playlists
$ ./csv2liquid.py -a Rankin media.csv # Omit the --alternative arg for a single playlist
$ ./finalize.sh

πŸ’Ύ Build the container(s)

# Navigate to the root of your local repo
#
# +++ Build, compose and start the docker containers +++
#
$ ./docker.sh

This script will build all the containers, retrofit some dependencies with docker commit, and then start the Lobster Tank service.

πŸ›‘ Possible issues

docker.sh will run a down/up cycle after a successful build - beacuse reasons:

  • nginx may need a restart / SIGHUP if your TLS certificates are freshly generated
  • liquidsoap may complain about the "internal scheduler"

If you experience difficulties, stop and start the containers ➑ docker compose down / docker compose up

#######################
# ==== How TO ... === #

# Start the Lobster Tank 🦞
$ docker compose up

# Shell into the containers  🦞
$ docker exec --user root -it tank /bin/bash
$ docker exec --user root -it swag /bin/bash
$ docker exec --user root -it liquidsoap /bin/bash

# Stop the Lobster Tank πŸ›‘
$ docker compose down

# ^^^ To delete the containers, make sure they are down, and then
$ docker system prune -a --volumes

# Update the playlists and databases in the containers
$ cd playlists
$ # Modify media.csv, regenerate playlists
$ ./csv2liquid.py --help
$ # Finalize
$ ./finalize.sh
$ # Install into the docker container
$ ./update-docker.sh

⏭ Linux native installation (because you dabble in the dark arts)

πŸš€ Choose your own adventure. With any luck it's not rocket science...

πŸ’Ύ Not-so-concise instructions follow. What could possibly go wrong?

  • install jinja2 and other dependencies using your distro's package manager (align with what apt gets from the Dockerfile )
  • edit config.yaml and modify the mandatory top section
  • comment out the compose step in docker.sh and run it to generate a directory /configs/ with variables adjusted to your specific deployment
  • install nginx and add the generated default.conf to your /sites-enabled/
  • get dehydrated to acquire and manage TLS certificates and renewals via letsencrypt
  • install python3 and all the app dependencies
  • examine lobster.sh for how to start services manually
  • gunicorn/uvicorn backend runs tank.py (FastAPI) on port 10000
  • liquidsoap must 2.2.x >= 2.2.4
  • go through the the Dockerfile and reproduce the layout
  • install npm and react-scripts, then npm run build in the repo root
  • unpack the app to /var/app and mkdir -p /var/tmp/stream/hls, creaete all the required directories like /var/log/liquidsoap
  • adduser liquidsoap and chown locations under /var to the liquidsoap user, chmod a+rx your /build directory so nginx can serve up your build
  • setup logrotate
  • take appropriate action to install process management for bin/liquidsoap, gunicorn+tank.py, and websocketd (sample systemd unit configs in /etc)
  • perhaps bang your head against the wall for taking the hard route and nothing is working
  • reflect on the choices that led you to read this

πŸ€¦β€ Option 1: It's not working

  • Repent all your sins and follow the docker instructions.

πŸ†˜ Option 2: Seek help

πŸ‘©β€βš•οΈ Contact a therapist as you may require help for deeper issues that led you here

  • "Any man who goes to a psychiatrist ought to have his head examined"

βœ… Option 3: So far so good, and it seems to work?

  • congratulate yourself on being a prodigy
  • edit the boilerplate csv with data about your content. local media or web URLs can be referenced
  • if you provide web URLs, /var/tmp will swell
  • your file must not take more than five minutes to download
  • use the tooling provided to generate dbase.json and hbase.json
  • generate your m3u playlists with metadata annotations -> liquidsoap uses the in-file annotations to generate the "now playing" information state (json files are updated in the web root, and polled by client-side React components)-

❓ What next

Visit https://yourdomain.com:8443 (or whatever port you specified in the config)

πŸ”Š Listen

Press β–Ά on the embedded player to listen to your radio stream.

πŸ”‘ Authenticate with Google

You should have edited templates/config.yaml and updated the allowed_emails (comma separated) to include yours.

Sign in to the Tank using a Google account. If you don't have one create a new Google account (...you can re-use any non-Google email addr you have access to).

πŸ”Š Stream a live show

Click GO LIVE to enable live streaming.

Configure your favourite IceCast client. We like Butt. You must enable TLS in your streaming configuration to connect to the exposed host port.

nginx listens on port 9015 (default) for incoming streams. Stream ingress is reverse proxied to the liquidsoap harbour via a unix socket. The socket expires after 3 hours but You can click GO LIVE anytime to reset expiry by 3 more hours.

πŸ“€ Request a rewind

Click BISQUE to browse available content. Content is defined in media.csv. Run the csv2liquid.py script to regenerate your catalogue and playlists from an updated media.csv.

Clicking a row will reveal details for the show. Click REQUEST A REWIND to interrupt regular broadcasting and immediately stream your selection.

🎀 Send a Shout Out

Type a message and click SHOUT OUT. Your message will be rendered with gtts and played over whatever is currently streaming.

  • SHOUT OUT RULES
    • Must be short, it's not an essay
    • No spamming, wait until it's your turn.
    • Don't repeat yourself. You can say the same message after 7 days.

πŸ“ License

Licensed under the MIT License.