OBS Studio Lua Скриптинг

от автора

Всем привет, в этом руководстве рассмотрим создание скриптов для OBS на языке Lua.

Скриптинг в OBS доступен начиная с версии 21, на данный момент новейшая 26.0.0-rc3 версия доступна для тестирования.Обновление включает в себя виртуальную веб камеру (пока что только на Windows), улучшенный UI, возможность скриншота любого источника( КДПВ была сделана с помощью этой функции).

image

Описание глобальных функций, 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 = obslua local selected_source pos = obs.vec2() switch = false counter = 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 props end

Добавляем пользовательский интерфейс. 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 switch end

Кнопка переключатель и таймер периодического запуска функции в миллисекундах.
Гифка

Исходный код

local obs = obslua  local selected_source pos = obs.vec2() switch = false counter = 0  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 switch end  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_button(props,p)   move_source_on_scene() 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 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 props end  function 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('Старт')   end end

Словарь с клавишами и функция типа "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)   end end

Сохранение/загрузка изменяющихся горячих клавиш.

function htk_1_cb(pressed)    if pressed then     print('1')   end end  function htk_2_cb(pressed)    if pressed then     print('2 активно')   else     print('2 не активно')   end end  key_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ],' key_2 = '"htk_2": [ { "key": "OBS_KEY_2" } ]}' json_s = key_1 .. key_2 default_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 = obslua  hotkeys = {   htk_stop = "Стоп",   htk_start = "Старт", } hk = {}  function hotkey_mapping(hotkey)   if hotkey == "htk_stop" then     print('Стоп')   elseif hotkey == "htk_start" then     print('Старт')   end end  function htk_1_cb(pressed)    if pressed then     print('1')   end end  function htk_2_cb(pressed)    if pressed then     print('2 активно')   else     print('2 не активно')   end end  key_1 = '{"htk_1": [ { "key": "OBS_KEY_1" } ],' key_2 = '"htk_2": [ { "key": "OBS_KEY_2" } ]}' json_s = key_1 .. key_2 default_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) 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)   end end

Задачи

Задача на движение по кругу:
На основе скрипта движение по линии, создайте скрипт с движением вокруг часовой/против.

Гифка

Задача на использование кнопок клавиатуры:
На основе скрипта с горячими клавишами, создайте скрипт с переключателем вкл/выкл,
доп кнопкой через JSON, доп кнопкой с комбинацией клавиш через JSON.

Гифка

Ссылки

ссылка на оригинал статьи https://habr.com/ru/post/520684/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *