如何使用 Python 腳本操作 OBS 來源?OBS 來源物件介紹

閱讀 25:33·字數 7669·發佈 
Youtube 頻道
訂閱 133

Python 腳本中的 OBS 來源物件

通過 OBS 來源物件(Source Objects)以及obspython模組提供的函式,你可以在 Python 腳本中操作 OBS 的來源。

什麽是 OBS 來源?

OBS 中的來源(Sources)主要用於算繪視訊串流和音訊串流,這包括顯示器擷取,視窗擷取,圖片,場景,濾鏡,轉場特效等。

什麽是 OBS 私用來源?

與一般來源不同,OBS 使用者無法直接建立私用來源。私用來源無法被obs_enum_sources函式列舉,也無法被obs_save_sources函式儲存,這意味任何涉及儲存場景群組的操作,都將忽略私用來源和由其產生的場景項。

OBS 私用來源和 OBS 非私用來源的命名沖突問題

由於存在 OBS 來源的建立和複製操作,因此來源之間可能會發生命名上的沖突,無論這是來自於 OBS 使用者還是 Python 腳本,他們大體上會遵守以下規則。私用來源之間,以及私用來源與非私用來源之間不會檢測命名沖突。非私用來源之間會檢測命名沖突,不同的非私用來源不能具有相同的名稱。

雖然允許 OBS 私用來源與 OBS 非私用來源同名,但這種情況應盡量避免,因為他們可能導致一些詭異的問題。

使用 Python 腳本建立 OBS 來源

OBS 的obspython模組提供了以下函式,用於建立新的 OBS 來源。

obs_source_createobs_source_create_private函式,可以使用指定的 OBS 來源類型和 OBS 來源設定建立 OBS 來源,建立失敗時會傳回空值None。兩者的區別在於,obs_source_create_private函式會建立私用 OBS 來源。

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

id 參數

id參數為來源類型識別碼,他將決定建立來源的類型。

name 參數

name參數為建立來源的期望名稱,當發生命名沖突時,OBS 會修改期望名稱,直到沖突消失。

settings 參數

settings參數是一個 OBS 資料設定物件,他表示了來源的設定,其包含的內容由來源類型確定。如果指定為None,則會采用來源的預設設定。

hotkey_data 參數

hotkey_data參數是一個 OBS 資料設定物件,他表示了來源對應的快速鍵,可以被指定為None

什麽是 OBS 來源設定?

和腳本設定類似,OBS 來源設定也是一個 OBS 資料設定物件,顧名思義,他決定了 OBS 來源的相關設定,比如,圖片來源對應的圖片檔案路徑。

什麽是 OBS 來源類型識別碼?

OBS 的每一種來源都對應了一個來源類型識別碼(Source Type Identifiers),該識別碼可以有效區分不同類型的 OBS 來源。比如,文字(GDI+)的來源類型識別碼為text_gdiplus,圖片的來源類型識別碼為image_source

使用 obs_source_release 函式釋放在 Python 腳本中建立的 OBS 來源物件

對於使用obs_source_createobs_source_create_private函式建立的 OBS 來源物件,需要通過obs_source_release釋放參考,否則 OBS 可能會出現錯誤。

我們嘗試在按鈕的回呼函式test中,建立一個私用文字(GDI+)來源,並通過 OBS 資料設定物件對來源進行設定,最後將文字(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

使用 Python 腳本複製 OBS 來源

obspython模組的obs_source_duplicate函式,可用於複製 OBS 來源。

這裏需要指出,如果 OBS 來源不支援完全複製,那麽obs_source_duplicate函式所傳回的來源是對原有 OBS 來源的參考。

obs_source_duplicate(source, desired_name, create_private)

source 參數

source參數為被複製的 OBS 來源物件。

desired_name 參數

desired_name參數為新來源的期望名稱,當發生命名沖突時,OBS 會修改期望名稱,直到沖突消失。

create_private 參數

create_private參數表示新來源是否為私用來源,僅對完全複製的 OBS 來源生效,采用參考方式得到的新來源無法成為私用來源。

使用 obs_source_release 函式釋放在 Python 腳本中複製的 OBS 來源物件

對於使用obs_source_duplicate函式複製的 OBS 來源物件,需要通過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)

使用 Python 腳本取得 OBS 來源

obspython模組的obs_get_source_by_name函式,可用於取得指定名稱的 OBS 來源(物件)。

obs_get_source_by_name(name)

name 參數

name參數為 OBS 來源的名稱。

obspython模組的obs_get_source_by_uuid函式,可用於取得指定 UUID 的 OBS 來源(物件),UUID 會在來源被建立時自動分配,不同來源的 UUID 不會相同。

obs_get_source_by_uuid(uuid)

uuid 參數

uuid參數為 OBS 來源的 UUID。

如何使用 Python 腳本取得 OBS 私用來源?

你需要使用obs_get_source_by_uuid函式而非obs_get_source_by_name來取得一個 OBS 私用來源,因此,通過obs_source_get_uuid函式記錄所建立的私用來源的 UUID 是必要的。

使用 obs_data_release 函式釋放在 Python 腳本中取得的 OBS 來源物件

對於使用obs_get_source_by_nameobs_get_source_by_uuid函式取得的 OBS 來源物件,需要通過obs_source_release釋放參考,否則 OBS 可能會出現錯誤。

使用 Python 腳本取得和設定 OBS 來源的設定

正如之前提到的,OBS 來源設定是一個資料設定物件,該物件的作用類似於 Python 腳本的腳本設定物件,他是實作通過 Python 腳本操作 OBS 來源的關鍵要素之一,不同類型的 OBS 來源,其來源設定物件所包含的內容會有所差異。OBS 的obspython模組提供了以下關於來源設定的函式。

obs_source_get_settings函式,可用於取得 OBS 來源對應的來源設定物件,obs_source_get_private_settings函式,可用於取得 OBS 來源對應的私用來源設定物件,該物件應存放不希望對 OBS 使用者公開的設定。

obs_source_get_settings(source)
obs_source_get_private_settings(item)

source 參數

source參數為需要取得來源設定物件的 OBS 來源物件。

item 參數

item參數為需要取得私用來源設定物件的 OBS 來源物件。

obs_source_update函式,可用於更新 OBS 來源的來源設定物件,這將直接改變來源在 OBS 中的行為或表現,當然,對於某些類型的來源,改變帶來的效果可能不會立即顯現。

obs_source_reset_settings函式,可用於重設和更新 OBS 來源的來源設定物件,清除現有 OBS 來源設定的工作會首先進行,這意味著所有的設定都將恢復為預設。

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

source 參數

source參數為需要更新或重設更新來源設定物件的 OBS 來源物件。

settings 參數

settings參數為用於更新來源設定物件的 OBS 資料設定物件。

obs_get_source_defaults函式,可用於取得某類型來源的來源設定預設值,預設值將被包含在一個新的 OBS 來源設定物件(資料設定物件)中傳回。

obs_get_source_defaults(id)

id 參數

id參數為來源類型識別碼,obs_get_source_defaults函式將傳回該識別碼對應的來源類型的來源設定預設值。

使用 obs_data_release 函式釋放在 Python 腳本中取得的 OBS 來源設定物件

對於使用obs_source_get_settingsobs_source_get_private_settingsobs_get_source_defaults函式取得的 OBS 來源設定物件,需要通過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)
	# …

使用 Python 腳本取得 OBS 來源的原始寬度和高度

obspython模組的obs_source_get_widthobs_source_get_height函式,可用於取得 OBS 來源的原始寬度和高度,這並不會將轉場特效計算在內,因此obs_source_get_widthobs_source_get_height函式所傳回的並非來源對應場景項的實際顯示大小。

obs_source_get_width(source)
obs_source_get_height(source)

source 參數

source參數為需要取得原始寬度或高度的 OBS 來源物件。

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

使用 Python 腳本判斷 OBS 來源是否有效

OBS 來源的有效狀態用於指示其是否被用於算繪輸出,處於無效狀態的來源並未真正的參與算繪,比如,當 OBS 使用者將場景項隱藏時,其對應的來源可能將處於無效狀態。需要說明的是,是否處於有效狀態與來源是否可用無關。

obspython模組的obs_source_active函式,可用於判斷 OBS 來源是否處於有效狀態,傳回True表示來源處於有效狀態,傳回False表示來源處於無效狀態。

obs_source_active(source)

source 參數

source參數為需要判斷有效狀態的 OBS 來源物件。

使用 Python 腳本取得和設定 OBS 來源是否可用

obspython模組的obs_source_enabledobs_source_set_enabled函式,可用於取得和設定 OBS 來源是否可用(啟用或停用)。對於不可用的來源,不會在算繪中產生任何效果。需要說明的是,是否可用並不影響來源的有效狀態。

obs_source_enabled(source)
obs_source_set_enabled(source, enabled)

source 參數

source參數為需要取得或設定是否可用的 OBS 來源物件。

enabled 參數

enabled參數為True時,將啟用 OBS 來源,為False時,將停用 OBS 來源。

使用 Python 腳本取得和設定 OBS 來源是否可見

obspython模組的obs_source_showing函式與obs_source_active類似,可判斷 OBS 來源是否已經被算繪至最終輸出,只不過obs_source_showing的傳回結果,可以通過obs_source_inc_showingobs_source_dec_showing函式進行幹預。

obs_source_showing(source)

source 參數

source參數為需要判斷是否可見的 OBS 來源物件。

obspython模組的obs_source_inc_showingobs_source_dec_showing函式,可增加或減少 OBS 來源的可見計數,這將最終影響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 來源物件。

使用 Python 腳本取得和設定 OBS 來源的名稱

obspython模組的obs_source_get_nameobs_source_set_name函式,可用於取得或設定 OBS 來源的名稱,該名稱可顯示在 OBS 的相關視窗中。

obs_source_get_name(source)
obs_source_set_name(source, name)

source 參數

source參數為需要取得或設定名稱的 OBS 來源物件。

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)

使用 Python 腳本取得 OBS 來源的類型

obspython模組的obs_source_get_type函式,可用於取得 OBS 來源的類型,其傳回值可能對應以下某個obspython模組變數,OBS_SOURCE_TYPE_INPUT(輸入,一般 OBS 來源均為此類型),OBS_SOURCE_TYPE_FILTER(濾鏡),OBS_SOURCE_TYPE_TRANSITION(轉場特效),OBS_SOURCE_TYPE_SCENE(場景)。

obs_source_get_type(source)

source 參數

source參數為需要取得類型的 OBS 來源物件。

另外,obspython模組的obs_source_is_scene函式,可用於判斷 OBS 來源是否為場景,obspython模組的obs_source_is_group函式,可用於判斷 OBS 來源是否為群組。

obs_source_is_scene(source)
obs_source_is_group(source)

source 參數

source參數為需要判斷是否為場景或群組的 OBS 來源物件。

在下面的程式碼中,我們取得了來源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

使用 Python 腳本取得和設定 OBS 來源的 ID

obspython模組的obs_source_get_idobs_source_get_unversioned_id函式,可用於取得 OBS 來源的來源類型識別碼,二者的區別在於是否帶有版本資訊。

obs_source_get_id(source)
obs_source_get_unversioned_id(source)

source 參數

source參數為需要取得來源類型識別碼的 OBS 來源物件。

obspython模組的obs_source_get_uuid函式,可用於取得 OBS 來源的 UUID,每一個 OBS 來源都擁有一個唯一的 UUID。

obs_source_get_uuid(source)

source 參數

source參數為需要取得 UUID 的 OBS 來源物件。

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

使用 Python 腳本移除 OBS 來源

當你不再需要某個 OBS 來源時,可以使用obspython模組的obs_source_remove函式將其移除,這會使該來源以及該來源產生的場景項立即從 OBS 的相關視窗中消失,比如來源列

obs_source_remove(source)

source 參數

source參數為需要移除的 OBS 來源物件。

obspython模組的obs_source_removed函式,可用於判斷 OBS 來源是否已經被移除,傳回True表示已經被移除。

obs_source_removed(source)

source 參數

source參數為需要判斷是否被移除的 OBS 來源物件。

被 obs_source_remove 函式移除的 OBS 來源依然可能存在

這裏需要指出,被obs_source_remove函式移除的 OBS 來源,如果未釋放所有的參考,那麽他依然可以在 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

使用 Python 腳本新增和釋放對 OBS 來源的參考

如果一個 OBS 來源(物件)不存在任何參考,那麽該來源將被終結,毫無疑問,這增加了 OBS Python 腳本的編寫難度,沒有或過多的釋放參考,均可能導致 OBS 發生例外狀況。假設,你不小心對來源進行了過多的釋放,那麽一個錯誤視窗可能在所難免。obspython模組提供了以下與來源參考相關的函式。

obs_source_get_ref函式(OBS 27.2.0 之前為obs_source_addref函式),可用於為 OBS 來源物件新增參考。每當你額外呼叫一次obs_source_get_ref函式,就需要對等增加一次obs_source_release函式的呼叫。

OBS 27.2.0 之前,應使用函式obs_source_addref,而非obs_source_get_ref

obs_source_release函式,可用於為 OBS 來源物件釋放參考,他適用於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 來源物件。

obs_source_get_ref(source)
obs_source_release(source)

source 參數

source參數為需要新增或釋放參考的 OBS 來源物件。

使用 Python 腳本取得和設定 OBS 來源是否隱藏

如果希望新增一些對 OBS 使用者不公開的來源,那麽可將其設定為隱藏,隱藏來源產生的場景項不會出現在 OBS 的來源列中,也不會作為場景的一部分儲存,這意味著你總是需要在適當的時機建立並新增他們。

obspython模組的obs_source_is_hidden函式,可用於判斷 OBS 來源是否對 OBS 使用者隱藏,傳回False表示不隱藏,True表示隱藏。obspython模組的obs_source_set_hidden函式,可用於設定 OBS 來源是否對 OBS 使用者隱藏,該函式需要在場景項顯示在來源列之前呼叫,否則其效果不會是立即的。

obs_source_is_hidden(source)
obs_source_set_hidden(source, hidden)

source 參數

source參數為需要設定是否隱藏的 OBS 來源物件。

hidden 參數

hidden參數表示是否隱藏,False表示不隱藏,True表示隱藏。

使用 Python 腳本取得和設定 OBS 來源的輸出旗標

obspython模組的obs_source_get_output_flagsobs_get_source_output_flags函式,可用於取得 OBS 來源類型的輸出旗標,輸出旗標表示了該類型的來源所具備的功能,你可以將其視為一組列舉成員的組合(雖然並不是真正的列舉)。由於篇幅限製,這裏不再詳細解釋他們。

obs_source_get_output_flags(source)
obs_get_source_output_flags(id)

source 參數

source參數是一個 OBS 來源物件,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

使用 Python 腳本取得 OBS 來源類型的顯示名稱

obspython模組的obs_source_get_display_name函式,可用於取得指定 OBS 來源類型對應的顯示名稱,該函式的傳回值由目前 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