如何使用 Python 腳本操作 OBS 來源?OBS 來源物件介紹
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_create
和obs_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_create
或obs_source_create_private
函式建立的 OBS 來源物件,需要通過obs_source_release
釋放參考,否則 OBS 可能會出現錯誤。
我們嘗試在按鈕的回呼函式test
中,建立一個私用文字(GDI+)來源,並通過 OBS 資料設定物件對來源進行設定,最後將文字(GDI+)作為場景項新增到場景Scene
中,假設Scene
存在。這裏涉及到與場景相關的函式,但由於篇幅限製,不再進行說明。
# 匯入模組 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 視窗中。
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_name
,obs_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_settings
,obs_source_get_private_settings
,obs_get_source_defaults
函式取得的 OBS 來源設定物件,需要通過obs_data_release
釋放參考,否則 OBS 可能會出現錯誤。
調整之前的程式碼,我們通過obs_source_get_settings
和obs_source_update
函式,更新了Welcome
來源的文字。
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_width
和obs_source_get_height
函式,可用於取得 OBS 來源的原始寬度和高度,這並不會將轉場特效計算在內,因此obs_source_get_width
和obs_source_get_height
函式所傳回的並非來源對應場景項的實際顯示大小。
obs_source_get_width(source)
obs_source_get_height(source)
- source 參數
source
參數為需要取得原始寬度或高度的 OBS 來源物件。
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_enabled
和obs_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_showing
和obs_source_dec_showing
函式進行幹預。
obs_source_showing(source)
- source 參數
source
參數為需要判斷是否可見的 OBS 來源物件。
obspython
模組的obs_source_inc_showing
和obs_source_dec_showing
函式,可增加或減少 OBS 來源的可見計數,這將最終影響obs_source_showing
的傳回結果。需要說明的是,雖然可通過obs_source_inc_showing
和obs_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_name
和obs_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
。
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
。
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_id
和obs_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 來源物件。
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
包含該來源。
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_create
,obs_source_create_private
,obs_source_duplicate
,obs_get_source_by_name
,obs_get_source_by_uuid
,obs_source_get_filter_by_name
,obs_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_flags
和obs_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
的輸出旗標,並判斷其是否具有視訊和音訊功能。
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 語言為中文的話。