OBS Lua .. On_Event_Replay_Buffer (not working)

sutex

New Member
This Lua script is used in conjunction with VoiceMacro voice command software, and VMRemote.exe, and bat files to synchronize my VM variables when either the Replay buffer button is started or stopped. (https://www.voicemacro.net/documentation/#RemoteControl_VoiceMacro)

The issue is that when I click Start Replay Buffer, the BAT file associated with it runs, and a few seconds later, my other BAT file, which is supposed to run when I click Stop Replay Buffer, also runs. The end result is that the replay buffer does not start. I'm new to OBS and Lua, only a few days, so I have no idea where the problem may lie. Any help would be greatly appreciated.

Note: I did try a powershell script by modifying line 35: "(*.exe *.bat *.sh);" with *.ps1 in another version, but those.ps1 files would not work independently; the two bat files do work independently when clicking on them.

Lua:
obs         = obslua
start_script_name = ""
end_script_name = ""

-- This Lua script is used in conjunction with VoiceMacro, VMRemote.exe, and bat files to synchronize my VM variables when either the Replay buffer button is started or stopped. (https://www.voicemacro.net/documentation/#RemoteControl_VoiceMacro)

function on_event(event)
    if event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED then
        if start_script_name ~= "start_script" then
            obs.script_log(obs.LOG_INFO, "executing " .. start_script_name)
            os.execute(start_script_name)
        end
    end
    if event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED then
        if end_script_name ~= "end_script" then
            obs.script_log(obs.LOG_INFO, "executing " .. end_script_name)
            os.execute(end_script_name)
        end
    end
end
-----------------------------------------------------------------------------------------------------

function script_update(settings)
    start_script_name = obs.obs_data_get_string(settings, "start_script_name")
    end_script_name = obs.obs_data_get_string(settings, "end_script_name")
end

function script_description()
    return "run a script / executable when the stream starts or ends"
end

function script_properties()
    props = obs.obs_properties_create()

    obs.obs_properties_add_path(props, "start_script_name", "Start Buffer", obs.OBS_PATH_FILE, "(*.exe *.bat *.sh);;(*.*)", NULL)
    obs.obs_properties_add_path(props, "end_script_name", "End Buffer", obs.OBS_PATH_FILE, "(*.exe *.bat *.sh);;(*.*)", NULL)
        
    return props
end

function script_defaults(settings)
    obs.obs_data_set_default_string(settings, "start_script_name", "start_script")
    obs.obs_data_set_default_string(settings, "end_script_name", "end_script")
end

function script_load(settings)
    obs.obs_frontend_add_event_callback(on_event)
end

-- This Lua script was is an adaptation of ntoff work, streamcmd.lua

-- Credits: (https://github.com/ntoff/obs_scripts/blob/master/streamcmd.lua)
-- Thank you!
 

sutex

New Member
A stripped-down version of the code above.
I used io.popen and not os.execute and added VMRemote.exe to PATH in Environment Variables, and the script below is now running the bat files, and the replay buffer button turns on and off without any issues. It does seem to flash two CMD windows for each bat file call, but hey, I can live with that. Any suggestions on how to do it better? Let me know.

Lua:
obs = obslua
start_script_name = '"C:\\Program Files\\obs-studio\\data\\obs-plugins\\frontend-tools\\scripts\\start_script.bat"'
end_script_name = '"C:\\Program Files\\obs-studio\\data\\obs-plugins\\frontend-tools\\scripts\\end_script.bat"'

function on_event(event)
    if event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED
    then io.popen(start_script_name)
    end

    if event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED
    then io.popen(end_script_name)
    end
end

function script_load(settings)
  obs.obs_frontend_add_event_callback(on_event)
end
 

Suslik V

Active Member
I think it is better to close the file handle:
Lua:
handle = io.popen(start_script_name)
handle:close()
os.execute() blocks scripts execution (and thus blocks OBS UI) until batch file completed (or cmd window closed). But, let's say, this secures you from mistakes in a threading of concurrent tasks.

You can use script_path() to get script's path:
Lua:
local start_script_name = script_path() .. "start_script.bat"

By writing elseif it will be easier to read the code.
 

sutex

New Member
I think it is better to close the file handle:
Lua:
handle = io.popen(start_script_name)
handle:close()
os.execute() blocks scripts execution (and thus blocks OBS UI) until batch file completed (or cmd window closed). But, let's say, this secures you from mistakes in a threading of concurrent tasks.

You can use script_path() to get script's path:
Lua:
local start_script_name = script_path() .. "start_script.bat"

By writing elseif it will be easier to read the code.
I tried your suggestions and the script would not function.
 

Suslik V

Active Member
strange... It works pretty fine for me.

My code (all files in the same dir):
"obs-test-bat.lua"
Lua:
local obs = obslua
local start_script_name = script_path() .. "start_script.bat"
local end_script_name = script_path() .. [[end_script.bat]]

function script_description()
    return "Executes bat files:\n" ..
    "'" .. start_script_name .. "' on REPLAY_BUFFER_STARTED\n\n" ..
    "'" .. end_script_name .. "' on REPLAY_BUFFER_STOPPED"
end

function on_event(event)
    if event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED
        then os.execute(start_script_name)
    elseif event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED
        then os.execute(end_script_name)
    end
end

function script_load(settings)
    obs.obs_frontend_add_event_callback(on_event)
end

"start_script.bat"
Lua:
echo start_script_bat
timeout 7

"end_script.bat"
Lua:
echo end_script_bat
timeout 5
 

sutex

New Member
strange... It works pretty fine for me.

My code (all files in the same dir):
"obs-test-bat.lua"
Lua:
local obs = obslua
local start_script_name = script_path() .. "start_script.bat"
local end_script_name = script_path() .. [[end_script.bat]]

function script_description()
    return "Executes bat files:\n" ..
    "'" .. start_script_name .. "' on REPLAY_BUFFER_STARTED\n\n" ..
    "'" .. end_script_name .. "' on REPLAY_BUFFER_STOPPED"
end

function on_event(event)
    if event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED
        then os.execute(start_script_name)
    elseif event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED
        then os.execute(end_script_name)
    end
end

function script_load(settings)
    obs.obs_frontend_add_event_callback(on_event)
end

"start_script.bat"
Lua:
echo start_script_bat
timeout 7

"end_script.bat"
Lua:
echo end_script_bat
timeout 5
That's not working either the bat files are not sending their data to Voice Macro, so it can set the variables to on or off And I'm unsure why this [[end_script.bat]] is in brackets. And why you have used os.execute instead of handle = io.popen(start_script_name).

I supect the root cause is local start_script_name = script_path()


Thanks for the feedback, learning here :)
 

sutex

New Member
Below, when clicking the replay buffer, it turns on and then immediately off. When using os.execute, this does not happen when using io.popen. In either case, the scripts send the needed information to VM.
I'm using this io.popen version https://obsproject.com/forum/threads/obs-lua-on_event_replay_buffer-not-working.175417/post-646656

Lua:
obs = obslua
start_script_name = '"C:\\Program Files\\obs-studio\\data\\obs-plugins\\frontend-tools\\scripts\\start_script.bat"'
end_script_name = '"C:\\Program Files\\obs-studio\\data\\obs-plugins\\frontend-tools\\scripts\\end_script.bat"'

function on_event(event)
    if event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED
        then os.execute(start_script_name)
    elseif event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED
        then os.execute(end_script_name)
    end
end

function script_load(settings)
  obs.obs_frontend_add_event_callback(on_event)
end
 
Last edited:

Suslik V

Active Member
You need to check what your "Voice Macro" application do and how your batches communicate with it. It has nothing to do with OBS programming. Probably, you need to ask in Support section of the forum if someone using same util.

The .lua script itself executes the batch file once and didn't trigger other events. If your mouse doubles clicks by itself (or hands are shaking) then as I mentioned above UI of OBS is locked until batch of commands ends, but UI "remembers" all your clicks and will execute them all as soon as the batch file ends. By timeout of 7 seconds you can press a lot of buttons in OBS UI (for example, you can enter Studio Mode and Exit - just try it! os.execute will help to understand how it works :)

As for the double square brackets.
It is for example, in the posted code they do nothing. Brackets is for the [[text with back slash "\" (the escaping character)]] - just replacement of the '"\\"', more details: https://stackoverflow.com/questions/21246668/whats-the-point-of-nesting-brackets-in-lua
 

sutex

New Member
Voice Marco is set up, and that is not the issue. There is a link in my first post if you need to understand how it works. Its OBS and the scripts that you have suggested that have not worked; the one I made works, so I will stick with that for now. I'll read up on the timeout and UI OBS and see if that relevant for my use. thanks.
 
Top