Skip to content

Instantly share code, notes, and snippets.

@daisyUniverse
Created July 18, 2026 10:09
Show Gist options
  • Select an option

  • Save daisyUniverse/6401c0d3629490a9e13cd04b58ffe329 to your computer and use it in GitHub Desktop.

Select an option

Save daisyUniverse/6401c0d3629490a9e13cd04b58ffe329 to your computer and use it in GitHub Desktop.
Basic-Scene-Switcher

Basic Scene Switcher

I wrote this because the AUR build of Advanced-Scene-Switcher was not working All I wanted to do was to be able to change my OBS scene to the monitor my mouse was hovering over the corrosponding monitor

requirements:

  • hyprland & hyprctl
  • OBS + WebSockets
  • python3 + WebSockets
  • fish shell

It basically just runs in a loop and checks if your monitor is to the left or right of a margin value if it is, it invokes the python script to tell OBS what scene to switch to using WebSockets..

It will automatically just try to switch between whatever the first two scenes are in OBS, and in fact is mostly made with two monitors in mind, so it only checks the horizontal position of the cursor and simply checks if it's above a certain value (Line 12 in switcher.fish)

This can be upgraded by making it check for 2D zones to allow it to change in arbitrary areas

Demo of it working in action on my bisky...

#!/bin/fish
# Get Focused Monitor
# Loops hyprctl cursorpos to detect when the cursor crosses into another monitor
# When this is detected, fire off a python script to change OBS to the appropriate scene
# Daisy Universe [S]
# 07 . 18 . 26
# This is designed for a dual monitor setup, so only one margin value is needed
# ( This is the global coordinate of the right edge of the left monitor )
set margin "2915"
# Gets a list of scenes from OBS, switched by index
function get_scenes
set scenes (python3 ~/githell/less-advanced/switcher.py)
string split ', ' $scenes
end
set scenes (get_scenes)
function get_focused_monitor
set pos (hyprctl cursorpos | cut --delimiter "," --fields 1)
if test "$pos" -gt "$margin"
echo 1
else
echo 2
end
end
set current_index (get_focused_monitor)
function switch_scene
python3 ~/githell/less-advanced/switcher.py $argv > /dev/null
end
while true
set current_index "$(get_focused_monitor)"
sleep 1
if test "$current_index" != "$(get_focused_monitor)"
if test "$current_index" = 2
switch_scene $scenes[$current_index]
else
switch_scene $scenes[$current_index]
end
notify-send "Switching to" $scenes[$current_index] -t 1000
echo "Switching to" $scenes[$current_index]
end
end
#!/bin/python3
# OBS Scene Switcher - commands OBS to switch to argv[1] using websockets
# Heavily modified script from mud_punk on the OBS Support forum
# https://obsproject.com/forum/threads/python-script-to-connect-to-obs-websocket-server-help.173395/#post-639549
# Daisy Universe [S]
# 07 . 18 . 26
import base64
import hashlib
import json
import sys
import websocket
host = "localhost"
port = 4455 #or whatever port you use
password = "Put your OBS WebSocket password here..."
id = 1
ws = websocket.WebSocket()
url = "ws://{}:{}".format(host, port)
ws.connect(url)
def _build_auth_string(salt, challenge):
secret = base64.b64encode(
hashlib.sha256(
(password + salt).encode('utf-8')
).digest()
)
auth = base64.b64encode(
hashlib.sha256(
secret + challenge.encode('utf-8')
).digest()
).decode('utf-8')
return auth
def _auth():
message = ws.recv()
result = json.loads(message)
server_version = result['d'].get('obsWebSocketVersion')
auth = _build_auth_string(result['d']['authentication']['salt'], result['d']['authentication']['challenge'])
payload = {
"op": 1,
"d": {
"rpcVersion": 1,
"authentication": auth,
"eventSubscriptions": 1000
}
}
ws.send(json.dumps(payload))
message = ws.recv()
# Message Identified...or so we assume...probably good to check if this is empty or not.
result = json.loads(message)
_auth()
def set_scene(scene):
# lets switch to a scene
payload = {"op": 6, "d": {"requestId": "SetMeSomeFrigginScenesYo", "requestType": "SetCurrentProgramScene", "requestData": {"sceneName":scene}}}
ws.send(json.dumps(payload))
message=ws.recv()
return message
def get_scenes():
# get me my damn scenes already
scenes = ""
delimiter = ", "
payload = {"op": 6, "d": {"requestId": "GetMeSomeFrigginScenesYo", "requestType": "GetSceneList", "requestData": {}}}
ws.send(json.dumps(payload))
message=ws.recv()
message = json.loads(message)
for i in message['d']['responseData']['scenes']:
if scenes != "": delimiter = ""
scenes = scenes + i['sceneName'] + delimiter
return scenes
if len(sys.argv) > 1:
scene = sys.argv[1]
set_scene(scene)
else:
print(get_scenes())
ws.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment