Всем привет, в этом руководстве рассмотрим создание скриптов для OBS на языке Lua.
Скриптинг в OBS доступен начиная с версии 21, на данный момент новейшая 26.0.0-rc3 версия доступна для тестирования.Обновление включает в себя виртуальную веб камеру (пока что только на Windows), улучшенный UI, возможность скриншота любого источника( КДПВ была сделана с помощью этой функции).
Описание глобальных функций, API, настроек
Добавить скрипт можно через меню -> Инструменты -> Скрипты
-> значок "плюс".
Скрипты могут быть добавлены, перезагружены, удалены в режиме
реального времени.
Сходства и различия c С-API
Сходства: почти полный доступ к API, СБОЙ или УТЕЧКА ПАМЯТИ с неправильно написанным скриптом.
Различия: некоторые функции(с двойными указателями) недоступны, некоторые заменены на другие.
У каждого скрипта своё пространство имён, убедиться в этом можно открыв текущую коллекцию сцен "~/obs-studio/basic/scenes".
Настройки settings
представляют собой JSON строку,
они могут быть созданы/загружены/сохранены с помощью JSON строк или
файлов.
Описание функций:
-
obslua
модуль для доступа к функциям OBS -
script_description()
описание скрипта, поддерживает примитивный HTML -
script_properties()
пользовательский интерфейс -
script_defaults(settings)
устанавливает настройки по умолчанию -
script_update(settings)
вызывается каждый раз когда пользователь изменил настройки через пользовательский интерфейс -
script_load(settings)
загружает настройки при первом запуске -
script_unload()
вызывается при закрытии скрипта -
script_save(settings)
используется в основном для сохранения горячих клавиш, настройки c пользовательского интерфейса сохраняются автоматически -
script_tick(seconds)
вызывается каждый кадр, аргумент seconds получает значение потраченных секунд с предыдущего кадра -
script_path()
возвращает абсолютный путь к папке скрипта -
timer_add(callback,milliseconds)
вызов функции периодично -
timer_remove(callback)
удаление функции с таймера, также есть вариант использоватьremove_current_callback()
внутри функции которая вызывается периодично
Пример скрипта
Скрипт: Движение по линии с использованием кнопок и таймера.
local obs = obslualocal selected_sourcepos = obs.vec2()switch = falsecounter = 0
Короткая запись модуля, local var
инициализация
значения как nil
, pos
структура
предоставляемая OBS для перемещения источников на сцене.
function script_properties() local props = obs.obs_properties_create() obs.obs_properties_add_button(props, "button1", "Вкл/Выкл",on_off) obs.obs_properties_add_button(props, "button2", "Добавить источник",add_source) obs.obs_properties_add_button(props, "button3", "Подвинуть источник на +10,0",move_button) local p = obs.obs_properties_add_list(props, "selected_source", "Выберите источник", 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 == "color_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) return propsend
Добавляем пользовательский интерфейс.
obs.obs_properties_add_button(props, "имя",
"Описание",функция)
, local p =
obs.obs_properties_add_list
выпадающие меню с выбором
источника, source_id =
obs.obs_source_get_unversioned_id(source)
получение имени
источника при этом игнорируя его версию,
obs.source_list_release(sources)
освобождение
памяти
function script_update(settings) selected_source = obs.obs_data_get_string(settings,"selected_source")end
Обновление selected_source
каждый раз когда
настройки (выпадающее меню в этом случае) изменены.
function add_source() current_scene = obs.obs_frontend_get_current_scene() scene = obs.obs_scene_from_source(current_scene) settings = obs.obs_data_create() counter = counter + 1 green = 0xff00ff00 hotkey_data = nil obs.obs_data_set_int(settings, "width",200) obs.obs_data_set_int(settings, "height",200) obs.obs_data_set_int(settings, "color",green) source = obs.obs_source_create("color_source", "ист#" .. counter, settings, hotkey_data) obs.obs_scene_add(scene, source) obs.obs_scene_release(scene) obs.obs_data_release(settings) obs.obs_source_release(source)end
Выбор сцены и создание настроек для источника, добавление на сцену, освобождение памяти.
function move_source_on_scene() current_scene = obs.obs_frontend_get_current_scene() scene = obs.obs_scene_from_source(current_scene) scene_item = obs.obs_scene_find_source(scene, selected_source) if scene_item then dx, dy = 10, 0 obs.obs_sceneitem_get_pos( scene_item, pos) -- обновить позицию если источник был перемещён мышкой pos.x = pos.x + dx pos.y = pos.y + dy obs.obs_sceneitem_set_pos(scene_item, pos) end obs.obs_scene_release(scene)end
Функция перемещения источника в рамках сцены.
function move_button(props,p) move_source_on_scene()end
Кнопка перемещения источника и 2 необходимых аргумента.
function on_off() if switch then obs.timer_add(move_source_on_scene,50) else obs.timer_remove(move_source_on_scene) end switch = not switchend
Кнопка переключатель и таймер периодического запуска функции в
миллисекундах.
local obs = obslualocal selected_sourcepos = obs.vec2()switch = falsecounter = 0function on_off() if switch then obs.timer_add(move_source_on_scene,50) else obs.timer_remove(move_source_on_scene) end switch = not switchendfunction add_source() current_scene = obs.obs_frontend_get_current_scene() scene = obs.obs_scene_from_source(current_scene) settings = obs.obs_data_create() counter = counter + 1 green = 0xff00ff00 hotkey_data = nil obs.obs_data_set_int(settings, "width",200) obs.obs_data_set_int(settings, "height",200) obs.obs_data_set_int(settings, "color",green) source = obs.obs_source_create("color_source", "ист#" .. counter, settings, hotkey_data) obs.obs_scene_add(scene, source) obs.obs_scene_release(scene) obs.obs_data_release(settings) obs.obs_source_release(source)endfunction move_button(props,p) move_source_on_scene()endfunction move_source_on_scene() current_scene = obs.obs_frontend_get_current_scene() scene = obs.obs_scene_from_source(current_scene) scene_item = obs.obs_scene_find_source(scene, selected_source) if scene_item then dx, dy = 10, 0 obs.obs_sceneitem_get_pos( scene_item, pos) -- обновить позицию если источник был перемещён мышкой pos.x = pos.x + dx pos.y = pos.y + dy obs.obs_sceneitem_set_pos(scene_item, pos) end obs.obs_scene_release(scene)endfunction script_properties() local props = obs.obs_properties_create() obs.obs_properties_add_button(props, "button1", "Вкл/Выкл",on_off) obs.obs_properties_add_button(props, "button2", "Добавить источник",add_source) obs.obs_properties_add_button(props, "button3", "Cдвинуть источник на +10,0",move_button) local p = obs.obs_properties_add_list(props, "selected_source", "Выберите источник", 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 == "color_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) return propsendfunction script_update(settings) selected_source = obs.obs_data_get_string(settings,"selected_source")end
Пример горячих клавиш
Скрипт: Создание постоянных и изменяющихся горячих клавиш.
Создание изменяющихся горячих клавиш, в том смысле что их можно поменять в настройках OBS.
hotkeys = { htk_stop = "Стоп", htk_start = "Старт",}hk = {}function hotkey_mapping(hotkey) if hotkey == "htk_stop" then print('Стоп') elseif hotkey == "htk_start" then print('Старт') endend
Словарь с клавишами и функция типа "switch"
function script_load(settings) for k, v in pairs(hotkeys) do hk[k] = obs.obs_hotkey_register_frontend(k, v, function(pressed) if pressed then hotkey_mapping(k) end end) a = obs.obs_data_get_array(settings, k) obs.obs_hotkey_load(hk[k], a) obs.obs_data_array_release(a) end ...function script_save(settings) for k, v in pairs(hotkeys) do a = obs.obs_hotkey_save(hk[k]) obs.obs_data_set_array(settings, k, a) obs.obs_data_array_release(a) endend
Сохранение/загрузка изменяющихся горячих клавиш.
function htk_1_cb(pressed) if pressed then print('1') endendfunction htk_2_cb(pressed) if pressed then print('2 активно') else print('2 не активно') endendkey_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ],'key_2 = '"htk_2": [ { "key": "OBS_KEY_2" } ]}'json_s = key_1 .. key_2default_hotkeys = { {id='htk_1',des='Кнопка 1 ',callback=htk_1_cb}, {id='htk_2',des='Кнопка 2 ',callback=htk_2_cb},}
Создание постоянных клавиш, их можно поменять в настройках, но при перезапуске OBS они примут значения по умолчанию. В данном случае кнопку 1 и 2.
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
local obs = obsluahotkeys = { htk_stop = "Стоп", htk_start = "Старт",}hk = {}function hotkey_mapping(hotkey) if hotkey == "htk_stop" then print('Стоп') elseif hotkey == "htk_start" then print('Старт') endendfunction htk_1_cb(pressed) if pressed then print('1') endendfunction htk_2_cb(pressed) if pressed then print('2 активно') else print('2 не активно') endendkey_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ],'key_2 = '"htk_2": [ { "key": "OBS_KEY_2" } ]}'json_s = key_1 .. key_2default_hotkeys = { {id='htk_1',des='Кнопка 1 ',callback=htk_1_cb}, {id='htk_2',des='Кнопка 2 ',callback=htk_2_cb},}function script_load(settings) for k, v in pairs(hotkeys) do hk[k] = obs.obs_hotkey_register_frontend(k, v, function(pressed) if pressed then hotkey_mapping(k) end end) a = obs.obs_data_get_array(settings, k) obs.obs_hotkey_load(hk[k], a) obs.obs_data_array_release(a) end 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)endfunction script_save(settings) for k, v in pairs(hotkeys) do a = obs.obs_hotkey_save(hk[k]) obs.obs_data_set_array(settings, k, a) obs.obs_data_array_release(a) endend
Задачи
Задача на движение по кругу:
На основе скрипта движение по линии, создайте скрипт с движением
вокруг часовой/против.
Задача на использование кнопок клавиатуры:
На основе скрипта с горячими клавишами, создайте скрипт с
переключателем вкл/выкл,
доп кнопкой через JSON, доп кнопкой с комбинацией клавиш через
JSON.