URLhttps://learnscript.net/zh/obs-python-scripting/sources/
    复制链接转到说明  示例

    如何操作 OBS 来源?来源对象介绍

    我被代码海扁署名-非商业-禁演绎
    阅读 24:47·字数 7436·发布 

    OBS 来源对象

    通过 OBS 来源对象(Source Objects)以及obspython模块提供的函数,你可以在 Python 脚本中操作 OBS 来源。

    什么是 OBS 来源?

    OBS 中的来源(Sources)主要用于渲染视频流和音频流,这包括显示器采集,窗口采集,图像,场景,滤镜,转场特效等。

    什么是 OBS 私有来源?

    与一般来源不同,用户无法直接创建私有来源。私有来源无法被obs_enum_sources函数枚举,也无法被obs_save_sources函数保存,这意味任何涉及保存场景集合的操作,都将忽略私有来源和由其产生的场景项。

    私有来源和非私有来源的命名冲突问题

    由于存在 OBS 来源的创建和复制操作,因此来源之间可能会发生命名上的冲突,无论这是来自于用户还是 Python 脚本,他们大体上会遵守以下规则。私有来源之间,以及私有来源与非私有来源之间不会检测命名冲突。非私有来源之间会检测命名冲突,不同的非私有来源不能具有相同的名称。

    虽然允许私有来源与非私有来源同名,但这种情况应尽量避免,因为他们可能导致一些诡异的问题。

    创建 OBS 来源

    obspython模块提供了以下函数,用于创建新的来源。

    obs_source_createobs_source_create_private函数,可以使用指定的来源类型和来源设置创建来源,创建失败时会返回空值None。两者的区别在于,obs_source_create_private函数会创建私有来源。

    obs_source_create(id, name, settings, hotkey_data)
    obs_source_create_private(id, name, settings)

    id 参数

    id参数为来源类型标识符,他将决定创建来源的类型。

    name 参数

    name参数为创建来源的期望名称,当发生命名冲突时,OBS 会修改期望名称,直到冲突消失。

    settings 参数

    settings参数是一个数据设置对象,他表示了来源的设置,其包含的内容由来源类型确定。如果指定为None,则会采用来源的默认配置。

    hotkey_data 参数

    hotkey_data参数是一个数据设置对象,他表示了来源对应的快捷键,可以被指定为None

    什么是 OBS 来源设置?

    和脚本设置类似,OBS 来源设置也是一个数据设置对象,顾名思义,他决定了来源的相关设置,比如,图片来源对应的图片文件路径。

    什么是 OBS 来源类型标识符?

    OBS 的每一种来源都对应了一个来源类型标识符(Source Type Identifiers),该标识符可以有效区分不同类型的来源。比如,文本(GDI+)的来源类型标识符为text_gdiplus,图像的来源类型标识符为image_source

    使用 obs_source_release 函数释放创建的来源对象

    对于使用obs_source_createobs_source_create_private函数创建的来源对象,需要通过obs_source_release释放引用,否则 OBS 可能会出现错误。

    我们尝试在按钮的回调函数test中,创建一个私有文本(GDI+)来源,并通过数据设置对象对来源进行设置,最后将文本(GDI+)作为场景项添加到场景Scene中,假设Scene存在。这里涉及到与场景相关的函数,但由于篇幅限制,不再进行说明。

    sources.py
    # 导入模块 obspython
    import obspython as obs
    
    def test(props, prop): # 创建一个名称为 my_text 的私有文本(GDI+)来源,并将字符串 "今天天气不错!" 设置为文本 settings = obs.obs_data_create_from_json('{"text":"今天天气不错!"}') source_text = obs.obs_source_create_private('text_gdiplus', 'my_text', settings)
    # 将文本(GDI+)来源,添加至名为 Scene 的场景 source_scene = obs.obs_get_source_by_name('Scene') scene = obs.obs_scene_from_source(source_scene) obs.obs_scene_add(scene, source_text)
    # 释放来源对象和来源设置对象 obs.obs_source_release(source_scene) obs.obs_source_release(source_text) obs.obs_data_release(settings)
    # 为脚本添加一个用于测试的按钮,回调函数为 test def script_properties(): props = obs.obs_properties_create() obs.obs_properties_add_button(props, 'test', '测试', test) return props

    复制 OBS 来源

    obspython模块的obs_source_duplicate函数,可用于复制来源。

    这里需要指出,如果来源不支持完全复制,那么obs_source_duplicate函数所返回的来源是对原有来源的引用。

    obs_source_duplicate(source, desired_name, create_private)

    source 参数

    source参数为被复制的来源对象。

    desired_name 参数

    desired_name参数为新来源的期望名称,当发生命名冲突时,OBS 会修改期望名称,直到冲突消失。

    create_private 参数

    create_private参数表示新来源是否为私有来源,仅对完全复制的来源生效,采用引用方式得到的新来源无法成为私有来源。

    使用 obs_source_release 函数释放复制的来源对象

    对于使用obs_source_duplicate函数复制的来源对象,需要通过obs_source_release释放引用,否则 OBS 可能会出现错误。

    在下面的代码中,我们对已有的来源Welcome进行了复制,由于并未将复制得到的新来源添加至场景,因此他无法作为场景项显示在 OBS 窗口中。

    sources.py
    def test(props, prop):
    	# …
    	# 复制名称为 Welcome 的来源,并指定新名称 Bye
    	welcome = obs.obs_get_source_by_name('Welcome')
    	bye = obs.obs_source_duplicate(welcome, 'Bye', False)
    
    # 释放来源 Welcome 和 Bye obs.obs_source_release(welcome) obs.obs_source_release(bye)

    获取 OBS 来源

    obspython模块的obs_get_source_by_name函数,可用于获取指定名称的来源(对象)。

    obs_get_source_by_name(name)

    name 参数

    name参数为来源的名称。

    obspython模块的obs_get_source_by_uuid函数,可用于获取指定 UUID 的 OBS 来源(对象),UUID 会在来源被创建时自动分配,不同来源的 UUID 不会相同。

    obs_get_source_by_uuid(uuid)

    uuid 参数

    uuid参数为来源的 UUID。

    如何获取私有来源?

    你需要使用obs_get_source_by_uuid函数而非obs_get_source_by_name来获取一个私有来源,因此,通过obs_source_get_uuid函数记录所创建的私有来源的 UUID 是必要的。

    使用 obs_data_release 函数释放获取的来源对象

    对于使用obs_get_source_by_nameobs_get_source_by_uuid函数获取的来源对象,需要通过obs_source_release释放引用,否则 OBS 可能会出现错误。

    获取和设置 OBS 来源的设置

    正如之前提到的,OBS 来源设置是一个数据设置对象,该对象的作用类似于 Python 脚本的脚本设置对象,他是实现通过脚本操作来源的关键要素之一,不同类型的来源,其来源设置对象所包含的内容会有所差异。obspython模块提供了以下关于来源设置的函数。

    obs_source_get_settings函数,可用于获取来源对应的来源设置对象,obs_source_get_private_settings函数,可用于获取来源对应的私有来源设置对象,该对象应存放不希望对用户公开的设置。

    obs_source_get_settings(source)
    obs_source_get_private_settings(item)

    source 参数

    source参数为需要获取来源设置对象的来源对象。

    item 参数

    item参数为需要获取私有来源设置对象的来源对象。

    obs_source_update函数,可用于更新来源的来源设置对象,这将直接改变来源在 OBS 中的行为或表现,当然,对于某些类型的来源,改变带来的效果可能不会立即显现。

    obs_source_reset_settings函数,可用于重置和更新来源的来源设置对象,清除现有来源设置的工作会首先进行,这意味着所有的设置都将恢复为默认。

    obs_source_update(source, settings)
    obs_source_reset_settings(source, settings)

    source 参数

    source参数为需要更新或重置更新来源设置对象的来源对象。

    settings 参数

    settings参数为用于更新来源设置对象的数据设置对象。

    obs_get_source_defaults函数,可用于获取某类型来源的来源设置默认值,默认值将被包含在一个新的 OBS 来源设置对象(数据设置对象)中返回。

    obs_get_source_defaults(id)

    id 参数

    id参数为来源类型标识符,obs_get_source_defaults函数将返回该标识符对应的来源类型的来源设置默认值。

    使用 obs_data_release 函数释放获取的来源设置对象

    对于使用obs_source_get_settingsobs_source_get_private_settingsobs_get_source_defaults函数获取的来源设置对象,需要通过obs_data_release释放引用,否则 OBS 可能会出现错误。

    调整之前的代码,我们通过obs_source_get_settingsobs_source_update函数,更新了Welcome来源的文本。

    sources.py
    def test(props, prop):
    	# …
    	# 通过 Welcome 的来源设置对象,修改其对应的文本
    	settings = obs.obs_source_get_settings(welcome)
    	obs.obs_data_set_string(settings, 'text', '你好,欢迎!')
    	obs.obs_source_update(welcome, settings)
    	# 释放来源设置对象
    	obs.obs_data_release(settings)
    	# …

    获取 OBS 来源的原始宽度和高度

    obspython模块的obs_source_get_widthobs_source_get_height函数,可用于获取来源的原始宽度和高度,这并不会将转场特效计算在内,因此obs_source_get_widthobs_source_get_height函数所返回的并非来源对应场景项的实际显示大小。

    obs_source_get_width(source)
    obs_source_get_height(source)

    source 参数

    source参数为需要获取原始宽度或高度的来源对象。

    sources.py
    def test(props, prop):
    	# …
    	# 显示 Weclome 来源的大小
    	width = obs.obs_source_get_width(welcome)
    	height = obs.obs_source_get_height(welcome)
    	obs.script_log(obs.LOG_INFO, f'Welcome 的大小 {width}x{height}')
    	# …
    [sources.py] Welcome 的大小 1520x264

    判断 OBS 来源是否有效

    OBS 来源的有效状态用于指示其是否被用于渲染输出,处于无效状态的来源并未真正的参与渲染,比如,当用户将场景项隐藏时,其对应的来源可能将处于无效状态。需要说明的是,是否处于有效状态与来源是否可用无关。

    obspython模块的obs_source_active函数,可用于判断来源是否处于有效状态,返回True表示来源处于有效状态,返回False表示来源处于无效状态。

    obs_source_active(source)

    source 参数

    source参数为需要判断有效状态的来源对象。

    获取和设置 OBS 来源是否可用

    obspython模块的obs_source_enabledobs_source_set_enabled函数,可用于获取和设置来源是否可用(启用或禁用)。对于不可用的来源,不会在渲染中产生任何效果。需要说明的是,是否可用并不影响来源的有效状态。

    obs_source_enabled(source)
    obs_source_set_enabled(source, enabled)

    source 参数

    source参数为需要获取或设置是否可用的来源对象。

    enabled 参数

    enabled参数为True时,将启用来源,为False时,将禁用来源。

    获取和设置 OBS 来源是否可见

    obspython模块的obs_source_showing函数与obs_source_active类似,可判断来源是否已经被渲染至最终输出,只不过obs_source_showing的返回结果,可以通过obs_source_inc_showingobs_source_dec_showing函数进行干预。

    obs_source_showing(source)

    source 参数

    source参数为需要判断是否可见的来源对象。

    obspython模块的obs_source_inc_showingobs_source_dec_showing函数,可增加或减少来源的可见计数,这将最终影响obs_source_showing的返回结果。需要说明的是,虽然可通过obs_source_inc_showingobs_source_dec_showing控制obs_source_showing的返回结果,但最终输出可能不会改变。

    obs_source_inc_showing(source)
    obs_source_dec_showing(source)

    source 参数

    source参数为需要增加或减少可见计数的来源对象。

    获取和设置 OBS 来源的名称

    obspython模块的obs_source_get_nameobs_source_set_name函数,可用于获取或设置来源的名称,该名称可显示在 OBS 的相关窗口中。

    obs_source_get_name(source)
    obs_source_set_name(source, name)

    source 参数

    source参数为需要获取或设置名称的来源对象。

    name 参数

    name参数为修改后的名称,如果存在命名冲突,那么 OBS 会对名称进行修改,直到冲突消失。

    下面的代码,通过obs_source_set_name函数将名称为Groups的来源改名为Group,假设存在分组来源Groups

    sources.py
    def test(props, prop):
    	# …
    	# 如果存在名称为 Groups 的来源,则将其改名为 Group
    	groups = obs.obs_get_source_by_name('Groups')
    	if groups:
    		obs.obs_source_set_name(groups, 'Group')
    		obs.obs_source_release(groups)

    获取 OBS 来源的类型

    obspython模块的obs_source_get_type函数,可用于获取来源的类型,其返回值可能对应以下某个obspython模块变量,OBS_SOURCE_TYPE_INPUT(输入,一般来源均为此类型),OBS_SOURCE_TYPE_FILTER(滤镜),OBS_SOURCE_TYPE_TRANSITION(转场特效),OBS_SOURCE_TYPE_SCENE(场景)。

    obs_source_get_type(source)

    source 参数

    source参数为需要获取类型的来源对象。

    另外,obspython模块的obs_source_is_scene函数,可用于判断来源是否为场景,obspython模块的obs_source_is_group函数,可用于判断来源是否为分组。

    obs_source_is_scene(source)
    obs_source_is_group(source)

    source 参数

    source参数为需要判断是否为场景或分组的来源对象。

    在下面的代码中,我们获取了来源Groups的类型,并判断其是否为分组。从输出的结果可以得知,分组的类型为OBS_SOURCE_TYPE_SCENE

    sources.py
    def test(props, prop):
    	# …
    	# 显示 Group 来源的类型,并判断是否为分组
    	group = obs.obs_get_source_by_name('Group')
    	group_type = obs.obs_source_get_type(group)
    	obs.script_log(obs.LOG_INFO, f'Group 的类型 {group_type},等于 OBS_SOURCE_TYPE_SCENE?{group_type == obs.OBS_SOURCE_TYPE_SCENE}')
    	obs.script_log(obs.LOG_INFO, f'Group 是分组?{obs.obs_source_is_group(group)}')
    	obs.obs_source_release(group)
    [sources.py] Group 的类型 3,等于 OBS_SOURCE_TYPE_SCENE?True
    [sources.py] Group 是分组?True

    获取和设置 OBS 来源的 ID

    obspython模块的obs_source_get_idobs_source_get_unversioned_id函数,可用于获取来源的来源类型标识符,二者的区别在于是否带有版本信息。

    obs_source_get_id(source)
    obs_source_get_unversioned_id(source)

    source 参数

    source参数为需要获取来源类型标识符的来源对象。

    obspython模块的obs_source_get_uuid函数,可用于获取来源的 UUID,每一个来源都拥有一个唯一的 UUID。

    obs_source_get_uuid(source)

    source 参数

    source参数为需要获取 UUID 的来源对象。

    sources.py
    def test(props, prop):
    	# …
    	# 显示 Weclome 来源的来源类型标识符和 UUID
    	v_id = obs.obs_source_get_id(welcome)
    	id = obs.obs_source_get_unversioned_id(welcome)
    	obs.script_log(obs.LOG_INFO, f'Welcome 的 id {v_id} {id}')
    	uuid = obs.obs_source_get_uuid(welcome)
    	obs.script_log(obs.LOG_INFO, f'Welcome 的 uuid {uuid}')
    	# …
    [sources.py] Welcome 的 id text_gdiplus_v2 text_gdiplus
    [sources.py] Welcome 的 uuid 84808b04-9373-4c21-b3b8-c506bbc8effb

    移除 OBS 来源

    当你不再需要某个来源时,可以使用obspython模块的obs_source_remove函数将其移除,这会使该来源以及该来源产生的场景项立即从 OBS 的相关窗口中消失,比如来源栏

    obs_source_remove(source)

    source 参数

    source参数为需要移除的来源对象。

    obspython模块的obs_source_removed函数,可用于判断来源是否已经被移除,返回True表示已经被移除。

    obs_source_removed(source)

    source 参数

    source参数为需要判断是否被移除的来源对象。

    被 obs_source_remove 函数移除的来源依然可能存在

    这里需要指出,被obs_source_remove函数移除的来源,如果未释放所有的引用,那么他依然可以在 Python 脚本中访问,比如,通过obs_get_source_by_name获取。

    下面的代码,移除了来源Screen,假设分组Group包含该来源。

    sources.py
    def test(props, prop):
    	# …
    	# 来源 Screen 如果存在,则将其移除
    	screen = obs.obs_get_source_by_name('Screen')
    	if screen:
    		obs.obs_source_remove(screen)
    		obs.script_log(obs.LOG_INFO, f'Screen 被移除?{obs.obs_source_removed(screen)}')
    [sources.py] Screen 被移除?True

    添加和释放对 OBS 来源的引用

    如果一个来源(对象)不存在任何引用,那么该来源将被销毁,毫无疑问,这增加了 Python 脚本的编写难度,没有或过多的释放引用,均可能导致 OBS 发生异常。假设,你不小心对来源进行了过多的释放,那么一个错误窗口可能在所难免。obspython模块提供了以下与来源引用相关的函数。

    obs_source_get_ref函数(OBS 27.2.0 之前为obs_source_addref函数),可用于为来源对象添加引用。每当你额外调用一次obs_source_get_ref函数,就需要对等增加一次obs_source_release函数的调用。

    OBS 27.2.0 之前,应使用函数obs_source_addref,而非obs_source_get_ref

    obs_source_release函数,可用于为来源对象释放引用,他适用于obs_source_createobs_source_create_privateobs_source_duplicateobs_get_source_by_nameobs_get_source_by_uuidobs_source_get_filter_by_nameobs_get_transition_by_name函数所返回的来源对象。

    obs_source_get_ref(source)
    obs_source_release(source)

    source 参数

    source参数为需要添加或释放引用的来源对象。

    获取和设置 OBS 来源是否隐藏

    如果希望添加一些对用户不公开的来源,那么可将其设置为隐藏,隐藏来源产生的场景项不会出现在来源栏中,也不会作为场景的一部分保存,这意味着你总是需要在适当的时机创建并添加他们。

    obspython模块的obs_source_is_hidden函数,可用于判断来源是否对用户隐藏,返回False表示不隐藏,True表示隐藏。obspython模块的obs_source_set_hidden函数,可用于设置来源是否对用户隐藏,该函数需要在场景项显示在来源栏之前调用,否则其效果不会是立即的。

    obs_source_is_hidden(source)
    obs_source_set_hidden(source, hidden)

    source 参数

    source参数为需要设置是否隐藏的来源对象。

    hidden 参数

    hidden参数表示是否隐藏,False表示不隐藏,True表示隐藏。

    获取和设置 OBS 来源的输出标志

    obspython模块的obs_source_get_output_flagsobs_get_source_output_flags函数,可用于获取来源类型的输出标志,输出标志表示了该类型的来源所具备的功能,你可以将其视为一组枚举成员的组合(虽然并不是真正的枚举)。由于篇幅限制,这里不再详细解释他们。

    obs_source_get_output_flags(source)
    obs_get_source_output_flags(id)

    source 参数

    source参数是一个来源对象,obs_source_get_output_flags函数将返回该对象对应的来源类型的输出标志。

    id 参数

    id参数为来源类型标识符,obs_get_source_output_flags函数将返回该标识符对应的来源类型的输出标志。

    在下面的代码中,我们通过obs_source_get_output_flags函数获取了媒体源Video的输出标志,并判断其是否具有视频和音频功能。

    sources.py
    def test(props, prop):
    	# …
    	# 判断来源 Video 的输出标志
    	video = obs.obs_get_source_by_name('Video')
    	flags = obs.obs_source_get_output_flags(video)
    	obs.script_log(obs.LOG_INFO, f'Video 具有视频功能?{flags & obs.OBS_SOURCE_VIDEO == obs.OBS_SOURCE_VIDEO}')
    	obs.script_log(obs.LOG_INFO, f'Video 具有音频功能?{flags & obs.OBS_SOURCE_AUDIO == obs.OBS_SOURCE_AUDIO}')
    	obs.obs_source_release(video)
    [sources.py] Video 具有视频功能?True
    [sources.py] Video 具有音频功能?True

    获取 OBS 来源类型的显示名称

    obspython模块的obs_source_get_display_name函数,可用于获取指定来源类型对应的显示名称,该函数的返回值由当前 OBS 的语言来确定。

    obs_source_get_display_name(id)

    id 参数

    id参数为某个来源类型标识符,比如text_gdiplus,这将使obs_source_get_display_name函数返回字符串'文字 (GDI+)',如果 OBS 语言为中文的话。

    内容分类

    源码

    sources.py·codebeatme/obs-python-scripting·GitHub