如何操作 OBS 场景?场景对象介绍
关注 1260
OBS 场景对象
场景对象(Scene Objects)与obspython
模块提供的场景函数,可用于操作场景。比如,将来源作为场景项添加至场景,或将场景项从场景移除。
什么是 OBS 场景?
场景(Scenes)是一种特殊的 OBS 来源,他可以管理由来源产生的场景项,这些场景项可能引用不同或相同的来源,场景项显示的名称即为其对应来源的名称。当多个场景项引用同一个来源时,他们的某些表现将是一致的,比如,显示在来源栏的名称。
什么是 OBS 私有场景?
私有场景与私有来源类似,无法被用户直接创建。通过 Python 脚本创建的私有场景不会出现在场景栏,在被添加至非私有场景后可显示在来源栏中。私有场景会在重启后消失,场景集合导出操作将忽略他。
需要特别指出,如果私有场景拥有非私有来源,那么这些非私有来源可能不会被清除。
私有场景和非私有场景的命名冲突问题
由于场景本身就是 OBS 来源,因此,私有场景与非私有场景在命名的问题上,遵守与来源一样的规则。
来源
关于 OBS 来源的命名冲突问题,你可以查看OBS 来源对象一段。
创建 OBS 场景
与创建 OBS 来源有所不同,创建场景只需要指定场景的名称即可。
obspython
模块的obs_scene_create
和obs_scene_create_private
函数,均可用于创建场景,两者的区别在于,obs_source_create_private
函数创建的来源是私有的。
obs_scene_create(name)
obs_scene_create_private(name)
- name 参数
name
参数为创建场景的期望名称,当发生命名冲突时,OBS 会修改期望名称,直到冲突消失。
使用 obs_scene_release 函数释放创建的场景对象
对于使用obs_scene_create
或obs_scene_create_private
函数创建的场景对象,需要通过obs_scene_release
释放引用,否则 OBS 可能会出现错误。
我们尝试在按钮的回调函数test
中,创建一个私有场景sub_scene
,并将其作为场景项添加至场景Scene
,假设Scene
存在。
# 导入模块 obspython
import obspython as obs
def test(props, prop):
# 创建一个名称为 sub_scene 的私有场景
scene_sub = obs.obs_scene_create_private('scene_sub')
# 获取场景 Scene 对应的场景对象
source_scene = obs.obs_get_source_by_name('Scene')
scene = obs.obs_scene_from_source(source_scene)
# 将私有场景 sub_scene 添加至场景 Scene
obs.obs_scene_add(scene, obs.obs_scene_get_source(scene_sub))
# 释放场景对象和来源对象
obs.obs_source_release(source_scene)
obs.obs_scene_release(scene_sub)
# 为脚本添加一个用于测试的按钮,回调函数为 test
def script_properties():
props = obs.obs_properties_create()
obs.obs_properties_add_button(props, 'test', '测试', test)
return props
复制 OBS 场景
obspython
模块的obs_scene_duplicate
函数,可用于复制场景,新场景的场景项对应的来源,可能是原场景中场景项对应来源的完全复制或阴影复制。对于阴影复制,新的场景项将与原有场景项共享同一个 OBS 来源,这意味着他们在某些方面的表现会相同。对于原场景中的私有来源,在其被复制到新场景后,依然为私有来源。对于原场景中的非私有来源,在其被复制到新场景后,依然为非私有来源。
obs_scene_duplicate(scene, name, type)
- scene 参数
scene
参数为被复制的场景对象。- name 参数
name
参数为新场景的期望名称,当发生命名冲突时,OBS 会修改期望名称,直到冲突消失。- type 参数
type
参数为场景的复制方式,可使用如下obspython
模块变量进行设置,OBS_SCENE_DUP_REFS
表示场景中的来源将采用阴影复制,OBS_SCENE_DUP_COPY
表示场景中的来源将尝试采用完全复制(对于不支持完全复制的来源,依然采用阴影复制),OBS_SCENE_DUP_PRIVATE_REFS
与OBS_SCENE_DUP_REFS
类似,只不过新的场景将是私有的,OBS_SCENE_DUP_PRIVATE_COPY
与OBS_SCENE_DUP_COPY
类似,只不过新的场景将是私有的。
使用 obs_scene_release 函数释放复制的场景对象
对于使用obs_scene_duplicate
函数复制的场景对象,需要通过obs_scene_release
释放引用,否则 OBS 可能会出现错误。
在下面的代码中,如果场景(来源)Game
不存在,那么会将场景Scene
复制为Game
,复制的方式为OBS_SCENE_DUP_REFS
。
def test(props, prop):
# …
# 将场景 Scene 复制为场景 Game,如果场景 Game 不存在
source_game = obs.obs_get_source_by_name('Game')
if not source_game:
scene_game = obs.obs_scene_duplicate(scene, 'Game', obs.OBS_SCENE_DUP_REFS)
# 释放场景对象
obs.obs_scene_release(scene_game)
else:
# 释放来源对象
obs.obs_source_release(source_game)
转换 OBS 场景对象与来源对象
在 OBS Python 脚本中,场景对象一般不与来源对象互换使用,想要获取场景对象对应的来源对象,或来源对象对应的场景对象,需要进行转换。
obspython
模块的obs_scene_get_source
函数,可用于获取场景对象对应的来源对象。obspython
模块的obs_scene_from_source
函数,可用于获取来源对象对应的场景对象,前提是该来源是一个场景。
obs_scene_get_source(scene)
obs_scene_from_source(source)
- scene 参数
scene
参数为需要获取来源对象的场景对象。- source 参数
source
参数为需要获取场景对象的来源对象。
为 OBS 场景添加来源
obspython
模块的obs_scene_add
函数,可用于将 OBS 来源作为场景项添加至场景,并返回一个场景项对象。
obs_scene_add(scene, source)
- scene 参数
scene
参数为需要添加场景项的场景对象。- source 参数
source
参数为添加场景项对应的来源对象。
在下面的代码中,我们创建了一个名称为message
的私有文字(GDI+)来源,并通过函数obs_scene_add
将其添加到了场景scene_sub
中。
def test(props, prop):
# …
# 创建一个文字(GDI+)来源
settings = obs.obs_data_create_from_json('{"text":"新消息"}')
source_text = obs.obs_source_create_private('text_gdiplus_v2', 'message', settings)
# 将文字(GDI+)添加至场景 scene_sub
obs.obs_scene_add(scene_sub, source_text)
# …
清除已移除 OBS 场景中的来源
当一个场景被移除时,其场景项对应的非私有来源依然可能存在,此时可以调用obspython
模块的obs_scene_prune_sources
函数,来移除这些非私有来源,如果他们没有任何引用的话。
obs_scene_prune_sources(scene)
- scene 参数
scene
参数为已经被移除的场景对象。
在下面的代码中,我们对场景项Welcome
进行了两次查询,一次包括分组,一次不包括,假设Welcome
是分组Group
中的场景项。
def test(props, prop):
# …
# 在移除场景 World 之后,尝试移除不再使用的其他来源
source_world = obs.obs_get_source_by_name('World')
scene_world = obs.obs_scene_from_source(source_world)
obs.obs_source_remove(source_world)
obs.obs_scene_prune_sources(scene_world)
obs.obs_source_release(source_world)
# …
添加和释放对 OBS 场景的引用
作为一种来源,当场景不存在任何引用时,他将被销毁,如果你没有或过多的进行了场景的释放,那么 OBS 可能会出现错误。obspython
模块提供了以下与场景引用相关的函数。
obs_scene_get_ref
函数,可用于为场景对象添加引用。每当你额外调用一次obs_scene_get_ref
函数,就需要对等增加一次obs_scene_release
函数的调用。
OBS 27.2.0 之前,应使用函数obs_scene_addref
,而非obs_scene_get_ref
。
obs_scene_release
函数,可用于为场景对象释放引用,他适用于obs_scene_create
,obs_scene_create_private
,obs_scene_duplicate
函数所返回的场景对象。
obs_scene_get_ref(scene)
obs_scene_release(scene)
- scene 参数
scene
参数为需要添加或释放引用的场景对象。