{"id":7785512,"url":"https://github.com/balena-io-experimental/audio","last_synced_at":"2025-04-30T19:27:57.548Z","repository":{"id":42659697,"uuid":"266122295","full_name":"balena-io-experimental/audio","owner":"balena-io-experimental","description":"Audio building block for balenaOS, based on pulseaudio.","archived":false,"fork":false,"pushed_at":"2022-11-15T22:58:24.000Z","size":293,"stargazers_count":31,"open_issues_count":20,"forks_count":13,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-08-07T16:52:00.325Z","etag":null,"topics":["alsa","audio-applications","balenablock","linux","pulseaudio","raspberry-pi"],"latest_commit_sha":null,"homepage":"https://hub.balena.io/blocks","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/balena-io-experimental.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-22T13:51:20.000Z","updated_at":"2024-04-05T09:51:15.000Z","dependencies_parsed_at":"2022-09-18T22:24:13.833Z","dependency_job_id":null,"html_url":"https://github.com/balena-io-experimental/audio","commit_stats":null,"previous_names":["balena-io-experimental/audio"],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balena-io-experimental%2Faudio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balena-io-experimental%2Faudio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balena-io-experimental%2Faudio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balena-io-experimental%2Faudio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/balena-io-experimental","download_url":"https://codeload.github.com/balena-io-experimental/audio/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223783033,"owners_count":17201915,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alsa","audio-applications","balenablock","linux","pulseaudio","raspberry-pi"],"created_at":"2024-04-11T21:06:44.945Z","updated_at":"2024-11-09T04:14:59.690Z","avatar_url":"https://github.com/balena-io-experimental.png","language":"Shell","funding_links":[],"categories":["Shell"],"sub_categories":[],"readme":"# balena audio block\n\nProvides an easy way to work with audio applications in a containerized environment.\nThe `audio` block is a docker image that runs a [PulseAudio](https://www.freedesktop.org/wiki/Software/PulseAudio/) server optimized for balenaOS.\n\n## Features\n\n- PulseAudio v15 audio server\n- Configuration optimized for balenaOS, extendable via PA config files\n- Supports both TCP and UNIX socket communication\n- Bluetooth and ALSA support out of the box\n- Companion library to send PA commands and handle events using JavaScript\n\n## Usage\n\n#### Prebuilt images\n\nWe maintain images for this block on balenaHub Container Registry. The images can be accessed using:\n\n`bh.cr/balenalabs/audio-\u003carch\u003e` or `bhcr.io/balenalabs/audio-\u003carch\u003e` where `\u003carch\u003e` is one of: `rpi`, `armv7hf`, `aarch64` or `amd64`.\n\nFor details on how to select a specific version or commit version of the image see our [documentation](https://github.com/balena-io/open-balena-registry-proxy/#usage).\n\n#### docker-compose file\nTo use this image, create a container in your `docker-compose.yml` file as shown below:\n\n```yaml\nversion: '2'\n\nvolumes:\n  pulse:                          # Only required if using PA over UNIX socket\n\nservices:\n\n  audio:\n    image: bh.cr/balenalabs/audio-\u003carch\u003e # where \u003carch\u003e is one of rpi, armv7hf, aarch64 or amd64\n    privileged: true\n    labels:\n      io.balena.features.dbus: 1  # Only required for bluetooth support\n    ports:\n      - 4317:4317                 # Only required if using PA over TCP socket\n    volumes:\n      - 'pulse:/run/pulse'        # Only required if using PA over UNIX socket\n\n  my-audio-app:\n    build: ./my-audio-app\n    volumes:\n      - 'pulse:/run/pulse'        # Only required if using PA over UNIX socket\n```\n\n#### Send/receive audio\n\nIn order to route audio through the `audio` block there are a few environment variables you'll need to set. Note that they must be set on your client container, where your audio application is running and **not** on the block itself. We recommend setting them in the `Dockerfile`. \n\n| Environment variable | Description |\n| --- | --- |\n| `PULSE_SERVER` | **Required** Address of the PulseAudio server which you want to connect to. Depending on the communication protocol you want to use it can be: \u003cbr\u003e- *UNIX socket*: `PULSE_SERVER=unix:/run/pulse/pulseaudio.socket`\u003cbr\u003e- *TCP socket*: `PULSE_SERVER=tcp:audio:4317` |\n| `PULSE_SINK` | **Optional** The PulseAudio sink your application will send audio to. If not set, the block will use the PulseAudio default sink. Unless you are building a complex audio application we don't recommend setting this variable. If you want to select which output to use, for example HDMI or audio jack for a Raspberry Pi use the `AUDIO_OUTPUT` [env var](#environment-variables) on the block to select the output device.  |\n| `PULSE_SOURCE` | **Optional** The PulseAudio source your application will get audio from. |\n\nSetting these environment variables will instruct your application to route audio to the PulseAudio server on the `audio` container. For this to work your application must have built-in support for  PulseAudio as an audio backend. Most applications do, though some might require installing or configuring additional packages. If your application does not have native support for the PulseAudio backend you'll need to use your container's ALSA backend to bridge over to PulseAudio.\n\nRead on for details on both alternatives. We've also included some examples in the `examples` folder (along with the `docker-compose.yml` file) so be sure to check that as well for implementation details.\n\n**PulseAudio backend**\n\nFor applications with PulseAudio support, the audio is routed as follows: \n\n`[client-container] audio-app --\u003e [audio] PulseAudio --\u003e [audio] ALSA --\u003e Audio Hardware`\n\nHere is a non-exhaustive list of applications with PulseAudio backend that have been tested to work, feel free to PR more: \n- [SoX](http://sox.sourceforge.net/): PA backend distributed via `libsox-fmt-pulse` package\n- [MPlayer](http://www.mplayerhq.hu/): Native PA backend\n- [FFmpeg](https://ffmpeg.org/): Native PA backend\n\n**ALSA bridge**\n\nFor audio applications that don't have built-in PulseAudio support you can use ALSA to brige the gap:\n\n`[client-container] audio-app --\u003e [client-container] ALSA --\u003e [audio] PulseAudio --\u003e [audio] ALSA --\u003e Audio Hardware`\n\nSetting up the ALSA bridge requires extra configuration steps on your containers so we created a few bash scripts to simplify the process:\n\n- [Debian](scripts/alsa-bridge/debian-setup.sh)\n- [Alpine](scripts/alsa-bridge/alpine-setup.sh) \n\nBefore making use of audio capabilities you should run this script. An easy way to do so is by including the following instruction in your `Dockerfile`:\n\n```Dockerfile\nRUN curl -skL https://raw.githubusercontent.com/balena-labs-projects/audio/master/scripts/alsa-bridge/debian-setup.sh| sh\n```\n\n## Customization\n### Extend image configuration\n\nYou can extend the `audio` block to include custom configuration as you would with any other `Dockerfile`. Just make sure you don't override the `ENTRYPOINT` as it contains important system configuration.\n\nHere are some of the most common extension cases: \n\n- Pass a flag to the PulseAudio server:\n\n```Dockerfile\nFROM bh.cr/balenalabs/audio-aarch64\n\nCMD [ \"--disallow-module-loading\" ]\n```\n\n- Add custom configuration files:\n\n```Dockerfile\nFROM bh.cr/balenalabs/audio-aarch64\n\nCOPY custom.pa /usr/src/custom.pa\nCMD [ \"pulseaudio\", \"--file /usr/src/custom.pa\" ]\n```\n\n- Start PulseAudio from your own bash script:\n\n```Dockerfile\nFROM bh.cr/balenalabs/audio-aarch64\n\nCOPY custom.pa /usr/src/custom.pa\nCOPY start.sh /usr/src/start.sh\nCMD [ \"/bin/bash\", \"/usr/src/start.sh\" ]\n```\n\n### Environment variables\n\nThe following environment variables allow some degree of configuration:\n\n| Environment variable | Description | Default | Options | \n| --- | --- | --- | --- |\n| `AUDIO_LOG_LEVEL` | PulseAudio log level. | `WARN` | `ERROR`, `WARN`, `NOTICE`, `INFO`, `DEBUG`. |\n| `AUDIO_OUTPUT` | Select the default audio output device. \u003cbr\u003eCan also be changed at runtime by using the [companion library](#companion-library) | `AUTO` | For all device types: \u003cbr\u003e- `AUTO`: Let PulseAudio decide. Priority is `USB \u003e DAC \u003e HEADPHONES \u003e HDMI`\u003cbr\u003e- `DAC`: Force default output to be an attached GPIO based DAC\u003cbr\u003e- `\u003cPULSE_SINK_NAME\u003e`: If you know the sink name you can force set it too. Note that you can't use this to set custom sinks as default, in that case use `set-default-sink` on your custom pa script. \u003cbr\u003e\u003cbr\u003e For Raspberry Pi devices: \u003cbr\u003e- `RPI_AUTO`: BCM2835 automatic audio switching as described [here](https://web.archive.org/web/20200427023741/https://www.raspberrypi.org/documentation/configuration/audio-config.md). Deprecated for devices running Linux kernel 5.4 or newer. \u003cbr\u003e- `RPI_HEADPHONES`: 3.5mm audio jack \u003cbr\u003e- `RPI_HDMI0`: Main HDMI port \u003cbr\u003e- `RPI_HDMI1`: Secondary HDMI port (only Raspberry Pi 4) \u003cbr\u003e\u003cbr\u003e For Intel NUC: \u003cbr\u003e- NUCs have automatic output detection and switching. If you plug both the HDMI and the 3.5mm audio jack it will use the latter.  |\n| `AUDIO_VOLUME` | Initial volume level for the default audio output device. | `75%` | Any value between 0-100%. |\n\n### Companion library\n\nIf you need to manipulate the block's behavior at runtime you can connect to the PulseAudio server, send commands and receive data or events from it. You should be able to use any existing library that implements the PA client protocol over TCP/UNIX sockets (some examples: [Python](https://pypi.org/project/pulsectl/), [Rust](https://docs.rs/libpulse-binding/2.16.0/libpulse_binding/), [JavaScript](https://github.com/stanford-oval/node-pulseaudio#readme)), or you could even [write your own](https://freedesktop.org/software/pulseaudio/doxygen/). Libraries that manipulate PA over dbus won't work because we don't run the pulse dbus daemon. \n\nOn this note, we built a companion javascript library that exposes the most common use cases with an easy to use interface, these include changing the volume, listening to play/stop events, etc. \nYou can install it with ```npm install balena-audio```; see https://github.com/balena-io-modules/balena-audio for usage and examples.\n\n### Bluetooth\n\nBluetooth support for PulseAudio is enabled out of the box. Note that this only provides the backend that routes bluetooth packets over to PulseAudio, this does not include the Bluetooth agent that's required for initiating a connection and pairing devices. Check out our [Bluetooth block](https://github.com/balena-labs-projects/bluetooth) for an easy to use Bluetooth agent.\n\n## Supported devices\nThe audio block has been tested to work on the following devices:\n\n| Device Type  | Supported interface (driver) |\n| ------------- | ------------- |\n| Raspberry Pi (v1 / Zero / Zero W) | - Audio jack (`bcm2835`): ✔ \u003cbr\u003e- HDMI (`bcm2835`): ✔\u003cbr\u003e- I2S DAC (`snd-rpi-simple`): ✔ \u003cbr\u003e- USB (`snd-usb-audio`): ✔ |\n| Raspberry Pi 2 | - Audio jack (`bcm2835`): ✔ \u003cbr\u003e- HDMI (`bcm2835`): ✔\u003cbr\u003e- I2S DAC (`snd-rpi-simple`): ✔ \u003cbr\u003e- USB (`snd-usb-audio`): ✔ |\n| Raspberry Pi 3 | - Audio jack (`bcm2835`): ✔ \u003cbr\u003e- HDMI (`bcm2835`): ✔\u003cbr\u003e- I2S DAC (`snd-rpi-simple`): ✔ \u003cbr\u003e- USB (`snd-usb-audio`): ✔ |\n| Raspberry Pi 4 | - Audio jack (`bcm2835`): ✔ \u003cbr\u003e- HDMI (`bcm2835`): ✔\u003cbr\u003e- I2S DAC (`snd-rpi-simple`): ✔ \u003cbr\u003e- USB (`snd-usb-audio`): ✔ |\n| Intel NUC  | - Audio jack (`snd_hda_intel`): ✔\u003cbr\u003e- HDMI (`snd_hda_intel`): ✔\u003cbr\u003e- USB (`snd-usb-audio`): ✔ |\n| Jetson Nano \u003csup\u003e1\u003c/sup\u003e | - HDMI (`tegrahda`): ✘ \u003cbr\u003e- I2S DAC (`tegrasndt210ref`): ?\u003csup\u003e2\u003c/sup\u003e \u003cbr\u003e- USB (`snd-usb-audio`): ✔ |\n| BeagleBone Black | - USB (`snd-usb-audio`): ✔ |\n\n1: Audio block crashes if no USB/DAC present. See: https://github.com/balena-labs-projects/audio/issues/35\n2: Not tested. PR's welcome.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalena-io-experimental%2Faudio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbalena-io-experimental%2Faudio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalena-io-experimental%2Faudio/lists"}