[Работа с видео, API, Lua] OBS Studio Lua Скриптинг
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Всем привет, в этом руководстве рассмотрим создание скриптов для 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 = 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
Кнопка переключатель и таймер периодического запуска функции в миллисекундах.
Исходный код
SPL
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
Исходный код
SPL
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.
Ссылки
- Книга 1-го издания Lua
- Задания тесты Lua
- Модули доступные в LuaJIT
- Документация по скриптингу OBS
- Заметки, краткое описание OBS API и модуль obspython
- Форумный раздел со скриптами OBS
- Дискорд комната #scripting
- Гитхаб гист obslua
- Гитхаб поиск obslua
- Баг API где в аргументах указатель-указатель
===========
Источник:
habr.com
===========
Похожие новости:
- [API, Геоинформационные сервисы, Визуализация данных, Инфографика] Кому на Руси жить хорошо? Как мы искали самый “зеленый” город с помощью OpenStreetMap и Overpass API
- [CMS, Разработка веб-сайтов] Почему для информационных проектов из всех Headless CMS мы часто выбираем Strapi
- [Тестирование IT-систем, Программирование, TDD] Деконструкция TDD
- [Facebook API, Лайфхаки для гиков, Социальные сети и сообщества] Как узнать, кто отписался в Instagram? И почему мобильные приложения больше не работают
- [API, Big Data, IT-компании, Искусственный интеллект, Софт] Искусственный интеллект может предупредить о приближении эвакуатора
- [Настройка Linux, Программирование, Go, Разработка под Linux] eBPF: современные возможности интроспекции в Linux, или Ядро больше не черный ящик
- [API, Data Engineering, R, Системы обмена сообщениями] Пишем telegram бота на языке R (часть 4): Построение последовательного, логического диалога с ботом
- [Open source, Python, Data Mining, Big Data] Crime, Race and Lethal Force in the USA — Part 3 (перевод)
- [API, Big Data, Data Mining, Интерфейсы, Открытые данные] Парсинг сайта Умного Голосования и новый API на сайте ЦИК
- [Финансы в IT] Хакеры остановили торги на бирже в Новой Зеландии
Теги для поиска: #_rabota_s_video (Работа с видео), #_api, #_lua, #_obs, #_obslua, #_obs_studio, #_lua, #_video, #_livestream, #_streaming_video, #_luajit, #_api, #_strim (стрим), #_striming (стриминг), #_zapis_video (запись видео), #_realnoe_vremja (реальное время), #_rabota_s_video (
Работа с видео
), #_api, #_lua
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 06:38
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Всем привет, в этом руководстве рассмотрим создание скриптов для OBS на языке Lua. Скриптинг в OBS доступен начиная с версии 21, на данный момент новейшая 26.0.0-rc3 версия доступна для тестирования.Обновление включает в себя виртуальную веб камеру (пока что только на Windows), улучшенный UI, возможность скриншота любого источника( КДПВ была сделана с помощью этой функции). Описание глобальных функций, API, настроек Добавить скрипт можно через меню -> Инструменты -> Скрипты -> значок "плюс". Скрипты могут быть добавлены, перезагружены, удалены в режиме реального времени. Сходства и различия c С-API Сходства: почти полный доступ к API, СБОЙ или УТЕЧКА ПАМЯТИ с неправильно написанным скриптом. Различия: некоторые функции(с двойными указателями) недоступны, некоторые заменены на другие. У каждого скрипта своё пространство имён, убедиться в этом можно открыв текущую коллекцию сцен "~/obs-studio/basic/scenes". Настройки settings представляют собой JSON строку, они могут быть созданы/загружены/сохранены с помощью JSON строк или файлов. Описание функций:
Пример скрипта Скрипт: Движение по линии с использованием кнопок и таймера. 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 Кнопка переключатель и таймер периодического запуска функции в миллисекундах. Исходный кодSPLlocal 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 Исходный кодSPLlocal 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. Ссылки
=========== Источник: habr.com =========== Похожие новости:
Работа с видео ), #_api, #_lua |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 06:38
Часовой пояс: UTC + 5