如何使用 Python 脚本操作 OBS 场景?OBS 场景对象介绍
Python 脚本中的 OBS 场景对象
OBS 场景对象(Scene Objects)与obspython
模块提供的场景函数,可用于操作场景。比如,将来源作为场景项添加至 OBS 场景,或将场景项从 OBS 场景移除。
什么是 OBS 场景?
OBS 场景(Scenes)是一种特殊的 OBS 来源,他可以管理由 OBS 来源产生的场景项,这些场景项可能引用不同或相同的来源,场景项显示的名称即为其对应来源的名称。当多个场景项引用同一个 OBS 来源时,他们的某些表现将是一致的,比如,显示在来源栏的名称。
什么是 OBS 私有场景?
OBS 私有场景与私有来源类似,无法被 OBS 用户直接创建。通过 Python 脚本创建的私有场景不会出现在场景栏,在被添加至非私有场景后可显示在 OBS 的来源栏中。OBS 私有场景会在重启后消失,场景集合导出操作将忽略他。
需要特别指出,如果 OBS 私有场景拥有非私有来源,那么这些非私有来源可能不会被清除。
OBS 私有场景和 OBS 非私有场景的命名冲突问题
由于 OBS 场景本身就是 OBS 来源,因此,OBS 私有场景与 OBS 非私有场景在命名的问题上,遵守与 OBS 来源一样的规则。
来源
关于 OBS 来源的命名冲突问题,你可以查看Python 脚本中的 OBS 来源对象一段。
使用 Python 脚本创建 OBS 场景
与创建 OBS 来源有所不同,创建 OBS 场景只需要指定场景的名称即可。
obspython
模块的obs_scene_create
和obs_scene_create_private
函数,均可用于创建 OBS 场景,两者的区别在于,obs_source_create_private
函数创建的来源是私有的。
obs_scene_create(name)
obs_scene_create_private(name)
- name 参数
name
参数为创建场景的期望名称,当发生命名冲突时,OBS 会修改期望名称,直到冲突消失。
使用 obs_scene_release 函数释放在 Python 脚本中创建的 OBS 场景对象
对于使用obs_scene_create
或obs_scene_create_private
函数创建的 OBS 场景对象,需要通过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
使用 Python 脚本复制 OBS 场景
obspython
模块的obs_scene_duplicate
函数,可用于复制 OBS 场景,新场景的场景项对应的来源,可能是原场景中场景项对应来源的完全复制或阴影复制。对于阴影复制,新的场景项将与原有场景项共享同一个 OBS 来源,这意味着他们在某些方面的表现会相同。对于原场景中的私有来源,在其被复制到新场景后,依然为私有来源。对于原场景中的非私有来源,在其被复制到新场景后,依然为非私有来源。
obs_scene_duplicate(scene, name, type)
- scene 参数
scene
参数为被复制的 OBS 场景对象。- 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 函数释放在 Python 脚本中复制的 OBS 场景对象
对于使用obs_scene_duplicate
函数复制的 OBS 场景对象,需要通过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)
使用 Python 脚本转换 OBS 场景对象与来源对象
在 OBS Python 脚本中,场景对象一般不与来源对象互换使用,想要获取场景对象对应的来源对象,或来源对象对应的场景对象,需要进行转换。
obspython
模块的obs_scene_get_source
函数,可用于获取 OBS 场景对象对应的 OBS 来源对象。obspython
模块的obs_scene_from_source
函数,可用于获取 OBS 来源对象对应的 OBS 场景对象,前提是该来源是一个场景。
obs_scene_get_source(scene)
obs_scene_from_source(source)
- scene 参数
scene
参数为需要获取来源对象的 OBS 场景对象。- source 参数
source
参数为需要获取场景对象的 OBS 来源对象。
使用 Python 脚本为 OBS 场景添加来源
obspython
模块的obs_scene_add
函数,可用于将 OBS 来源作为场景项添加至场景,并返回一个场景项对象。
obs_scene_add(scene, source)
- scene 参数
scene
参数为需要添加场景项的 OBS 场景对象。- source 参数
source
参数为添加场景项对应的 OBS 来源对象。
在下面的代码中,我们创建了一个名称为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)
# …
使用 Python 脚本清除已移除 OBS 场景中的来源
当一个 OBS 场景被移除时,其场景项对应的非私有来源依然可能存在,此时可以调用obspython
模块的obs_scene_prune_sources
函数,来移除这些非私有来源,如果他们没有任何引用的话。
obs_scene_prune_sources(scene)
- scene 参数
scene
参数为已经被移除的 OBS 场景对象。
在下面的代码中,我们对场景项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)
# …
使用 Python 脚本添加和释放对 OBS 场景的引用
作为一种来源,当 OBS 场景不存在任何引用时,他将被销毁,如果你没有或过多的进行了场景的释放,那么 OBS 可能会出现错误。obspython
模块提供了以下与场景引用相关的函数。
obs_scene_get_ref
函数,可用于为 OBS 场景对象添加引用。每当你额外调用一次obs_scene_get_ref
函数,就需要对等增加一次obs_scene_release
函数的调用。
OBS 27.2.0 之前,应使用函数obs_scene_addref
,而非obs_scene_get_ref
。
obs_scene_release
函数,可用于为 OBS 场景对象释放引用,他适用于obs_scene_create
,obs_scene_create_private
,obs_scene_duplicate
函数所返回的 OBS 场景对象。
obs_scene_get_ref(scene)
obs_scene_release(scene)
- scene 参数
scene
参数为需要添加或释放引用的 OBS 场景对象。