Скрипт: изменение параметра прозрачности у фильтра на случайную величину от 1 до 100.
Чтобы узнать название параметра "прозрачность" необходимо добавить фильтр с прозрачностью на какой-нибудь источник, изменить этот параметр. Далее открыть файл коллекции сцен, путь к директории можно узнать через меню OBS:
Справка > Файлы журнала > Показать файлы журнала
далее с этой директории поднимаемся выше, и получаем путь ~/basic>scenes>название_сцены.json
В этом файле ищем color_filter или color_key_filter (оба фильтра могут изменить прозрачность источника).
В строке settings видим что прозрачность записана как opacity.
Ещё один способ узнать название параметра, прочитать исходный код фильтра - ссылка
Находим источник по имени
function add_filter_to_source(random_n)
source = obs.obs_get_source_by_name(source_name)
Создаём настройки с изменением параметра opacity на случайное число
Проверяем существует ли уже фильтр на источнике, если нет добавляем
_color_filter = obs.obs_source_get_filter_by_name(source,"opacity_random")
if _color_filter == nil then -- if not exists
_color_filter = obs.obs_source_create_private( "color_filter", "opacity_random", settings)
obs.obs_source_filter_add(source, _color_filter)
end
Обновляем и освобождаем память
obs.obs_source_update(_color_filter,settings)
obs.obs_source_release(source)
obs.obs_data_release(settings)
obs.obs_source_release(_color_filter)
end
Привязка к горячей клавише
function htk_1_cb(pressed)
if pressed then
n = math.random(1,100)
add_filter_to_source(n)
end
end
Исходный код
```lua
local obs = obslua
source_name = ''
function htk_1_cb(pressed)
if pressed then
n = math.random(1,100)
add_filter_to_source(n)
end
end
function add_filter_to_source(random_n)
source = obs.obs_get_source_by_name(source_name)
settings = obs.obs_data_create()
obs.obs_data_set_int(settings, "opacity",random_n)
_color_filter = obs.obs_source_get_filter_by_name(source,"opacity_random")
if _color_filter == nil then -- if not exists
_color_filter = obs.obs_source_create_private( "color_filter", "opacity_random", settings)
obs.obs_source_filter_add(source, _color_filter)
end
obs.obs_source_update(_color_filter,settings)
obs.obs_source_release(source)
obs.obs_data_release(settings)
obs.obs_source_release(_color_filter)
end
function script_properties()
-- source https://raw.githubusercontent.com/insin/obs-bounce/master/bounce.lua
local props = obs.obs_properties_create()
local source = obs.obs_properties_add_list(
props,
'source',
'Source:',
obs.OBS_COMBO_TYPE_EDITABLE,
obs.OBS_COMBO_FORMAT_STRING)
for _, name in ipairs(get_source_names()) do
obs.obs_property_list_add_string(source, name, name)
end
return props
end
function script_update(settings)
source_name = obs.obs_data_get_string(settings, 'source')
end
--- get a list of source names, sorted alphabetically
function get_source_names()
local sources = obs.obs_enum_sources()
local source_names = {}
if sources then
for _, source in ipairs(sources) do
-- exclude Desktop Audio and Mic/Aux by their capabilities
local capability_flags = obs.obs_source_get_output_flags(source)
if bit.band(capability_flags, obs.OBS_SOURCE_DO_NOT_SELF_MONITOR) == 0 and
capability_flags ~= bit.bor(obs.OBS_SOURCE_AUDIO, obs.OBS_SOURCE_DO_NOT_DUPLICATE) then
table.insert(source_names, obs.obs_source_get_name(source))
end
end
end
obs.source_list_release(sources)
table.sort(source_names, function(a, b)
return string.lower(a) < string.lower(b)
end)
return source_names
end
key_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ]}'
json_s = key_1
default_hotkeys = {
{id='htk_1',des='Кнопка 1 ',callback=htk_1_cb},
}
function script_load(settings)
s = obs.obs_data_create_from_json(json_s)
for _,v in pairs(default_hotkeys) do
a = obs.obs_data_get_array(s,v.id)
h = obs.obs_hotkey_register_frontend(v.id,v.des,v.callback)
obs.obs_hotkey_load(h,a)
obs.obs_data_array_release(a)
end
obs.obs_data_release(s)
end
```
Стоит упомянуть также о функции obs_source_enum_filters с её помощью можно получить
список всех фильтров у конкретного источника, кстати эта функция не работает в obspython,
но об этом чуть позже.
function check()
source = obs.obs_get_source_by_name(source_name)
result = obs.obs_source_enum_filters(source)
for k,v in pairs(result) do
name = obs.obs_source_get_name(v)
print('name'.. name)
end
obs.source_list_release(result)
obs.obs_source_release(source)
end
Эвенты и состояние
Скрипт: звуковое оповещение о том что сцена изменена, с использованием .mp3 файла.
На основе этого скрипта
Создадим функцию для проигрывания звука при смене сцен.
function on_event(event)
if event == obs.OBS_FRONTEND_EVENT_SCENE_CHANGED
then obs_play_sound_release_source()
end
end
function play_sound()
mediaSource = obs.obs_source_create_private("ffmpeg_source", "Global Media Source", nil)
local s = obs.obs_data_create()
obs.obs_data_set_string(s, "local_file",script_path() .. "alert.mp3")
obs.obs_source_update(mediaSource,s)
obs.obs_source_set_monitoring_type(mediaSource,obs.OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT)
obs.obs_data_release(s)
obs.obs_set_output_source(outputIndex, mediaSource)
return mediaSource
end
function obs_play_sound_release_source()
r = play_sound()
obs.obs_source_release(r)
end
Исходный код
```lua
local obs = obslua
mediaSource = nil -- Null pointer
outputIndex = 63 -- Last index
function play_sound()
mediaSource = obs.obs_source_create_private("ffmpeg_source", "Global Media Source", nil)
local s = obs.obs_data_create()
obs.obs_data_set_string(s, "local_file",script_path() .. "alert.mp3")
obs.obs_source_update(mediaSource,s)
obs.obs_source_set_monitoring_type(mediaSource,obs.OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT)
obs.obs_data_release(s)
obs.obs_set_output_source(outputIndex, mediaSource)
return mediaSource
end
function obs_play_sound_release_source()
r = play_sound()
obs.obs_source_release(r)
end
function on_event(event)
if event == obs.OBS_FRONTEND_EVENT_SCENE_CHANGED
then obs_play_sound_release_source()
end
end
function script_load(settings)
obs.obs_frontend_add_event_callback(on_event)
end
function script_unload()
obs.obs_set_output_source(outputIndex, nil)
end
```
Время и файлы
Запись в файл, "a" - создаст(если нет) файл и добавит "content", а "w" - перезапишет .
obs_sceneitem_get_source - предметы сцен в источник
obs_scene_from_source - преобразование сцены в источник
obs_scene_find_source - преобразование источника в предмет сцены
obs_frontend_get_scenes - получение всех сцен, освобождать с source_list_release
obs_frontend_get_current_scene - получение текущей сцены
obs_scene_enum_items - список всех предметов в сцене, освобождать с sceneitem_list_release
Скрипт: включение и выключение предмета сцены(источника на сцене).
Получение всех сцен и предметов в них
function toggle_source()
scenes = obs.obs_frontend_get_scenes()
for _,scene in pairs(scenes) do
scene_source = obs.obs_scene_from_source(scene)
items = obs.obs_scene_enum_items(scene_source)
...
Поиск конкретного источника и его включение или выключение, source_name и boolean определены глобально.
...
for _,scene_item in pairs(items) do
_source = obs.obs_sceneitem_get_source(scene_item)
_name = obs.obs_source_get_name(_source)
if _name == source_name then
boolean = not boolean
obs.obs_sceneitem_set_visible(scene_item, boolean)
end
end
...
Исходный код
```lua
local obs = obslua
source_name = ''
boolean = true
function htk_1_cb(pressed)
if pressed then
toggle_source()
end
end
function toggle_source()
scenes = obs.obs_frontend_get_scenes()
for _,scene in pairs(scenes) do
scene_source = obs.obs_scene_from_source(scene)
items = obs.obs_scene_enum_items(scene_source)
for _,scene_item in pairs(items) do
_source = obs.obs_sceneitem_get_source(scene_item)
_name = obs.obs_source_get_name(_source)
if _name == source_name then
boolean = not boolean
obs.obs_sceneitem_set_visible(scene_item, boolean)
end
end
obs.sceneitem_list_release(items)
end
obs.source_list_release(scenes)
end
function script_properties()
-- source https://raw.githubusercontent.com/insin/obs-bounce/master/bounce.lua
local props = obs.obs_properties_create()
local source = obs.obs_properties_add_list(
props,
'source',
'Source:',
obs.OBS_COMBO_TYPE_EDITABLE,
obs.OBS_COMBO_FORMAT_STRING)
for _, name in ipairs(get_source_names()) do
obs.obs_property_list_add_string(source, name, name)
end
obs.obs_property_set_long_description(source,"?" )
return props
end
function script_update(settings)
source_name = obs.obs_data_get_string(settings, 'source')
end
--- get a list of source names, sorted alphabetically
function get_source_names()
local sources = obs.obs_enum_sources()
local source_names = {}
if sources then
for _, source in ipairs(sources) do
-- exclude Desktop Audio and Mic/Aux by their capabilities
local capability_flags = obs.obs_source_get_output_flags(source)
if bit.band(capability_flags, obs.OBS_SOURCE_DO_NOT_SELF_MONITOR) == 0 and
capability_flags ~= bit.bor(obs.OBS_SOURCE_AUDIO, obs.OBS_SOURCE_DO_NOT_DUPLICATE) then
table.insert(source_names, obs.obs_source_get_name(source))
end
end
end
obs.source_list_release(sources)
table.sort(source_names, function(a, b)
return string.lower(a) < string.lower(b)
end)
return source_names
end
key_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ]}'
json_s = key_1
default_hotkeys = {
{id='htk_1',des='Кнопка 1 ',callback=htk_1_cb},
}
function script_load(settings)
s = obs.obs_data_create_from_json(json_s)
for _,v in pairs(default_hotkeys) do
a = obs.obs_data_get_array(s,v.id)
h = obs.obs_hotkey_register_frontend(v.id,v.des,v.callback)
obs.obs_hotkey_load(h,a)
obs.obs_data_array_release(a)
end
obs.obs_data_release(s)
end
```
Регистрация фильтров
В obslua доступна функция obs_register_source, с её помощью можно зарегистрировать
источник( переходы и фильтры это источники). Для этого понадобится создать таблицу источника
Регистрация фильтров удобна тем,что позволяет закрепить функциональность скрипта за
определенным источником. Поддерживает горячие клавиши, интерфейс, таймеры.
Скрипт: закрепление горячих клавиш на фильтре, и полный доступ к источнику.
Импорт библиотеки, и определение типа как источник-фильтр.
local obs = obslua
local bit = require("bit")
local info = {} -- obs_source_info https://obsproject.com/docs/reference-sources.html
info.id = "uniq_filter_id"
info.type = obs.OBS_SOURCE_TYPE_FILTER
info.output_flags = bit.bor(obs.OBS_SOURCE_VIDEO)
info.get_name = function() return 'default filter name' end
Инициализация фильтра, будет вызываться при запуске программы или при добавлении к источнику
info.create = function(settings,source)
local filter = {}
filter.context = source
filter.hotkeys = {
htk_stop = "[stop] ",
htk_restart = "[start] ",
}
filter.hotkey_mapping = function(hotkey,data)
if hotkey == "htk_stop" then
print('stop '.. data.srsn .. " : " .. data.filn)
elseif hotkey == "htk_restart" then
print('restart ' .. data.srsn .. " : " .. data.filn)
end
end
filter.hk = {}
for k,v in pairs(filter.hotkeys) do
filter.hk[k] = obs.OBS_INVALID_HOTKEY_ID
end
Создание функции которая запустится не сразу ( это необходимо т.к фильтр ещё не создан)
Он будет создан после return
filter._reg_htk = function()
info.reg_htk(filter,settings)
end
obs.timer_add(filter._reg_htk,100) -- callback to register hotkeys, one time only
Завершающая регистрация горячих клавиш,obs_filter_get_parent источник который фильтруется
к которому прикреплён фильтр этого типа. Удаление таймера.
info.reg_htk = function(filter,settings) -- register hotkeys after 100 ms since filter was created
local target = obs.obs_filter_get_parent(filter.context)
local srsn = obs.obs_source_get_name(target)
local filn = obs.obs_source_get_name(filter.context)
local data = {srsn = srsn, filn = filn}
for k, v in pairs(filter.hotkeys) do
filter.hk[k] = obs.obs_hotkey_register_frontend(k, v .. srsn .. " : " .. filn, function(pressed)
if pressed then filter.hotkey_mapping(k,data) end end)
local a = obs.obs_data_get_array(settings, k)
obs.obs_hotkey_load(filter.hk[k], a)
obs.obs_data_array_release(a)
end
obs.remove_current_callback()
end
Необходимый код для пропуска фильтрации, без него при добавлении фильтра источник "выключится"
info.video_render = function(filter, effect)
-- called every frame
local target = obs.obs_filter_get_parent(filter.context)
if target ~= nil then
filter.width = obs.obs_source_get_base_width(target)
filter.height = obs.obs_source_get_base_height(target)
end
obs.obs_source_skip_video_filter(filter.context)
end
info.get_width = function(filter)
return filter.width
end
info.get_height = function(filter)
return filter.height
end
Функция .save вызывается при сохранении настроек,т.е можно переназначить горячие клавиши.
obs.obs_register_source(info) - регистрация фильтра, теперь его видно при нажатии ПКМ
info.save = function(filter,settings)
for k, v in pairs(filter.hotkeys) do
local a = obs.obs_hotkey_save(filter.hk[k])
obs.obs_data_set_array(settings, k, a)
obs.obs_data_array_release(a)
end
end
obs.obs_register_source(info)
info.load - также как и script_load, вызывается при запуске программы, но в данном
случае дублирует функциональность и требует перезапуска. .update, .get_properties
функции аналогичные script_update, script_properties.
Исходный код
```lua
local obs = obslua
local bit = require("bit")
local info = {} -- obs_source_info https://obsproject.com/docs/reference-sources.html
info.id = "uniq_filter_id"
info.type = obs.OBS_SOURCE_TYPE_FILTER
info.output_flags = bit.bor(obs.OBS_SOURCE_VIDEO)
info.get_name = function() return 'default filter name' end
info.create = function(settings,source)
local filter = {}
filter.context = source
filter.hotkeys = {
htk_stop = "[stop] ",
htk_restart = "[start] ",
}
filter.hotkey_mapping = function(hotkey,data)
if hotkey == "htk_stop" then
print('stop '.. data.srsn .. " : " .. data.filn)
elseif hotkey == "htk_restart" then
print('restart ' .. data.srsn .. " : " .. data.filn)
end
end
filter.hk = {}
for k,v in pairs(filter.hotkeys) do
filter.hk[k] = obs.OBS_INVALID_HOTKEY_ID
end
filter._reg_htk = function()
info.reg_htk(filter,settings)
end
obs.timer_add(filter._reg_htk,100) -- callback to register hotkeys, one time only
return filter
end
info.reg_htk = function(filter,settings) -- register hotkeys after 100 ms since filter was created
local target = obs.obs_filter_get_parent(filter.context)
local srsn = obs.obs_source_get_name(target)
local filn = obs.obs_source_get_name(filter.context)
local data = {srsn = srsn, filn = filn}
for k, v in pairs(filter.hotkeys) do
filter.hk[k] = obs.obs_hotkey_register_frontend(k, v .. srsn .. " : " .. filn, function(pressed)
if pressed then filter.hotkey_mapping(k,data) end end)
local a = obs.obs_data_get_array(settings, k)
obs.obs_hotkey_load(filter.hk[k], a)
obs.obs_data_array_release(a)
end
obs.remove_current_callback()
end
info.video_render = function(filter, effect)
-- called every frame
local target = obs.obs_filter_get_parent(filter.context)
if target ~= nil then
filter.width = obs.obs_source_get_base_width(target)
filter.height = obs.obs_source_get_base_height(target)
end
obs.obs_source_skip_video_filter(filter.context)
end
info.get_width = function(filter)
return filter.width
end
info.get_height = function(filter)
return filter.height
end
--info.load = function(filter,settings) -- restart required
--... same code as in info.reg_htk, but filters will be created from scratch every time
--obs restarts, there is no reason to define it here again becuase hotkeys will be duplicated
--end
info.save = function(filter,settings)
for k, v in pairs(filter.hotkeys) do
local a = obs.obs_hotkey_save(filter.hk[k])
obs.obs_data_set_array(settings, k, a)
obs.obs_data_array_release(a)
end
end
obs.obs_register_source(info)
```
obspython
В OBS также доступен скриптинг через Python, для Windows только 3.6 версия, для Linux встроенная (т.к в настройках нельзя указать путь),
для MacOS Python не доступен для текущей (26.0.0) версии.
В отличии от Lua тут нельзя регистрировать источники, перебор фильтров не работает,
т.к не написан wrapper на функции с аргументом типа указатель-указатель.
Но в контексте скриптинга имеет место быть т.к:
Перед тем как начать делать задачи, рекомендую сделать бэкап коллекции сцен,
с осторожностью использовать script_tick(вызывается раз в каждый кадр)
Проверять утечки памяти в папке logs, последняя строка последнего файла
пример - время: Number of memory leaks: 0,если скрипт написан неправильно то
этой строчки там не окажется т.к OBS вылетит с ошибкой при закрытии.
3)[фильтры] "Динамическая прокрутка"
Создать программно или выбрать через интерфейс источник который будет фильтроваться,
к этом источнику добавить(если нет) фильтр Прокрутка (scroll_filter),
добавить интерфейс и/или горячие клавиши которые меняют значение вертикальной скорости
на случайную величину от 0 до 1000 при этом включать/выключать повторение с 50% шансом.
4)[эвенты] "Проверка"
При переключении сцен проверять идёт ли запись.
Если нет - вывести оповещение ( например через error())
5)[время и файлы] "Пост-продакшен"
Создать скрипт который при нажатии горячей клавиши записывает текущее время,
относительное время от старта записи, добавляет текст "МЕТКА",
а через интерфейс UI кнопку записать текст, и место для набора текста.
6)[предметы сцены] "Сумма"
Посчитать количество сцен и предметов сцен, записать ответ в названии первой сцены.
Не учитывать группы, т.к перебор предметов груп не работает.
7) [фильтры и источники] "Нэйтив скриптинг"
Создать фильтр который будет с интервалом в 2 секунды включать и выключать источник за которым он закреплён.
Ответы на задачи и код скриптов включая первую часть на Github
Всем привет,в этой части руководства рассмотрим : фильтры, сцены, предметы сцен, Frontend API, создание функциональных фильтров и прочее...
Краткая справка для этой части
Источник - Источники используются для рендера аудио/видео, например: захват камеры,игры,звука. С помощью источников можно создавать фильтры,переходы
Фильтр - Источник который дополняет другие источники
Сцены - Коллекция источников, сцена является источником ( сцену можно добавить как источник в другой сцене)
Предмет сцены - конкретный источник в сцене, его можно: перемещать, увеличивать/уменьшать, переворачивать, менять состояние выкл/вкл и.т.д
Frontend API - Набор функций который предоставляет OBS Studio, например:
Фильтры
Типы фильтров так же как и источников, можно узнать через функцию
obs_source_get_unversioned_id
В английском варианте : ссылка
Скрипт: изменение параметра прозрачности у фильтра на случайную величину от 1 до 100.
Чтобы узнать название параметра "прозрачность" необходимо добавить фильтр с прозрачностью на какой-нибудь источник, изменить этот параметр. Далее открыть файл коллекции сцен, путь к директории можно узнать через меню OBS:
Справка
>Файлы журнала
>Показать файлы журнала
далее с этой директории поднимаемся выше, и получаем путь~/basic>scenes>название_сцены.json
В этом файле ищемcolor_filter
илиcolor_key_filter
(оба фильтра могут изменить прозрачность источника). В строкеsettings
видим что прозрачность записана какopacity
. Ещё один способ узнать название параметра, прочитать исходный код фильтра - ссылкаНаходим источник по имени
Создаём настройки с изменением параметра
opacity
на случайное числоПроверяем существует ли уже фильтр на источнике, если нет добавляем
Обновляем и освобождаем память
Привязка к горячей клавише
Исходный код
```lua local obs = obslua source_name = '' function htk_1_cb(pressed) if pressed then n = math.random(1,100) add_filter_to_source(n) end end function add_filter_to_source(random_n) source = obs.obs_get_source_by_name(source_name) settings = obs.obs_data_create() obs.obs_data_set_int(settings, "opacity",random_n) _color_filter = obs.obs_source_get_filter_by_name(source,"opacity_random") if _color_filter == nil then -- if not exists _color_filter = obs.obs_source_create_private( "color_filter", "opacity_random", settings) obs.obs_source_filter_add(source, _color_filter) end obs.obs_source_update(_color_filter,settings) obs.obs_source_release(source) obs.obs_data_release(settings) obs.obs_source_release(_color_filter) end function script_properties() -- source https://raw.githubusercontent.com/insin/obs-bounce/master/bounce.lua local props = obs.obs_properties_create() local source = obs.obs_properties_add_list( props, 'source', 'Source:', obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING) for _, name in ipairs(get_source_names()) do obs.obs_property_list_add_string(source, name, name) end return props end function script_update(settings) source_name = obs.obs_data_get_string(settings, 'source') end --- get a list of source names, sorted alphabetically function get_source_names() local sources = obs.obs_enum_sources() local source_names = {} if sources then for _, source in ipairs(sources) do -- exclude Desktop Audio and Mic/Aux by their capabilities local capability_flags = obs.obs_source_get_output_flags(source) if bit.band(capability_flags, obs.OBS_SOURCE_DO_NOT_SELF_MONITOR) == 0 and capability_flags ~= bit.bor(obs.OBS_SOURCE_AUDIO, obs.OBS_SOURCE_DO_NOT_DUPLICATE) then table.insert(source_names, obs.obs_source_get_name(source)) end end end obs.source_list_release(sources) table.sort(source_names, function(a, b) return string.lower(a) < string.lower(b) end) return source_names end key_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ]}' json_s = key_1 default_hotkeys = { {id='htk_1',des='Кнопка 1 ',callback=htk_1_cb}, } function script_load(settings) s = obs.obs_data_create_from_json(json_s) for _,v in pairs(default_hotkeys) do a = obs.obs_data_get_array(s,v.id) h = obs.obs_hotkey_register_frontend(v.id,v.des,v.callback) obs.obs_hotkey_load(h,a) obs.obs_data_array_release(a) end obs.obs_data_release(s) end ```Стоит упомянуть также о функции
obs_source_enum_filters
с её помощью можно получить список всех фильтров у конкретного источника, кстати эта функция не работает вobspython
, но об этом чуть позже.Эвенты и состояние
Скрипт: звуковое оповещение о том что сцена изменена, с использованием .mp3 файла. На основе этого скрипта
Создадим функцию для проигрывания звука при смене сцен.
Добавим источник медиа, установим настройки: файл
alert.mp3
относителен директории нахождения скрипта,obs_source_set_monitoring_type
выставляет прослушивание аудио.Исходный код
```lua local obs = obslua mediaSource = nil -- Null pointer outputIndex = 63 -- Last index function play_sound() mediaSource = obs.obs_source_create_private("ffmpeg_source", "Global Media Source", nil) local s = obs.obs_data_create() obs.obs_data_set_string(s, "local_file",script_path() .. "alert.mp3") obs.obs_source_update(mediaSource,s) obs.obs_source_set_monitoring_type(mediaSource,obs.OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT) obs.obs_data_release(s) obs.obs_set_output_source(outputIndex, mediaSource) return mediaSource end function obs_play_sound_release_source() r = play_sound() obs.obs_source_release(r) end function on_event(event) if event == obs.OBS_FRONTEND_EVENT_SCENE_CHANGED then obs_play_sound_release_source() end end function script_load(settings) obs.obs_frontend_add_event_callback(on_event) end function script_unload() obs.obs_set_output_source(outputIndex, nil) end ```Время и файлы
Запись в файл, "a" - создаст(если нет) файл и добавит "content", а "w" - перезапишет .
Сцены и предметы сцен
obs_sceneitem_get_source
- предметы сцен в источникobs_scene_from_source
- преобразование сцены в источникobs_scene_find_source
- преобразование источника в предмет сценыobs_frontend_get_scenes
- получение всех сцен, освобождать сsource_list_release
obs_frontend_get_current_scene
- получение текущей сценыobs_scene_enum_items
- список всех предметов в сцене, освобождать сsceneitem_list_release
Скрипт: включение и выключение предмета сцены(источника на сцене).
Получение всех сцен и предметов в них
Поиск конкретного источника и его включение или выключение,
source_name
иboolean
определены глобально.Исходный код
```lua local obs = obslua source_name = '' boolean = true function htk_1_cb(pressed) if pressed then toggle_source() end end function toggle_source() scenes = obs.obs_frontend_get_scenes() for _,scene in pairs(scenes) do scene_source = obs.obs_scene_from_source(scene) items = obs.obs_scene_enum_items(scene_source) for _,scene_item in pairs(items) do _source = obs.obs_sceneitem_get_source(scene_item) _name = obs.obs_source_get_name(_source) if _name == source_name then boolean = not boolean obs.obs_sceneitem_set_visible(scene_item, boolean) end end obs.sceneitem_list_release(items) end obs.source_list_release(scenes) end function script_properties() -- source https://raw.githubusercontent.com/insin/obs-bounce/master/bounce.lua local props = obs.obs_properties_create() local source = obs.obs_properties_add_list( props, 'source', 'Source:', obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING) for _, name in ipairs(get_source_names()) do obs.obs_property_list_add_string(source, name, name) end obs.obs_property_set_long_description(source,"?" ) return props end function script_update(settings) source_name = obs.obs_data_get_string(settings, 'source') end --- get a list of source names, sorted alphabetically function get_source_names() local sources = obs.obs_enum_sources() local source_names = {} if sources then for _, source in ipairs(sources) do -- exclude Desktop Audio and Mic/Aux by their capabilities local capability_flags = obs.obs_source_get_output_flags(source) if bit.band(capability_flags, obs.OBS_SOURCE_DO_NOT_SELF_MONITOR) == 0 and capability_flags ~= bit.bor(obs.OBS_SOURCE_AUDIO, obs.OBS_SOURCE_DO_NOT_DUPLICATE) then table.insert(source_names, obs.obs_source_get_name(source)) end end end obs.source_list_release(sources) table.sort(source_names, function(a, b) return string.lower(a) < string.lower(b) end) return source_names end key_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ]}' json_s = key_1 default_hotkeys = { {id='htk_1',des='Кнопка 1 ',callback=htk_1_cb}, } function script_load(settings) s = obs.obs_data_create_from_json(json_s) for _,v in pairs(default_hotkeys) do a = obs.obs_data_get_array(s,v.id) h = obs.obs_hotkey_register_frontend(v.id,v.des,v.callback) obs.obs_hotkey_load(h,a) obs.obs_data_array_release(a) end obs.obs_data_release(s) end ```Регистрация фильтров
В
obslua
доступна функцияobs_register_source
, с её помощью можно зарегистрировать источник( переходы и фильтры это источники). Для этого понадобится создать таблицу источника Регистрация фильтров удобна тем,что позволяет закрепить функциональность скрипта за определенным источником. Поддерживает горячие клавиши, интерфейс, таймеры.Скрипт: закрепление горячих клавиш на фильтре, и полный доступ к источнику.
Импорт библиотеки, и определение типа как источник-фильтр.
Инициализация фильтра, будет вызываться при запуске программы или при добавлении к источнику
Начальная регистрация горячих клавиш, принадлежащих конкретному фильтру.
Создание функции которая запустится не сразу ( это необходимо т.к фильтр ещё не создан) Он будет создан после
return
Завершающая регистрация горячих клавиш,
obs_filter_get_parent
источник который фильтруется к которому прикреплён фильтр этого типа. Удаление таймера.Необходимый код для пропуска фильтрации, без него при добавлении фильтра источник "выключится"
Функция .save вызывается при сохранении настроек,т.е можно переназначить горячие клавиши.
obs.obs_register_source(info)
- регистрация фильтра, теперь его видно при нажатии ПКМinfo.load
- также как иscript_load
, вызывается при запуске программы, но в данном случае дублирует функциональность и требует перезапуска..update
,.get_properties
функции аналогичныеscript_update
,script_properties
.Исходный код
```lua local obs = obslua local bit = require("bit") local info = {} -- obs_source_info https://obsproject.com/docs/reference-sources.html info.id = "uniq_filter_id" info.type = obs.OBS_SOURCE_TYPE_FILTER info.output_flags = bit.bor(obs.OBS_SOURCE_VIDEO) info.get_name = function() return 'default filter name' end info.create = function(settings,source) local filter = {} filter.context = source filter.hotkeys = { htk_stop = "[stop] ", htk_restart = "[start] ", } filter.hotkey_mapping = function(hotkey,data) if hotkey == "htk_stop" then print('stop '.. data.srsn .. " : " .. data.filn) elseif hotkey == "htk_restart" then print('restart ' .. data.srsn .. " : " .. data.filn) end end filter.hk = {} for k,v in pairs(filter.hotkeys) do filter.hk[k] = obs.OBS_INVALID_HOTKEY_ID end filter._reg_htk = function() info.reg_htk(filter,settings) end obs.timer_add(filter._reg_htk,100) -- callback to register hotkeys, one time only return filter end info.reg_htk = function(filter,settings) -- register hotkeys after 100 ms since filter was created local target = obs.obs_filter_get_parent(filter.context) local srsn = obs.obs_source_get_name(target) local filn = obs.obs_source_get_name(filter.context) local data = {srsn = srsn, filn = filn} for k, v in pairs(filter.hotkeys) do filter.hk[k] = obs.obs_hotkey_register_frontend(k, v .. srsn .. " : " .. filn, function(pressed) if pressed then filter.hotkey_mapping(k,data) end end) local a = obs.obs_data_get_array(settings, k) obs.obs_hotkey_load(filter.hk[k], a) obs.obs_data_array_release(a) end obs.remove_current_callback() end info.video_render = function(filter, effect) -- called every frame local target = obs.obs_filter_get_parent(filter.context) if target ~= nil then filter.width = obs.obs_source_get_base_width(target) filter.height = obs.obs_source_get_base_height(target) end obs.obs_source_skip_video_filter(filter.context) end info.get_width = function(filter) return filter.width end info.get_height = function(filter) return filter.height end --info.load = function(filter,settings) -- restart required --... same code as in info.reg_htk, but filters will be created from scratch every time --obs restarts, there is no reason to define it here again becuase hotkeys will be duplicated --end info.save = function(filter,settings) for k, v in pairs(filter.hotkeys) do local a = obs.obs_hotkey_save(filter.hk[k]) obs.obs_data_set_array(settings, k, a) obs.obs_data_array_release(a) end end obs.obs_register_source(info) ```obspython
В OBS также доступен скриптинг через Python, для Windows только 3.6 версия, для Linux встроенная (т.к в настройках нельзя указать путь), для MacOS Python не доступен для текущей (26.0.0) версии. В отличии от Lua тут нельзя регистрировать источники, перебор фильтров не работает, т.к не написан wrapper на функции с аргументом типа указатель-указатель. Но в контексте скриптинга имеет место быть т.к:
Задачи
Перед тем как начать делать задачи, рекомендую сделать бэкап коллекции сцен, с осторожностью использовать
script_tick
(вызывается раз в каждый кадр) Проверять утечки памяти в папкеlogs
, последняя строка последнего файла пример -время: Number of memory leaks: 0
,если скрипт написан неправильно то этой строчки там не окажется т.к OBS вылетит с ошибкой при закрытии.3)[фильтры] "Динамическая прокрутка" Создать программно или выбрать через интерфейс источник который будет фильтроваться, к этом источнику добавить(если нет) фильтр Прокрутка (scroll_filter), добавить интерфейс и/или горячие клавиши которые меняют значение вертикальной скорости на случайную величину от 0 до 1000 при этом включать/выключать повторение с 50% шансом.
4)[эвенты] "Проверка" При переключении сцен проверять идёт ли запись. Если нет - вывести оповещение ( например через error())
5)[время и файлы] "Пост-продакшен" Создать скрипт который при нажатии горячей клавиши записывает текущее время, относительное время от старта записи, добавляет текст "МЕТКА", а через интерфейс UI кнопку записать текст, и место для набора текста.
6)[предметы сцены] "Сумма" Посчитать количество сцен и предметов сцен, записать ответ в названии первой сцены. Не учитывать группы, т.к перебор предметов груп не работает.
7) [фильтры и источники] "Нэйтив скриптинг" Создать фильтр который будет с интервалом в 2 секунды включать и выключать источник за которым он закреплён.
Ответы на задачи и код скриптов включая первую часть на Github
Ссылки