OBS stops responding when setting scene within timer callback (Python Script)

redynotredy

New Member
Hi all,

I've been working on a python script which is a countdown timer pretty much like the Advanced Scene Switcher, but with customised funcionality for myself.

The timer callback seems to work just fine, however when I try to set the scene from within the timer_callback function, the log prints everything right before 0, and everything stops responding.

The log file prints 0, but doesn't print anything afterwards.

The most intriguing part is that outside of the callback function, setting the scene has no issues, meaning to say there is a problem specifically only when setting the scene inside a timer.

Any help is appreciated!
1660404845847.png
 
In script_properties, you call obs_frontend_get_scenes(), and then source_list_release. But the docs for obs_frontend_get_scenes say to call obs_frontend_source_list_free(). Not sure whether there is a difference in the implementation, but I'd go with the dox.

A bigger issue would seem to be: you are releasing (or trying to release) "scenes" in script_properties, but then referencing the variable in the timer_callback. Since the list has been released, it seems to me that all bets are off as to whether anything in scenes is still valid.

If "source" is the name of the scene, why not just call obs_get_scene_by_name in the timer callback (and obs_scene_release after obs_frontend_set_current_scene), rather than obs_frontend_get_scene_names and the dubious "scenes" variable? I have a script using that method in a timer and it works fine.
 

redynotredy

New Member
Hi John, thank you for the assistance. I didn't realise there was a function to get the scene object from the name, I'm rather new to scripting in OBS, thank you for the feedback

Thanks for catching the source_list_release part, I copied it over from another script I was working on without paying much attention.

I've attempted to retrieve the scene object using obs_get_scene_by_name and it shows that it's a <Swig Object of type 'obs_scene_t *' at (memory address)>. Passing that object as an argument to obs_frontend_set_current_scene however doesn't give any results i.e. the countdown works as intended but the scene does not change. At least OBS isn't crashing now
 

redynotredy

New Member
Hi, I just looked at the OBS documentation again and it tells us that obs_frontend_set_current_scene only accepts obs_source_t * as an argument, instead of the obs_scene_t * type. At this point when I get a source type instead of a scene type using obs_get_source_by_name, OBS stops responding again.

However, this time I had a media source playing audio, and it continued playing the audio despite the software not responding. Is there any way we can fix this? May I have some example code to reference?
 
My Lua code (executed in a timer callback) calls obs_get_scene_by_name, and then obs_scene_get_source to get the source:
local new_scene = obs.obs_get_scene_by_name(scene_name) if new_scene ~= nil then obs.obs_frontend_set_current_scene(obs.obs_scene_get_source(new_scene)) obs.obs_scene_release(new_scene) end

Most likely something you are doing is locking up the UI thread, but the other OBS threads continue to run, playing your audio etc.

My experience in writing OBS Lua script bugs is
  • messing up reference count (by not calling xxx_release, or by calling xxx_release when you shouldn't) usually causes a crash, either immediately, or when you exit OBS
  • lockups of the UI thread can be due to mutex deadlocks
The API docs are pretty good telling you about reference-counted items. Unfortunately, there is no mention in the API docs of the many mutexes used internally by OBS.

Python and Lua in OBS aren't multi-thread safe, so each script has a mutex that is locked when any part of that script is running. Structures such as the list-of-sources etc have a mutex to protect insertion and deletion. Some examples and info
https://obsproject.com/forum/thread...-when-reloading-script-with-lua-filter.84423/
https://github.com/obsproject/obs-studio/issues/5282

If you can build OBS and run it in the debugger, you can use stack traces to find the mutexes in question, but it can be tedious.
 
Top