/googolplex-theater

Persistently maintain multiple Chromecasts as digital signage without a browser.

Primary LanguageJavaMIT LicenseMIT

googolplex-theater

by @yuzawa-san

Icon

GitHub release (latest by date) GitHub All Releases Docker packagecloud

build codecov

Persistently maintain multiple Chromecast devices on you local network without using your browser. Ideal for digital signage applications: restaurant menus, notice boards. Originally developed to display statistics dashboards (e.g. Grafana).

Example

There are several tools and libraries out there (see below), but this project is intended to be very minimalist. There is a simple web UI to check device info and trigger refreshes.

Screenshot

There is no backing database or database dependencies, rather there is a YAML files containing the devices which is watched for changes. The YAML configuration is conveyed to the receiver application, which by default accepts a URL to display in an IFRAME. The receiver application can be customized easily to suit your needs. The application will try to reconnect if a session is ended for whatever reason. (Optional) The application has a local HTTP proxy for advanced use cases (adding/removing headers for auth or frame breaking). See feature files for more details.

Requirements

This application has very minimal runtime requirements:

  • Java runtime version 17 or later.
  • Linux or MacOS is preferred. Windows appears to work, but the maintainer lacks access to the hardware to test, so your mileage may vary.

There are certain requirements for networking which are beyond the realm of this project, but should be noted:

  • This application must run on the same local area network as your Chromecasts.
    • Multicast DNS must work on your network and on the computer you run the application on. This is how the devices and the application discover each other.
  • It is strongly recommended to use a dedicated computer to run this application.
    • The Raspberry Pi is a good, small, and cost-effective computer to use.
    • The newer models with ARMv8 processors are most desirable. See the models list for more details. Most models introduced after 2016 fulfill these recommendations.
    • It is not advisable to use older models which use older processor architectures (ARMv6 or ARMv7), specifically the original Raspberry Pi Zero or Zero W. See the linked specifications table in previous item for more details.
  • IMPORTANT: URLs must be HTTPS (unless you use an unpublished receiver app) and must not deny framing This is a limit of using an IFRAME to display content. NOTE: the built-in proxy provides a way to attempt to circumvent this.

Development requirements:

  • JDK 17 or later. The gradle wrapper is used to build this application and is already included.

Installation

There are few options for installation:

Package Installation

This application is available as a deb package which can be installed using apt. The Raspberry Pi is a cost-effective piece of hardware to run this application, so Raspberry Pi OS (Raspbian) is the main build target for this project. The package should theoretically work with other Debian distros as well.

The installation process may prompt you to install a version of Java. The packaging automates the installation for the most part, so it is only really necessary to update your configuration. The application is installed in /opt/googolplex-theater. It is registered as a systemd service enabled to launch at startup. The service file is installed at /usr/lib/systemd/system/googolplex-theater.service. The systemctl and journalctl commands are useful for starting, stopping, checking status, tailing logs, etc.

packagecloud

Packagecloud generously provides hosting for this project and other open-source projects. This is one of the easiest ways to install the application and keep it up to date. The following distros are currently supported: raspbian/bullseye, raspbian/bookworm, ubuntu/focal, ubuntu/jammy, ubuntu/noble.

Add the packagecloud repository for this project using their instructions:

curl -s https://packagecloud.io/install/repositories/yuzawa-san/googolplex-theater/script.deb.sh | sudo bash

Then install:

sudo apt install googolplex-theater

Since the repository has been added to the local apt system, the normal update + upgrade process will check and apply updates for this project.

Manual Package Download

Download a Debian package from the releases page using wget or curl. Then install:

sudo apt install ./googolplex-theater_VERSION-1_all.deb

This process also requires manual updating.

Docker Installation

The application is also available on dockerhub.

This may be comparatively easier versus getting a proper Java runtime installed. This is released in a few common processor architectures: amd64, arm64/v8.

To run a specific VERSION of the application, pull:

docker pull ghcr.io/yuzawa-san/googolplex-theater:VERSION

And then to run the application:

docker run --net=host -v /path/to/your/conf:/opt/googolplex-theater/conf ghcr.io/yuzawa-san/googolplex-theater:VERSION

For the service discovery to work correctly, you will need the --net=host option. There is no safer way to get this working at this point in time. Sadly, this option does not work in Mac. If you get warnings about port 5353 being in use, you may need to disable Avahi on Linux. The conf directory is mounted as a docker volume. This will seamlessly map your local configuration into the Docker runtime.

It is recommended to wrap your docker run in something to keep it running as a daemon or persistent service.

Manual Installation

Download a ZIP archive from the releases page.

Alternatively, clone/download this repo, and run:

./gradlew build

This will generate the application ZIP archive in ./build/distributions/googolplex-theater-boot-VERSION.zip

Once you have the ZIP archive, expand it in the desired destination location and cd into directory.

To run the application with default settings:

./bin/googolplex-theater

Running as Daemon

To provide resiliency, it is recommended to run the application as a daemon. See service descriptor files for upstart, systemd, and launchd in the ./service/ directory. They should work with minor modifications. Please refer to their respective installation guides to enable on your system.

Usage

The configuration is defined in ./conf/config.yml and ./conf/devices.yml. The file is automatically watched for changes. Some example use cases involve using cron and putting your config under version control and pulling from origin periodically, or downloading from S3/web, or updating using rsync/scp.

Using a Custom Receiver

If you wish to customize the behavior of the receiver from just displaying a single URL in an IFRAME, see the example custom receiver in receiver/custom.html.

For custom receivers, you will be required to sign up as a Chromecast developer and also configure devices for development.

Currently the device name and settings are printed to the screen. Customize the listener handler to do as you wish.

Host your modified file via HTTPS on your hosting provider of choice. Then point your new custom receiver application towards that page's URL.

There is a property in the config.yml to override the receiver application.

Case Study: Grafana Dashboards

The maintainer has used this to show statistics dashboards in a software engineering context.

  • Buy a new Raspberry Pi and install the default Raspberry Pi OS (Raspbian).
  • Configure and name your Chromecast(s).
  • Install application via download or via Debian package (which will likely install Java runtime if it is not already installed).
  • Create one Grafana playlist per device.
  • Make your devices.yml file with each playlist url per device. Set the rotation and refresh parameters and make sure the kiosk mode is in the query string parameters.
  • Figure out how to connect.
    • Less secure: Use HTTPS with an IP address allowlist to your location (which must have a static IP) on whatever proxy you may have in front of your Grafana deployment.
    • Medium Secure: Create a Grafana API token with viewer permission and run nginx or other proxy locally with a real SSL certificate, add Authorization header.
    • More Secure: Create a Grafana API token with viewer permission and use this application's proxy feature.
      • Sign up as a Chromecast developer so you can use the local proxy over HTTP.
      • Register your devices for development.
      • Register a new custom reciever, but do not publish it (that would force it to use HTTPS). Configure this app with the "appId" alphanumeric string. Point the url to your static private IP http://192.168.1.XXX:8001/receiver.html.
      • Configure this app's proxy settings pointing at your Grafana root url.
      • Add the Grafana token to the proxy "add header" settings
      • Make your devices.yml have proxyPath: /path/to/playlist?....
  • If you want to update the devices periodically, place the devices.yml file under version control (git) or store it someplace accessible (http/s3/gcs). Add a cron job to pull the devices.yml file from wherever you stored it (alternatively configure something to push the file to the Raspberry Pi). The updates are automatically picked up.
  • If a screen needs to be refreshed, one can do so by accessing the web UI exposed port 8080 and hitting a few buttons.

Troubleshooting

There may be some issues related to discovering the Chromecast devices on your network. It is important that the service discovery uses the network interface and IP address attached to the network with the Chromecasts. The application will make decent attempt to find the proper network interface to use. There is a chance it may find the wrong interface/address based on your system configration (wireless internet vs ethernet, VPN, ordering). Some diagnostic information is printed in the application output annotated with com.jyuzawa.googolplex_theater.mdns.ServiceDiscovery. There is a property in the config.yml which allows the desired network interface (by name) or IP address to be provided.

Contributing

See CONTRIBUTING.md for more details.

This is intended to be minimalist and easy to set up, so advanced features are not the goal here. Some other projects listed below may be more suited for your use case.

TODO

  • Split screen layouts

Related Projects

This application overlaps in functionality with some of these fine projects:

Protocol implementations

Foundational work has been done to research how the Chromecast protocol works and these protocol libraries have been developed in a variety of languages. A lot of the headless senders are built off of these.

Browser Senders

These applications cast directly from your browser. You may need to have your browser up and running all of the time.

Headless Senders

These applications cast without a Chrome browser running, rather they utilize the Chromecast protocol to establish a communication session with the devices directly.

This application is most similar to the headless sender projects. It does not use a protocol implementation library.

Name

It is designed for multiple Chromecasts, rather than a googol or googolplex. It is from The Simpsons. The developer made it singular and decided to use the American spelling. Googol sure does sound like the manufacturer of the Chromecast.