Skip to content

Instantly share code, notes, and snippets.

@HakierGrzonzo
Created August 30, 2021 19:24
Show Gist options
  • Save HakierGrzonzo/dae1e4dacfdfe63565da8bcc7226abee to your computer and use it in GitHub Desktop.
Save HakierGrzonzo/dae1e4dacfdfe63565da8bcc7226abee to your computer and use it in GitHub Desktop.
Hyperiond music efect using cava
## Configuration file for CAVA. Default values are commented out. Use either ';' or '#' for commenting.
[general]
# Smoothing mode. Can be 'normal', 'scientific' or 'waves'. DEPRECATED as of 0.6.0
; mode = normal
# Accepts only non-negative values.
; framerate = 60
# 'autosens' will attempt to decrease sensitivity if the bars peak. 1 = on, 0 = off
# new as of 0.6.0 autosens of low values (dynamic range)
# 'overshoot' allows bars to overshoot (in % of terminal height) without initiating autosens. DEPRECATED as of 0.6.0
; autosens = 1
; overshoot = 20
# Manual sensitivity in %. If autosens is enabled, this will only be the initial value.
# 200 means double height. Accepts only non-negative values.
; sensitivity = 100
# The number of bars (0-200). 0 sets it to auto (fill up console).
# Bars' width and space between bars in number of characters.
bars = 4
; bar_width = 2
; bar_spacing = 1
# Lower and higher cutoff frequencies for lowest and highest bars
# the bandwidth of the visualizer.
# Note: there is a minimum total bandwidth of 43Mhz x number of bars.
# Cava will automatically increase the higher cutoff if a too low band is specified.
; lower_cutoff_freq = 50
; higher_cutoff_freq = 10000
# Seconds with no input before cava goes to sleep mode. Cava will not perform FFT or drawing and
# only check for input once per second. Cava will wake up once input is detected. 0 = disable.
; sleep_timer = 0
[input]
# Audio capturing method. Possible methods are: 'pulse', 'alsa', 'fifo', 'sndio' or 'shmem'
# Defaults to 'pulse', 'alsa' or 'fifo', in that order, dependent on what support cava was built with.
#
# All input methods uses the same config variable 'source'
# to define where it should get the audio.
#
# For pulseaudio 'source' will be the source. Default: 'auto', which uses the monitor source of the default sink
# (all pulseaudio sinks(outputs) have 'monitor' sources(inputs) associated with them).
#
# For alsa 'source' will be the capture device.
# For fifo 'source' will be the path to fifo-file.
# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address
; method = pulse
; source = auto
; method = alsa
; source = hw:Loopback,1
; method = fifo
; source = /tmp/mpd.fifo
; sample_rate = 44100
; sample_bits = 16
; method = shmem
; source = /squeezelite-AA:BB:CC:DD:EE:FF
; method = portaudio
; source = auto
[output]
# Output method. Can be 'ncurses', 'noncurses' or 'raw'.
# 'noncurses' uses a custom framebuffer technique and draws only changes
# from frame to frame. 'ncurses' is default if supported
#
# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data
# stream of the bar heights that can be used to send to other applications.
# 'raw' defaults to 200 bars, which can be adjusted in the 'bars' option above.
method = raw
# Visual channels. Can be 'stereo' or 'mono'.
# 'stereo' mirrors both channels with low frequencies in center.
# 'mono' outputs left to right lowest to highest frequencies.
# 'mono_option' set mono to either take input from 'left', 'right' or 'average'.
channels = mono
; mono_option = average
# Raw output target. A fifo will be created if target does not exist.
; raw_target = /dev/stdout
# Raw data format. Can be 'binary' or 'ascii'.
data_format = ascii
# Binary bit format, can be '8bit' (0-255) or '16bit' (0-65530).
; bit_format = 16bit
# Ascii max value. In 'ascii' mode range will run from 0 to value specified here
ascii_max_range = 1000
# Ascii delimiters. In ascii format each bar and frame is separated by a delimiters.
# Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)).
bar_delimiter = 59
frame_delimiter = 10
[color]
# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow.
# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires
# ncurses output method and a terminal that can change color definitions such as Gnome-terminal or rxvt.
# if supported, ncurses mode will be force on if user defined colors are used.
# default is to keep current terminal color
; background = default
; foreground = default
# Gradient mode, only hex defined colors (and thereby ncurses mode) are supported,
# background must also be defined in hex or remain commented out. 1 = on, 0 = off.
# You can define as many as 8 different colors. They range from bottom to top of screen
; gradient = 1
; gradient_count = 8
; gradient_color_1 = '#59cc33'
; gradient_color_2 = '#80cc33'
; gradient_color_3 = '#a6cc33'
; gradient_color_4 = '#cccc33'
; gradient_color_5 = '#cca633'
; gradient_color_6 = '#cc8033'
; gradient_color_7 = '#cc5933'
; gradient_color_8 = '#cc3333'
[smoothing]
# Percentage value for integral smoothing. Takes values from 0 - 100.
# Higher values means smoother, but less precise. 0 to disable.
; integral = 77
# Disables or enables the so-called "Monstercat smoothing" with or without "waves". Set to 0 to disable.
; monstercat = 1
; waves = 0
# Set gravity percentage for "drop off". Higher values means bars will drop faster.
# Accepts only non-negative values. 50 means half gravity, 200 means double. Set to 0 to disable "drop off".
gravity = 100
# In bar height, bars that would have been lower that this will not be drawn.
; ignore = 0
[eq]
# This one is tricky. You can have as much keys as you want.
# Remember to uncomment more then one key! More keys = more precision.
# Look at readme.md on github for further explanations and examples.
; 1 = 1 # bass
; 2 = 1
; 3 = 1 # midtone
; 4 = 1
; 5 = 1 # treble
[Unit]
Description=Sound visulizer animation
Wants=sound.target
After=sound.target hyperiond.service
[Service]
ExecStart=/usr/bin/bash -c "/usr/bin/cava -p /etc/hyperion/custom-effects/cava.conf > /tmp/hyperionRGB_cava"
Restart=always
RestartSec=5
KillMode=process
TimeoutSec=10
[Install]
WantedBy=default.target
{
"name": "Test music effect",
"script": "music.py",
"args": {}
}
import hyperion, time, os
from threading import Thread
COLOR_FIFO = "/tmp/hyperionRGB_color"
CAVA_FIFO = "/tmp/hyperionRGB_cava"
class colorMixer:
def __init__(self) -> None:
self.isAllowedToRun = True
# make fifos to read cava and color
try:
os.mkfifo(COLOR_FIFO)
# change to your username
os.system("chown hakiergrzonzo {}".format(COLOR_FIFO))
except Exception as e:
print(e)
try:
os.mkfifo(CAVA_FIFO)
# change to your username
os.system("chown hakiergrzonzo {}".format(CAVA_FIFO))
except Exception as e:
print(e)
self.color = (255, 255, 255)
self.cavaErr = ""
self.colorErr = ""
self.cava = (1, 1, 1, 1)
self.cavaThread = Thread(target=self.cavaReader)
self.cavaThread.start()
self.colorThread = Thread(target=self.colorReader)
self.colorThread.start()
def cavaReader(self):
cavaFifo = open(CAVA_FIFO)
while self.isAllowedToRun:
try:
for line in cavaFifo:
if not self.isAllowedToRun:
break
cavaRaw = []
for field in line.strip().split(";"):
if len(field) > 0:
cavaRaw.append(max(min(int(field.strip()), 1000), 0) / 1000)
self.cava = cavaRaw[0], cavaRaw[1], cavaRaw[2], cavaRaw[3]
time.sleep(.04)
except Exception as e:
self.cavaErr = str(e)
print("CavaReader:", e, flush=True)
time.sleep(1)
def colorReader(self):
colorFifo = open(COLOR_FIFO)
while self.isAllowedToRun:
try:
for line in colorFifo:
if not self.isAllowedToRun:
break
colorRaw = []
for field in line.strip().split(";"):
colorRaw.append(float(field.strip()))
self.color = colorRaw[0], colorRaw[1], colorRaw[2]
time.sleep(.1)
except Exception as e:
self.colorErr = str(e)
print("colorReader:", e, flush=True)
time.sleep(1)
def getColor(self):
return tuple(int(max(x, .3) * self.cava[0]) for x in self.color)
colorObj = colorMixer()
while not hyperion.abort():
try:
color = colorObj.getColor()
hyperion.setColor(color[0], color[1], color[2])
time.sleep(0.05)
except ValueError as e:
print(e, flush=True)
colorObj.isAllowedToRun = False
colorObj.colorThread.join()
colorObj.cavaThread.join()
print("I have been killed", flush=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment