cg2121 / obs-advanced-timer Goto Github PK
View Code? Open in Web Editor NEWLicense: GNU General Public License v2.0
License: GNU General Public License v2.0
I have been trying OBS 0.27 rc2, it looks like it has an issue with the script, it behaves erratically.
It looks like when I hit Start/Stop timer, it will reset the dialogue and load some kind of defaults.
Is this the issue with OBS or with the script?
I am not sure exactly what I'm supposed to be downloading it's for broadcasting videos and I'm having more trouble than ever
Just a heads up. If you load the script on two scene collections, it will prevent the first scene collection from loading and cause obs to crash.
To fix this situation I had to rename the script, then my scene collections started loading again.
I suppose you need copies of the script to have it work multiple times. Would that work?
Before the last update, with studio mode, the countdown reset when i push scene from preview to live but after the last update, the countdown don't reset when i push it from preview to live scene. Possible to fix it ? Because, i think all people use it for countdown want this " option " ;)
Thx for your great work !
OBS 26.0.2, Mac High Sierra
Tried this timer but was unable to select the text source that I set up previously. In fact it's not showing many of my text sources at all. Only four are shown, whereas the standard OBS countdown sees all my text sources and works OK.
This script causes my OBS CPU usage to go up from 2.5 % to 6 %. After looking at the source, I can see that this is because you’re using script_tick()
to update the timer once per rendered frame (e.g. 60 times per second if using 60 fps). However, my timer only uses minutes and seconds. 59 out of 60 updates per second are not needed because the text doesn’t change.
My suggestion would be to use timer_add()
instead and be called by OBS only as often as required.
I know that it’s possible to use sub-second precision in a timer by changing the format string. Therefore, setting a 1000 ms timer is not always sufficient. Instead, the timer interval should either be manually configurable, or derived automatically depending on the format string placeholders used.
any way to choose the entire folder in the source instead of just 1 item?
When the count down time is reached, it will be good to have an option to switch to the desired scene.
This will help people to start programs/shows on time.
People can switch to a promo scene or the stage scene.
For some time now, every time I start OBS Studio for the first time I have a crash that prevents the first start.
Very strange bug, because when I click a second time, absolutely no stream problems, but the problem comes back every time I start my PC.
Following my research and although I do not know if it is a combination of several problems, I noticed that by just removing the script "advanced-timer.lua" I had no more crash, moreover in my logs at the time of the crash the last line of the log file concerns advanced-timer.lua
I don't know if it's from me or not ^^' I didn't test it on other pc, but I want to share this with you just in case and if you have a solution for me, because I love this script it does perfectly what I want and in automatic without unnecessary surplus.
I specify that I have the last version of the script to date and that I am on version 29.1.0-beta4 (but I also have this problem on the stable version :/)
Thanks for reading, I hope it will help if I'm not the only one to have this problem, bravo for your work !
👍
The idea is when the countdown timer reaches 0, it displays text and then waits a set amount of time before resetting and counting down again. I could create a script that times hotkeys, but I feel it would be clunky having a script ontop of a script running.
Hi, suggestion regarding the format of the timer
Could it be implemented that output of the timer be customisable?
for example:
Currently the timer shows as 00:00:00 (or 00:00:00.0)
Customized format could allow: 00h:00m:00s / 00hr:00min:00sec / 00hrs:00mins:00secs / etc
Hello, i added new modes for use:
mode == "Specific date and time record"
mode == "Specific time record"
feel free to use or deny it
code:
obs = obslua
source_name = ""
source_name2 = ""
stop_text = ""
mode = ""
a_mode = ""
format = ""
activated = false
global = false
timer_active = false
settings_ = nil
orig_time = 0
cur_time = 0
cur_ns = 0
cur_ns_rec = 0
up_when_finished = false
up = false
paused = false
recording = false
RECend_time = 0
REChour = 0
RECminute = 0
RECsecond = 0
hotkey_id_reset = obs.OBS_INVALID_HOTKEY_ID
hotkey_id_pause = obs.OBS_INVALID_HOTKEY_ID
function Startrecord()
obs.obs_frontend_recording_start()
recording = true
RECend_time = delta_time(-1, -1, -1, REChour, RECminute, RECsecond)
end
function Stoprecord()
obs.obs_frontend_recording_stop()
recording = false
end
function delta_time(year, month, day, hour, minute, second)
local now = os.time()
if (year == -1) then
year = os.date("%Y", now)
end
if (month == -1) then
month = os.date("%m", now)
end
if (day == -1) then
day = os.date("%d", now)
end
local future = os.time{year=year, month=month, day=day, hour=hour, min=minute, sec=second}
local seconds = os.difftime(future, now)
if (seconds < 0) then
seconds = seconds + 84600
end
return seconds * 1000000000
end
function set_time_text(ns, text, source_name)
local ms = math.floor(ns / 1000000)
if string.match(text, "%%0H") then
local hours_infinite = math.floor(ms / 3600000)
minutes_infinite = string.format("%02d", hours_infinite)
text = string.gsub(text, "%%0H", hours_infinite)
end
if string.match(text, "%%0M") then
local minutes_infinite = math.floor(ms / 60000)
minutes_infinite = string.format("%02d", minutes_infinite)
text = string.gsub(text, "%%0M", minutes_infinite)
end
if string.match(text, "%%0S") then
local seconds_infinite = math.floor(ms / 1000)
seconds_infinite = string.format("%02d", seconds_infinite)
text = string.gsub(text, "%%0S", seconds_infinite)
end
if string.match(text, "%%0h") then
local hours = math.floor(ms / 3600000) % 24
hours = string.format("%02d", hours)
text = string.gsub(text, "%%0h", hours)
end
if string.match(text, "%%0m") then
local minutes = math.floor(ms / 60000) % 60
minutes = string.format("%02d", minutes)
text = string.gsub(text, "%%0m", minutes)
end
if string.match(text, "%%0s") then
local seconds = math.floor(ms / 1000) % 60
seconds = string.format("%02d", seconds)
text = string.gsub(text, "%%0s", seconds)
end
if string.match(text, "%%H") then
local hours_infinite = math.floor(ms / 3600000)
text = string.gsub(text, "%%HH", hours_infinite)
end
if string.match(text, "%%M") then
local minutes_infinite = math.floor(ms / 60000)
text = string.gsub(text, "%%MM", minutes_infinite)
end
if string.match(text, "%%S") then
local seconds_infinite = math.floor(ms / 1000)
text = string.gsub(text, "%%S", seconds_infinite)
end
if string.match(text, "%%h") then
local hours = math.floor(ms / 3600000) % 24
text = string.gsub(text, "%%h", hours)
end
if string.match(text, "%%m") then
local minutes = math.floor(ms / 60000) % 60
text = string.gsub(text, "%%m", minutes)
end
if string.match(text, "%%s") then
local seconds = math.floor(ms / 1000) % 60
text = string.gsub(text, "%%s", seconds)
end
if string.match(text, "%%d") then
local days = math.floor(ms / 86400000)
text = string.gsub(text, "%%d", tostring(days))
end
local decimal = string.format("%.3d", ms % 1000)
if string.match(text, "%%3t") then
decimal = string.sub(decimal, 1, 3)
text = string.gsub(text, "%%3t", decimal)
end
if string.match(text, "%%2t") then
decimal = string.sub(decimal, 1, 2)
text = string.gsub(text, "%%2t", decimal)
end
if string.match(text, "%%t") then
decimal = string.sub(decimal, 1, 1)
text = string.gsub(text, "%%t", decimal)
end
local source = obs.obs_get_source_by_name(source_name)
if source ~= nil then
local settings = obs.obs_data_create()
obs.obs_data_set_string(settings, "text", text)
obs.obs_source_update(source, settings)
obs.obs_data_release(settings)
obs.obs_source_release(source)
end
end
function script_tick(sec)
if timer_active == false and recording == false then
return
end
local delta = obs.os_gettime_ns() - orig_time
if mode == "Countup" or mode == "Streaming timer" or mode == "Recording timer" or up == true then
cur_ns = cur_time + delta
cur_ns_rec = RECend_time - delta
else
cur_ns = cur_time - delta
cur_ns_rec = RECend_time - delta
end
set_time_text(cur_ns_rec, format, source_name2)
if cur_ns < 1 and (mode == "Countdown" or mode == "Specific time" or mode == "Specific date and time") then
if up_when_finished == false then
set_time_text(cur_ns, stop_text,source_name)
stop_timer()
start_timer()
stop_timer()
return
else
cur_time = 0
up = true
start_timer()
return
end
end
if cur_ns < 1 and (mode == "Specific time record" or mode == "Specific date and time record") and recording == false then
if up_when_finished == false then
set_time_text(cur_ns, stop_text,source_name)
Startrecord()
start_timer()
return
else
Startrecord()
set_time_text(cur_ns, stop_text,source_name)
cur_time = 0
up = true
start_timer()
return
end
end
if recording == true then
set_time_text(cur_ns_rec, format,source_name)
if cur_ns_rec < 1 and (mode == "Specific time record" or mode == "Specific date and time record") then
Stoprecord()
stop_timer()
set_time_text(cur_ns_rec, "OK.",source_name)
set_time_text(cur_ns_rec, "OK.",source_name2)
end
else
set_time_text(cur_ns, format,source_name)
end
end
function start_timer()
timer_active = true
orig_time = obs.os_gettime_ns()
end
function stop_timer()
timer_active = false
end
function on_event(event)
if event == obs.OBS_FRONTEND_EVENT_STREAMING_STARTED then
if mode == "Streaming timer" then
cur_time = 0
stop_timer()
start_timer()
end
elseif event == obs.OBS_FRONTEND_EVENT_STREAMING_STOPPED then
if mode == "Streaming timer" then
stop_timer()
end
elseif event == obs.OBS_FRONTEND_EVENT_RECORDING_STARTED then
recording = true
if mode == "Recording timer" then
cur_time = 0
stop_timer()
start_timer()
end
elseif event == obs.OBS_FRONTEND_EVENT_RECORDING_STOPPED then
recording = false
stop_timer()
if mode == "Recording timer" then
stop_timer()
end
end
end
function activate(activating)
if activated == activating then
return
end
if (mode == "Streaming timer" or mode == "Recording timer") then
return
end
activated = activating
if activating then
if global then
return
end
script_update(settings_)
end
end
function activate_signal(cd, activating)
local source = obs.calldata_source(cd, "source")
if source ~= nil then
local name = obs.obs_source_get_name(source)
if (name == source_name) then
activate(activating)
end
end
end
function source_activated(cd)
activate_signal(cd, true)
end
function source_deactivated(cd)
activate_signal(cd, false)
end
function reset(pressed)
if not pressed then
return
end
if mode == "Streaming timer" or mode == "Recording timer" then
return
end
script_update(settings_)
end
function on_pause(pressed)
if not pressed then
return
end
if mode == "Streaming timer" or mode == "Recording timer" then
return
end
if cur_ns < 1 then
reset(true)
end
if timer_active then
stop_timer()
cur_time = cur_ns
paused = true
else
stop_timer()
start_timer()
paused = false
end
end
function pause_button_clicked(props, p)
on_pause(true)
return true
end
function reset_button_clicked(props, p)
reset(true)
return true
end
function settings_modified(props, prop, settings)
local mode_setting = obs.obs_data_get_string(settings, "mode")
local p_duration = obs.obs_properties_get(props, "duration")
local p_year = obs.obs_properties_get(props, "year")
local p_month = obs.obs_properties_get(props, "month")
local p_day = obs.obs_properties_get(props, "day")
local p_hour = obs.obs_properties_get(props, "hour")
local p_minutes = obs.obs_properties_get(props, "minutes")
local p_seconds = obs.obs_properties_get(props, "seconds")
local p_stop_text = obs.obs_properties_get(props, "stop_text")
local p_a_mode = obs.obs_properties_get(props, "a_mode")
local button_pause = obs.obs_properties_get(props, "pause_button")
local button_reset = obs.obs_properties_get(props, "reset_button")
local up_finished = obs.obs_properties_get(props, "countup_countdown_finished")
local p_rechour = obs.obs_properties_get(props, "REChour")
local p_recminutes = obs.obs_properties_get(props, "RECminutes")
local p_recseconds = obs.obs_properties_get(props, "RECseconds")
if (mode_setting == "Countdown") then
obs.obs_property_set_visible(p_duration, true)
obs.obs_property_set_visible(p_year, false)
obs.obs_property_set_visible(p_month, false)
obs.obs_property_set_visible(p_day, false)
obs.obs_property_set_visible(p_hour, false)
obs.obs_property_set_visible(p_minutes, false)
obs.obs_property_set_visible(p_seconds, false)
obs.obs_property_set_visible(p_stop_text, true)
obs.obs_property_set_visible(button_pause, true)
obs.obs_property_set_visible(button_reset, true)
obs.obs_property_set_visible(p_a_mode, true)
obs.obs_property_set_visible(up_finished, true)
obs.obs_property_set_visible(p_rechour, false)
obs.obs_property_set_visible(p_recminutes, false)
obs.obs_property_set_visible(p_recseconds, false)
elseif (mode_setting == "Countup") then
obs.obs_property_set_visible(p_duration, false)
obs.obs_property_set_visible(p_year, false)
obs.obs_property_set_visible(p_month, false)
obs.obs_property_set_visible(p_day, false)
obs.obs_property_set_visible(p_hour, false)
obs.obs_property_set_visible(p_minutes, false)
obs.obs_property_set_visible(p_seconds, false)
obs.obs_property_set_visible(p_stop_text, false)
obs.obs_property_set_visible(button_pause, true)
obs.obs_property_set_visible(button_reset, true)
obs.obs_property_set_visible(p_a_mode, true)
obs.obs_property_set_visible(up_finished, false)
obs.obs_property_set_visible(p_rechour, false)
obs.obs_property_set_visible(p_recminutes, false)
obs.obs_property_set_visible(p_recseconds, false)
elseif (mode_setting == "Specific time") then
obs.obs_property_set_visible(p_duration, false)
obs.obs_property_set_visible(p_year, false)
obs.obs_property_set_visible(p_month, false)
obs.obs_property_set_visible(p_day, false)
obs.obs_property_set_visible(p_hour, true)
obs.obs_property_set_visible(p_minutes, true)
obs.obs_property_set_visible(p_seconds, true)
obs.obs_property_set_visible(p_stop_text, true)
obs.obs_property_set_visible(button_pause, true)
obs.obs_property_set_visible(button_reset, true)
obs.obs_property_set_visible(p_a_mode, true)
obs.obs_property_set_visible(up_finished, true)
obs.obs_property_set_visible(p_rechour, false)
obs.obs_property_set_visible(p_recminutes, false)
obs.obs_property_set_visible(p_recseconds, false)
elseif (mode_setting == "Specific time record") then
obs.obs_property_set_visible(p_duration, false)
obs.obs_property_set_visible(p_year, false)
obs.obs_property_set_visible(p_month, false)
obs.obs_property_set_visible(p_day, false)
obs.obs_property_set_visible(p_hour, true)
obs.obs_property_set_visible(p_minutes, true)
obs.obs_property_set_visible(p_seconds, true)
obs.obs_property_set_visible(p_stop_text, false)
obs.obs_property_set_visible(button_pause, true)
obs.obs_property_set_visible(button_reset, true)
obs.obs_property_set_visible(p_a_mode, false)
obs.obs_property_set_visible(up_finished, false)
obs.obs_property_set_visible(p_rechour, true)
obs.obs_property_set_visible(p_recminutes, true)
obs.obs_property_set_visible(p_recseconds, true)
elseif (mode_setting == "Specific date and time") then
obs.obs_property_set_visible(p_duration, false)
obs.obs_property_set_visible(p_year, true)
obs.obs_property_set_visible(p_month, true)
obs.obs_property_set_visible(p_day, true)
obs.obs_property_set_visible(p_hour, true)
obs.obs_property_set_visible(p_minutes, true)
obs.obs_property_set_visible(p_seconds, true)
obs.obs_property_set_visible(p_stop_text, true)
obs.obs_property_set_visible(button_pause, true)
obs.obs_property_set_visible(button_reset, true)
obs.obs_property_set_visible(p_a_mode, true)
obs.obs_property_set_visible(up_finished, true)
obs.obs_property_set_visible(p_rechour, false)
obs.obs_property_set_visible(p_recminutes, false)
obs.obs_property_set_visible(p_recseconds, false)
elseif (mode_setting == "Specific date and time record") then
obs.obs_property_set_visible(p_duration, false)
obs.obs_property_set_visible(p_year, true)
obs.obs_property_set_visible(p_month, true)
obs.obs_property_set_visible(p_day, true)
obs.obs_property_set_visible(p_hour, true)
obs.obs_property_set_visible(p_minutes, true)
obs.obs_property_set_visible(p_seconds, true)
obs.obs_property_set_visible(p_stop_text, false)
obs.obs_property_set_visible(button_pause, true)
obs.obs_property_set_visible(button_reset, true)
obs.obs_property_set_visible(p_a_mode, false)
obs.obs_property_set_visible(up_finished, false)
obs.obs_property_set_visible(p_rechour, true)
obs.obs_property_set_visible(p_recminutes, true)
obs.obs_property_set_visible(p_recseconds, true)
elseif (mode_setting == "Streaming timer") then
obs.obs_property_set_visible(p_duration, false)
obs.obs_property_set_visible(p_year, false)
obs.obs_property_set_visible(p_month, false)
obs.obs_property_set_visible(p_day, false)
obs.obs_property_set_visible(p_hour, false)
obs.obs_property_set_visible(p_minutes, false)
obs.obs_property_set_visible(p_seconds, false)
obs.obs_property_set_visible(p_stop_text, false)
obs.obs_property_set_visible(button_pause, false)
obs.obs_property_set_visible(button_reset, false)
obs.obs_property_set_visible(p_a_mode, false)
obs.obs_property_set_visible(up_finished, false)
obs.obs_property_set_visible(p_rechour, false)
obs.obs_property_set_visible(p_recminutes, false)
obs.obs_property_set_visible(p_recseconds, false)
elseif (mode_setting == "Recording timer") then
obs.obs_property_set_visible(p_duration, false)
obs.obs_property_set_visible(p_year, false)
obs.obs_property_set_visible(p_month, false)
obs.obs_property_set_visible(p_day, false)
obs.obs_property_set_visible(p_hour, false)
obs.obs_property_set_visible(p_minutes, false)
obs.obs_property_set_visible(p_seconds, false)
obs.obs_property_set_visible(p_stop_text, false)
obs.obs_property_set_visible(button_pause, false)
obs.obs_property_set_visible(button_reset, false)
obs.obs_property_set_visible(p_a_mode, false)
obs.obs_property_set_visible(up_finished, false)
obs.obs_property_set_visible(p_rechour, false)
obs.obs_property_set_visible(p_recminutes, false)
obs.obs_property_set_visible(p_recseconds, false)
end
return true
end
function script_properties()
local props = obs.obs_properties_create()
local p_mode = obs.obs_properties_add_list(props, "mode", "Mode", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
obs.obs_property_list_add_string(p_mode, "Countdown", "countdown")
obs.obs_property_list_add_string(p_mode, "Countup", "countup")
obs.obs_property_list_add_string(p_mode, "Specific time", "specific_time")
obs.obs_property_list_add_string(p_mode, "Specific date and time", "specific_date_and_time")
obs.obs_property_list_add_string(p_mode, "Streaming timer", "stream")
obs.obs_property_list_add_string(p_mode, "Recording timer", "recording")
obs.obs_property_list_add_string(p_mode, "Specific time record", "specific_time_record")
obs.obs_property_list_add_string(p_mode, "Specific date and time record", "specific_date_and_time_record")
obs.obs_property_set_modified_callback(p_mode, settings_modified)
obs.obs_properties_add_int(props, "duration", "Countdown duration (seconds)", 1, 100000000, 1)
obs.obs_properties_add_int(props, "year", "Year", 1971, 100000000, 1)
obs.obs_properties_add_int(props, "month", "Month (1-12)", 1, 12, 1)
obs.obs_properties_add_int(props, "day", "Day (1-31)", 1, 31, 1)
obs.obs_properties_add_int(props, "hour", "Hour (0-24)", 0, 24, 1)
obs.obs_properties_add_int(props, "minutes", "Minutes (0-59)", 0, 59, 1)
obs.obs_properties_add_int(props, "seconds", "Seconds (0-59)", 0, 59, 1)
local rh = obs.obs_properties_add_int(props, "REChour", "RECord End Hour (0-24)", 0, 24, 1)
local rm = obs.obs_properties_add_int(props, "RECminutes", "RECord End Minute (0-59)", 0, 59, 1)
local rs = obs.obs_properties_add_int(props, "RECseconds", "RECord End Second (0-59)", 0, 59, 1)
local f_prop = obs.obs_properties_add_text(props, "format", "Format", obs.OBS_TEXT_DEFAULT)
obs.obs_property_set_long_description(f_prop, "%d - days\n%0h - hours with leading zero (00..23)\n%h - hours (0..23)\n%0H - hours with leading zero (00..infinity)\n%H - hours (0..infinity)\n%0m - minutes with leading zero (00..59)\n%m - minutes (0..59)\n%0M - minutes with leading zero (00..infinity)\n%M - minutes (0..infinity)\n%0s - seconds with leading zero (00..59)\n%s - seconds (0..59)\n%0S - seconds with leading zero (00..infinity)\n%S - seconds (0..infinity)\n%t - tenths\n%2t - hundredths\n%3t - thousandths")
local p = obs.obs_properties_add_list(props, "source", "Text source start", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
local sources = obs.obs_enum_sources()
if sources ~= nil then
for _, source in ipairs(sources) do
source_id = obs.obs_source_get_unversioned_id(source)
if source_id == "text_gdiplus" or source_id == "text_ft2_source" then
local name = obs.obs_source_get_name(source)
obs.obs_property_list_add_string(p, name, name)
end
end
end
obs.source_list_release(sources)
obs.obs_property_set_long_description(p, "Start TIMER for record start")
local p2 = obs.obs_properties_add_list(props, "source2", "Text source Stop", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
local sources2 = obs.obs_enum_sources()
if sources2 ~= nil then
for _, source2 in ipairs(sources2) do
source_id2 = obs.obs_source_get_unversioned_id(source2)
if source_id2 == "text_gdiplus" or source_id == "text_ft2_source" then
local name = obs.obs_source_get_name(source2)
obs.obs_property_list_add_string(p2, name, name)
end
end
end
obs.source_list_release(sources2)
obs.obs_property_set_long_description(p2, "Stop TIMER for record stop")
obs.obs_properties_add_text(props, "stop_text", "Countdown final text", obs.OBS_TEXT_DEFAULT)
local p_a_mode = obs.obs_properties_add_list(props, "a_mode", "Activation mode", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
obs.obs_property_list_add_string(p_a_mode, "Global (timer always active)", "global")
obs.obs_property_list_add_string(p_a_mode, "Start timer on activation", "start_reset")
obs.obs_properties_add_bool(props, "countup_countdown_finished", "Countup when done")
obs.obs_properties_add_button(props, "pause_button", "Start/Stop", pause_button_clicked)
obs.obs_properties_add_button(props, "reset_button", "Reset", reset_button_clicked)
settings_modified(props, nil, settings_)
return props
end
function script_description()
return "Sets a text source to act as a timer with advanced options. Hotkeys can be set for starting/stopping and to the reset timer."
end
function script_update(settings)
stop_timer()
up = false
mode = obs.obs_data_get_string(settings, "mode")
a_mode = obs.obs_data_get_string(settings, "a_mode")
source_name = obs.obs_data_get_string(settings, "source")
source_name2 = obs.obs_data_get_string(settings, "source2")
stop_text = obs.obs_data_get_string(settings, "stop_text")
local year = obs.obs_data_get_int(settings, "year")
local month = obs.obs_data_get_int(settings, "month")
local day = obs.obs_data_get_int(settings, "day")
local hour = obs.obs_data_get_int(settings, "hour")
local minute = obs.obs_data_get_int(settings, "minutes")
local second = obs.obs_data_get_int(settings, "seconds")
REChour = obs.obs_data_get_int(settings, "REChour")
RECminute = obs.obs_data_get_int(settings, "RECminutes")
RECsecond = obs.obs_data_get_int(settings, "RECseconds")
format = obs.obs_data_get_string(settings, "format")
up_when_finished = obs.obs_data_get_bool(settings, "countup_countdown_finished")
if mode == "Countdown" then
cur_time = obs.obs_data_get_int(settings, "duration") * 1000000000
elseif mode == "Specific time" or mode == "Specific time record" then
cur_time = delta_time(-1, -1, -1, hour, minute, second)
RECend_time = delta_time(-1, -1, -1, REChour, RECminute, RECsecond)
elseif mode == "Specific date and time" or mode == "Specific date and time record" then
cur_time = delta_time(year, month, day, hour, minute, second)
RECend_time = delta_time(-1, -1, -1, REChour, RECminute, RECsecond)
else
cur_time = 0
RECend_time = 0
end
global = a_mode == "Global (timer always active)"
if mode == "Streaming timer" or mode == "Recording timer" or mode == "Specific date and time record" or mode == "Specific time record" then
global = true
end
set_time_text(cur_time, format,source_name)
set_time_text(RECend_time, format,source_name2)
if global == false and paused == false then
start_timer()
end
end
function script_defaults(settings)
obs.obs_data_set_default_int(settings, "duration", 5)
obs.obs_data_set_default_int(settings, "year", os.date("%Y", os.time()))
obs.obs_data_set_default_int(settings, "month", os.date("%m", os.time()))
obs.obs_data_set_default_int(settings, "day", os.date("%d", os.time()))
obs.obs_data_set_default_string(settings, "stop_text", "Rec.")
obs.obs_data_set_default_string(settings, "mode", "Specific time record")
obs.obs_data_set_default_string(settings, "a_mode", "Global (timer always active)")
obs.obs_data_set_default_string(settings, "format", "%0H:%0m:%0s")
end
function script_save(settings)
local hotkey_save_array_reset = obs.obs_hotkey_save(hotkey_id_reset)
local hotkey_save_array_pause = obs.obs_hotkey_save(hotkey_id_pause)
obs.obs_data_set_array(settings, "reset_hotkey", hotkey_save_array_reset)
obs.obs_data_set_array(settings, "pause_hotkey", hotkey_save_array_pause)
obs.obs_data_array_release(hotkey_save_array_pause)
obs.obs_data_array_release(hotkey_save_array_reset)
end
function script_load(settings)
local sh = obs.obs_get_signal_handler()
obs.signal_handler_connect(sh, "source_show", source_activated)
obs.signal_handler_connect(sh, "source_hide", source_deactivated)
hotkey_id_reset = obs.obs_hotkey_register_frontend("reset_timer_thingy", "Reset Timer", reset)
hotkey_id_pause = obs.obs_hotkey_register_frontend("pause_timer", "Start/Stop Timer", on_pause)
local hotkey_save_array_reset = obs.obs_data_get_array(settings, "reset_hotkey")
local hotkey_save_array_pause = obs.obs_data_get_array(settings, "pause_hotkey")
obs.obs_hotkey_load(hotkey_id_reset, hotkey_save_array_reset)
obs.obs_hotkey_load(hotkey_id_pause, hotkey_save_array_pause)
obs.obs_data_array_release(hotkey_save_array_reset)
obs.obs_data_array_release(hotkey_save_array_pause)
obs.obs_frontend_add_event_callback(on_event)
settings_ = settings
script_update(settings)
end
The countdown text keeps moving from side to side as the thinner numbers like 1 are placed. Is there a way to stop this from happening?
Hey, how would I start a countup from let's say 45:00 like a soccer match instead of 00:00?
Is there any way to split the formatting across multiple lines of wrapped text rather than all on a single line?
I would like to track the total time spent on something across various recordings visible.
Would be nice to have an option where I can put in inital value and it would count upwards from there.
i dont know if im doing something wrong, or just doesnt work on my obs 25.0.8 (64bits).
The format displayed when %m and %s are not implemented. Here is a working implementation :
if string.match(text, "%%m") then
local minutes = math.floor(ms / 60000) % 60
minutes = string.format("%d", minutes)
text = string.gsub(text, "%%m", minutes)
end
if string.match(text, "%%s") then
local seconds = math.floor(ms / 1000) % 60
seconds = string.format("%d", seconds)
text = string.gsub(text, "%%s", seconds)
end
Would it be too much to ask to get some information on how to actually install and start to use this?
Hi,
I run 4 different timers which I activate using the show/hide source. Even when the source isn't showing, my rendering lag jumps by 4 to 5 ms because of the 4 timers. If I remove the source, it drops down again.
I tried recreating the source and updating your timer but I still get the same issue. Right now, I get an increase of 5 to 6 ms "average time to render".
I duplicated your file 4 times and added them in OBS and each of them are linked to one text source using different values.
Any idea what might be causing the rendering frame spike ?
In both the Countdown and Countup mode, when the timer is stopped, pressing "Reset" causes the timer to start.
I'd like to use this as a stopwatch to showcase speedruns, etc. and it would be great to have the timer starting at 00:00.000
(stopped) and then be able to use the hotkey to start the timer as required.
the count up option doesn't save after closing OBS. especially doing a 1 life run on games to see how long you survive and you end the stream for the day to come back the next day and open up OBS and the timer resets
can you add in the function so the timer does not reset when you click Start to continue off where you left it
PS sorry if this isn't the correct location to post this but this is an annoying issue
I sometimes like to have the words minutes and seconds spelled correctly in the timer. Here is a working suggestions for plural forms (basic but working).
if string.match(text, "%%fm") then
local minutes = math.floor(ms / 60000) % 60
if minutes < 1 then
minutes = string.format("%d", minutes) .. " minute"
else
minutes = string.format("%d", minutes) .. " minutes"
end
text = string.gsub(text, "%%fm", minutes)
end
if string.match(text, "%%fs") then
local seconds = math.floor(ms / 1000) % 60
if seconds < 1 then
seconds = string.format("%d", seconds) .. " second"
else
seconds = string.format("%d", seconds) .. " seconds"
end
text = string.gsub(text, "%%fs", seconds)
end
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.