This media player is designed for realtime playback of audio and video in theatrical and interactive applications. Configure the display locations and cue new media over http, either on the same computer or from the web.
If you're on a 64-bit GNU/Linux system, you can use the the binary release here. Note: The Wayland display server is not yet supported. Try the Wayland branch at your own risk.
Binary releases for other systems are a work in progress. In the meantime, you'll need a few things to compile and run Apollo:
You'll need Rust, GTK+, and GStreamer to compile and run Apollo.
- Installation of Rust: https://www.rust-lang.org/
- Installation of GTK+: https://www.gtk.org/ (This is usually installed already on GNU/Linux systems. Search for package libgtk-3-0, and libgtk-3-dev if you'd like to compile Apollo.)
Follow the directions on both websites to download and install these tools before you proceed.
To install GStreamer on a Debian-like system,
sudo apt install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav libgstrtspserver-1.0-dev libges-1.0-dev
If you're on a different system, you'll need to follow the platform-specific instructions for GStreamer-rs: https://gitlab.freedesktop.org/gstreamer/gstreamer-rs
Once you have installed the prerequities above, clone or download this repository. Then compile and run the program using Cargo (included with Rust):
cargo run
This will take several minutes to download all the components. You'll be left with a running Apollo instance in the background. You can use
cargo run
to run Apollo again (it will not recompile this time). This is a debug version (larger file, but otherwise perfectly functional).
To compile a finished copy for deployment, use
cargo build --release
The completed binary will be located in the automatically generated "target/release" folder with the name "apollo".
If you run into issues with glib-2.0 or gdk-3.0, you can run these commands on a Debian-like system:
glib2.0 issue:
sudo apt install libgtk2.0-dev
gdk-3.0 issue:
sudo apt install build-essential libgtk-3-dev
To play media on Apollo, you need to
- Define the media channel, and
- Tell Apollo what media to play on that channel.
You can have as many channels as you like (currrently tested with eleven simultaneous channels), but only one piece of media playing on each channel at a time.
Before you specify a media channel, you have the option to specify the properties of the application window where it will be displayed. Remember that these settings only take effect if applied before adding a media channel to the window.
Here are the application window options:
- windowNumber: a unique number for the application window. Channels with the same window number will appear on the same application window and will be stacked from first-defined to last-defined on the top.
- fullscreen: a true or false value to indicate whether the window should be set to fullscreen.
- windowDimensions: a two element tuple that specifies the minimum size of the application window that holds the video screen. If the application window is set to fullscreen, you can use this tool to stretch the application window across multiple monitors.
When you define a channel, you have the option to specify where the audio is played and where the video is played. If you leave these options empty, Apollo with use the system default for audio and open a new window (sized to the content) to play video.
Here are the media channel options:
- channel: the channel number
- videoFrame: a structure that defines the location and size of the video screen. Defaults to a new window generated by gstreamer.
- audioDevice: the audio device for playing any sound. Defaults to the system default.
- loopMedia: the media (video or audio) to loop when no other media is playing on this channel. Defaults to nothing if left blank.
A video frame has several parameters:
- windowNumber: a number for the application window. Channels with the same window number will appear on the same application window and will be stacked from first-defined to last-defined on the top.
- top: distance (in pixels) from the top of the application window to the top of the video.
- left: distance (in pixels) from the left side of the application window to the left side of the video.
- height: height (in pixels) of the video screen
- width: (in pixels) of the video screen
An audio device has several options as well:
- a Pulse audio device (with deviceName parameter): a high-level toolkit which is recommended for most purposes. Multiple chanels can share a device and will automatically be mixed together.
- an Alsa device (with deviceName parameter): a lower-level toolkit usefull when trying to pick a specific display on a graphics card. WARNING: Only one channel can use an Alsa device at a time - Alsa does not have the capability to mixdown multiple audio sources.
When you cue a specific file for Apollo to play, it will begin instantly (or nearly instantly, depending on the capabilities of the computer). You have the option to play any type of media on any channel, though in practice you will typically have separate audio channels and video channels.
Here are the cue media options:
- uri: the location of the video or audio file to play. The uri format must follow the URI syntax rules. This means local files must be specified like "file:///absolute/path/to/file.mp4".
- channel: the media channel to play the video or audio. New media sent to the same channel will replace the old media, starting instantly.
- loopMedia: the location of media to loop after this media is complete. If a file is specified in the loop media field, it takes priority over the channel loop media field.
You can define media channels and cue media using the two available POST commands on localhost port 27655 (A-P-O-L-L). An example interaction might look like this:
curl -H "Content-Type: application/json" -X POST -d '{ "channel": 1, "videoFrame": { "windowNumber": 1, "top": 100, "left": 100, "height": 300, "width": 400}}' http://localhost:27655/defineChannel
curl -H "Content-Type: application/json" -X POST -d '{ "uri": "https://archive.org/download/never-gonna-give-you-up-4-k/Never%20Gonna%20Give%20You%20Up%204K.ia.mp4", "channel": 1}' http://localhost:27655/cueMedia
Then, perhaps:
curl -H "Content-Type: application/json" -X POST -d '{ "channel": 1, "videoFrame": { "top": 0, "left": 0, "height": 600, "width": 800}}' http://localhost:27655/resizeChannel
curl -H "Content-Type: application/json" -X POST -d '{ "channel": 1, "direction": "down"}' http://localhost:27655/alignChannel
curl -H "Content-Type: application/json" -X POST -d '{ "channel": 1, "position": 2000}' http://localhost:27655/seek
And mercifully
curl -H "Content-Type: application/json" -X POST -d '{ "channel": 1, "state": "paused"}' http://localhost:27655/changeState
curl -H "Content-Type: application/json" -X POST http://localhost:27655/quit
The port number (and listening location) can be adjusted with the '-a' or '--address' commandline option, and log level can be set via the '-l' or '--logLevel' option. Log levels are Trace, Info, Debug, Warn, Error (listed in decreasing level of verbosity).
If you need to make Apollo available to the open internet, we recommend Caddy. Follow the instructions for setting up a reverse proxy (it will take less than 60 seconds).
In the future, additional options such as changing media to a different channel, swapping channel position, etc., will be added based on our own needs. If you are using Apollo and have a specific feature you need, feel free to send us an email and we'll do our best to make it a priority.
It's possible to run Apollo on less-capible systems! For example, a Raspberry Pi 4 can manage audio very well, and plays video acceptably (with a small delay at the start of each).
Take careful notes of the steps to
- cross-compile Apollo, and
- setup your Raspberry Pi host to run Apollo
Note: These instructions are written for compiling the software on Ubuntu 22.04.
Note: These settings are largely analogous for arm64, but the 64-bit version hasn't been tested.
To cross-compile, install the correct rust target and install the linker.
rustup target add armv7-unknown-linux-gnueabihf
sudo apt install gcc-arm-linux-gnueabihf
You'll also need to add the armhf architecture to dpkg.
sudo dpkg --add-architecture armhf
And add these sources to the end of /etc/apt/sources.list.
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted+
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ jammy universe
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ jammy-updates universe
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ jammy multiverse
deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports/ jammy-updates multiverse
Make sure to add [arch=amd64]
to the other sources while you're at it.
Install the gtk dev packages for the new architecture.
sudo apt update
sudo apt install libgtk-3-dev:armhf libzmq3-dev:armhf libgstreamer1.0-dev:armhf libgstreamer-plugins-base1.0-dev:armhf gstreamer1.0-plugins-base:armhf gstreamer1.0-plugins-good:armhf gstreamer1.0-plugins-bad:armhf gstreamer1.0-plugins-ugly:armhf gstreamer1.0-libav:armhf libgstrtspserver-1.0-dev:armhf libges-1.0-dev:armhf libges-1.0-0:armhf
When you compile, pass several environment variables to the compilation.
env PKG_CONFIG_ALLOW_CROSS=1 PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig/ cargo build_armhf
To cross-compile, install the correct rust target and install the linker.
rustup target add aarch64-unknown-linux-gnu
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
You'll also need to add the arm64 architecture to dpkg.
sudo dpkg --add-architecture arm64
And add these sources to the end of /etc/apt/sources.list (or if also using 32 bit, combine the two like [arch=armhf,arm64]
).
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy universe
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-updates universe
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-updates multiverse
Make sure to add [arch=amd64]
to the other sources while you're at it.
Install the dev packages for the new architecture.
sudo apt update
sudo apt install libgtk-3-dev:arm64 libzmq3-dev:arm64 libgstreamer1.0-dev:arm64 libgstreamer-plugins-base1.0-dev:arm64 gstreamer1.0-plugins-base:arm64 gstreamer1.0-plugins-good:arm64 gstreamer1.0-plugins-bad:arm64 gstreamer1.0-plugins-ugly:arm64 gstreamer1.0-libav:arm64 libgstrtspserver-1.0-dev:arm64 libges-1.0-dev:arm64 libges-1.0-0:arm64
When you compile, pass several environment variables to the compilation.
env PKG_CONFIG_ALLOW_CROSS=1 PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig/ cargo build_arm64
All that is needed is installing the packages above (i.e. GStreamer). If you're displaying video, you probably want to disable screen blanking in the Raspberry Pi Config settings.
Hardware decoding works well for videos up to 1080p at 30 fps. There is a short delay when switching between playing videos, but there is no delay when playing a new video after the first has stopped.
This project is licensed under the GNU GPL Version 3 - see the LICENSE file for details. This project is closely connected to Minerva.
Thanks to all the wonderful free and open source people out there who have made this project possible, especially Mozilla et al. for a beautiful language and the folks at Gnome, GTK, and GStreamer for their ongoing efforts advance multimedia in open source software.