Bonjour à tous, dans cette partie du tutoriel, nous allons considérer: les
filtres, les scènes, les objets de scène, l'API Frontend, la création de filtres fonctionnels, et plus encore ...
La première partie se trouve sur ce lien.
Référence rapide pour cette partie
Source - Les sources sont utilisées pour rendre l'audio / vidéo, par exemple: capture d'une caméra, d'un jeu, d'un son. En utilisant des sources, vous pouvez créer des filtres, des transitions
—
-
— , : , /, , / ..
Frontend API — OBS Studio, :
- , /
- / /
, obs_source_get_unversioned_id
compressor_filter | |
expander_filter | |
gain_filter | |
invert_polarity_filter | |
limiter_filter | |
noise_gate_filter | |
noise_suppress_filter | |
VST 2.x | vst_filter |
() | async_delay_filter |
chroma_key_filter | |
color_filter | |
color_key_filter | |
crop_filter | |
/ | mask_filter |
luma_key_filter | |
gpu_delay | |
/ | scale_filter |
scroll_filter | |
sharpness_filter |
: 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
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 htk_1_cb(pressed)
if pressed then
n = math.random(1,100)
add_filter_to_source(n)
end
end
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
.
function on_event(event)
if event == obs.OBS_FRONTEND_EVENT_SCENE_CHANGED
then obs_play_sound_release_source()
end
end
, : alert.mp3
, obs_source_set_monitoring_type
.
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
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" — .
io.output(io.open(script_path() .. "out.txt","a"))
io.write("content")
io.close()
print(os.date("%c"))
--
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
...
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
.
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 -.
.:
- , OO, ..
- http://lua-users.org/wiki/LuaVersusPython — Lua Python
, ,
script_tick
( )
logs
,
— : Number of memory leaks: 0
,
. OBS .
3)[] " "
,
( ) (scroll_filter),
/
0 1000 / 50% .
4)[] ""
.
— ( error())
5)[ ] "-"
,
, "",
UI , .
7) [ ] " "
2 .
- DVD
- https://github.com/WiiPlayer2/obs-scripts —
- https://github.com/bfxdev/OBS — ,
- https://github.com/Palakis/obs-websocket — API OBS Studio websocket, OBS