OBS Studio libobs 源码 API 参考:obs_source_info 定义、信号、过滤器与过渡的完整实现指南
本篇基于 OBS Studio 官方文档 reference-sources.rst(Source API Reference)并结合当前仓库源码,完整讲解 libobs 中 obs_source_t 源(Source)API 的实现契约:从 obs_source_info 定义结构的每个字段、output_flags 能力标志,到通用信号(Signals)、通用函数(Functions)、过滤器(Filters)与过渡(Transitions)的配套 API。读完后你将能够独立编写一个可注册、可渲染、可保存、可挂过滤器的 libobs 源,并理解 libobs 在注册与调用链上的强制校验逻辑。
一、什么是 Source:视频/音频的渲染与处理单元
Source 是 libobs 中用于在直播/录制中渲染视频和/或音频的核心对象。文档开篇即指出其典型用途:
- 捕获显示器/游戏/音频;
- 播放视频、显示图片、播放音频;
- 以源的形式实现音视频过滤器(Filters);
- 以源的形式实现场景过渡(Transitions)。
实现源的专用头文件是 libobs/obs-source.h,文档头部给出最小包含方式:
#include <obs.h>
libobs 定义了两类源句柄(见文档 .. type:: 条目):
| 类型 | 语义 |
|---|---|
obs_source_t |
带引用计数的视频/音频输入源(强引用) |
obs_weak_source_t |
源的弱引用,不阻止源被销毁,可用于跨生命周期持有指针 |
从 libobs/obs-source.h 的 enum obs_source_type 可以看到源共分为四种类型:
enum obs_source_type {
OBS_SOURCE_TYPE_INPUT, // 视频/音频输入
OBS_SOURCE_TYPE_FILTER, // 过滤器
OBS_SOURCE_TYPE_TRANSITION, // 过渡
OBS_SOURCE_TYPE_SCENE, // 场景(仅由 libobs 内部注册使用)
};
注意:OBS_SOURCE_TYPE_SCENE 在文档的 type 字段说明中未列出,它由 libobs 内部(libobs/obs-scene.c)注册,插件开发者通常只会使用前三种。
二、源定义结构 obs_source_info 全字段解析
obs_source_info 是向 libobs 描述"一种源"的完整契约。文档对每个成员逐一说明,下文按"必填/可选"重新组织,并与 libobs/obs-source.h 中的实际结构定义对照。
2.1 必填字段
| 成员 | 说明 |
|---|---|
const char *id |
源类型的唯一字符串标识(必填)。若设置了 version,libobs 会将其改写为 id_vN |
enum obs_source_type type |
源类型:OBS_SOURCE_TYPE_INPUT / OBS_SOURCE_TYPE_FILTER / OBS_SOURCE_TYPE_TRANSITION |
uint32_t output_flags |
源输出能力标志(必填),详见下一节。文档保留了作者注:"这个字段应改名为 capability_flags" |
const char *(*get_name)(void *type_data) |
返回源类型的本地化显示名称 |
void *(*create)(obs_data_t *settings, obs_source_t *source) |
创建源的实现数据,入参为初始设置和关联的源句柄 |
void (*destroy)(void *data) |
销毁实现数据。异步源在该函数返回后不得再调用 obs_source_output_video |
补充说明:
uint32_t version(可选):当某源实现发生重大修改、旧版本被弃用但需保留兼容时使用。注册时 libobs 会将注册 id 生成为<id>_vN(见 6.1 节源码分析),从而让新旧版本可以并存。仓库中plugins/image-source就同时注册了color_source_info_v1/v2/v3与slideshow_info/slideshow_info_mk2多版本源(plugins/image-source/image-source.c),正是这一机制的实例。get_width/get_height:返回视频宽/高。当源是同步视频输入(INPUT 类型且带OBS_SOURCE_VIDEO且不带OBS_SOURCE_ASYNC)时为必填。文档保留的作者注:这两个回调"本应合并成一个函数"。type_data与free_type_data:与源类型条目关联的私有数据。它不同于实现数据——实现数据由create返回、destroy释放;type_data用于区分复用同一套回调的多个源类型,free_type_data在 libobs 关闭时释放它。
2.2 设置与属性回调
| 回调 | 说明 |
|---|---|
void (*get_defaults)(obs_data_t *settings) |
设置默认值,需调用 obs_data_set_default* 系列函数。需要 type_data 时用 get_defaults2(type_data, settings);若两者都定义,先调 get_defaults 再调 get_defaults2(见头文件注释) |
obs_properties_t *(*get_properties)(void *data) / get_properties2(void *data, void *type_data) |
返回属性列表,前端据此自动生成设置界面。注意 data 可能为 NULL(例如对源类型而非源实例调用 obs_get_source_properties() 时),实现需妥善处理 |
void (*update)(void *data, obs_data_t *settings) |
设置更新时的回调。注意:视频源的 update 会被延迟到视频线程执行,以避免线程问题(见 5.2 节 obs_source_update) |
void (*save)(void *data, obs_data_t *settings) |
保存自定义数据时调用。独立成回调的原因是:有些源需要知道"正在保存",以便不总是提前刷新当前设置 |
void (*load)(void *data, obs_data_t *settings) |
从已保存数据加载自定义数据。该回调在所有源创建完成之后才被调用,因此可以安全地引用其他已加载的源 |
2.3 生命周期回调
| 回调 | 触发时机 |
|---|---|
activate / deactivate |
源在主视图(最终混流)中被激活/停用 |
show / hide |
源在任一显示(预览)或主视图中可见/不可见 |
video_tick(float seconds) |
每个视频帧调用一次,seconds 为距上一帧的经过时间 |
2.4 视频渲染与过滤回调
void (*video_render)(void *data, gs_effect_t *effect) 是渲染的核心入口,其语义随源类型不同而变化(文档原文分三种情况说明):
- 输入/过渡源:用于以图形子系统绘制源纹理;
- 过滤器源:包裹目标源的绘制调用(例如套用带自定义参数的 effect)。文档强烈建议配合
obs_source_process_filter_begin()与obs_source_process_filter_end()自动处理基于 effect 的过滤; - 若能力标志不含
OBS_SOURCE_CUSTOM_DRAW,源必须使用obs_source_draw()渲染源纹理;effect参数在新版中已不再使用,文档明确提示"直接调用obs_source_draw()"。
struct obs_source_frame *(*filter_video)(void *data, struct obs_source_frame *frame):仅用于异步视频过滤器,接收原始帧,可返回新帧,也可延迟到后续再绘制。
struct obs_audio_data *(*filter_audio)(void *data, struct obs_audio_data *audio):仅用于音频过滤器。可以直接修改传入数据并返回,也可以延迟处理;若返回新数据,该数据必须存活到下次 filter_audio 调用或过滤器被移除/销毁为止。
2.5 交互事件回调(依赖 OBS_SOURCE_INTERACTION)
| 回调 | 参数要点 |
|---|---|
mouse_click(void *data, const obs_mouse_event *event, int32_t type, bool mouse_up, uint32_t click_count) |
type 为按下的鼠标按键,mouse_up 为 true 表示松开,click_count 1 为单击 |
mouse_move(void *data, const obs_mouse_event *event, bool mouse_leave) |
mouse_leave 为 true 表示鼠标移出源 |
mouse_wheel(void *data, const obs_mouse_event *event, int x_delta, int y_delta) |
滚轮的横/纵位移增量 |
focus(void *data, bool focus) |
获得/失去焦点 |
key_click(void *data, const obs_key_event *event, bool key_up) |
按键按下/抬起 |
前端可通过第 5 节的 obs_source_send_* 系列函数向源发送这些事件。
2.6 组合源(COMPOSITE)回调
| 回调 | 说明 |
|---|---|
bool (*audio_render)(void *data, uint64_t *ts_out, struct obs_source_audio_mix *audio_output, uint32_t mixers, size_t channels, size_t sample_rate) |
渲染组合源的音频。凡带有 OBS_SOURCE_COMPOSITE 的源必须实现该回调以完成子源的自定义混音——这一点不仅文档要求,注册校验也强制检查(见 6.1 节) |
enum_active_sources(void *data, obs_source_enum_proc_t cb, void *param) |
枚举本源内部正在使用的所有活动子源。若源有渲染音视频的子源则必须实现 |
enum_all_sources(void *data, obs_source_enum_proc_t cb, void *param) |
枚举活动与非活动的全部子源;若未实现则回退到 enum_active_sources。适用于源可能持有非活动子源的场景(如场景中未显示的源) |
枚举回调签名为:
typedef void (*obs_source_enum_proc_t)(obs_source_t *parent,
obs_source_t *child, void *param);
2.7 过渡回调与媒体控制回调
transition_start/transition_stop:过渡开始/停止时调用(可选)。- 媒体控制一组(配合
OBS_SOURCE_CONTROLLABLE_MEDIA能力标志):media_play_pause(bool pause)、media_restart、media_stop、media_next、media_previous、media_get_duration、media_get_time、media_set_time(int64_t ms)、media_get_state。 missing_files:返回源当前缺失文件列表(obs_missing_files_t *),支撑前端的"缺失文件"修复对话框。
媒体状态枚举(文档与 libobs/obs-source.h 一致):
enum obs_media_state {
OBS_MEDIA_STATE_NONE, OBS_MEDIA_STATE_PLAYING, OBS_MEDIA_STATE_OPENING,
OBS_MEDIA_STATE_BUFFERING, OBS_MEDIA_STATE_PAUSED, OBS_MEDIA_STATE_STOPPED,
OBS_MEDIA_STATE_ENDED, OBS_MEDIA_STATE_ERROR,
};
2.8 图标与色彩空间
icon_type 用于前端为源展示图标,文档列出的取值包括:OBS_ICON_TYPE_UNKNOWN / IMAGE / COLOR / SLIDESHOW / AUDIO_INPUT / AUDIO_OUTPUT / DESKTOP_CAPTURE / WINDOW_CAPTURE / GAME_CAPTURE / CAMERA / TEXT / MEDIA / BROWSER / CUSTOM。头文件在此基础上还有 OBS_ICON_TYPE_PROCESS_AUDIO_OUTPUT。当 icon_type 设为 OBS_ICON_TYPE_CUSTOM 时,可实现 get_dark_icon / get_light_icon(入参 type_data)分别返回深色/浅色主题的图标文件路径。
video_get_color_space(void *data, size_t count, const enum gs_color_space *preferred_spaces) 返回源的色彩空间,未实现时按 GS_CS_SRGB 处理。文档特别指出一个 SDR 源在渲染到 HDR 时的优化:若活动色彩空间为 GS_CS_709_EXTENDED,可返回 GS_CS_709_EXTENDED 而非 GS_CS_SRGB 以避免冗余转换——该优化仅在像素着色器输出线性 709 时才成立,因此默认不执行。plugins/image-source 中的实现即返回纹理实际空间:
return image->texture ? image->space : GS_CS_SRGB;
(plugins/image-source/image-source.c)
三、output_flags 能力标志位全表
output_flags 是位或组合,直接决定源的数据通路形态。以下按 libobs/obs-source.h 中的实际位定义列出:
| 标志 | 位 | 含义与约束 |
|---|---|---|
OBS_SOURCE_VIDEO |
1 << 0 |
源有视频。除非同时指定 SOURCE_ASYNC_VIDEO,否则必须实现 video_render |
OBS_SOURCE_AUDIO |
1 << 1 |
源有音频。用 obs_source_output_audio() 传入原始数据,自动转换与上传;若配合 OBS_SOURCE_ASYNC_VIDEO,音频按双方时间戳与视频自动同步 |
OBS_SOURCE_ASYNC |
1 << 2 |
视频为异步(文档建议使用 OBS_SOURCE_ASYNC_VIDEO,它会自动带上 OBS_SOURCE_VIDEO) |
OBS_SOURCE_ASYNC_VIDEO |
OBS_SOURCE_ASYNC | OBS_SOURCE_VIDEO |
源经 RAM 传原始视频数据,用 obs_source_output_video() 传入,按时间戳定时绘制;此时可省略 video_render |
OBS_SOURCE_CUSTOM_DRAW |
1 << 3 |
源使用自定义图形调用而非单纹理渲染。必须在不使用 obs_source_draw() 单纹理渲染时设置。它是重要提示:会关闭"过滤链第一个 effect 直接渲染源"的优化——有自定义绘制时源必须先渲染到纹理再交给第一个过滤器。文档保留了作者对此设计的自嘲注记 |
OBS_SOURCE_INTERACTION |
1 << 5 |
源可被用户交互。设置后源将接收 2.5 节所列交互事件(前提是实现了对应回调) |
OBS_SOURCE_COMPOSITE |
1 << 6 |
源组合子源(场景与过渡即此类)。渲染子源的源必须实现 audio_render 做自定义混音;过渡注册时 libobs 会强制置上此标志 |
OBS_SOURCE_DO_NOT_DUPLICATE |
1 << 7 |
禁止完整复制。obs_source_duplicate() / obs_scene_duplicate() 对带此标志的源只持有引用而不复制。典型适用者:视频设备、浏览器、音视频采集源(重复实例化会出问题或造成资源/性能问题) |
OBS_SOURCE_DEPRECATED |
1 << 8 |
源已弃用,不应再使用 |
OBS_SOURCE_DO_NOT_SELF_MONITOR |
1 << 9 |
当监听设备与被采集设备相同时,禁止对该源音频做监听,防止反馈回环。主要用于桌面音频采集源 |
OBS_SOURCE_CAP_DISABLED |
1 << 10 |
该源类型被禁用,不应出现在"可添加源"列表中 |
OBS_SOURCE_CAP_OBSOLETE |
等价于 OBS_SOURCE_CAP_DISABLED |
源已更新(默认值/属性变化)但为避免破坏旧配置而保留,语义为"我想改源默认值但不想弄坏用户配置" |
OBS_SOURCE_MONITOR_BY_DEFAULT |
1 << 11 |
源应默认开启监听,具体由前端在该标志置位时设置 |
OBS_SOURCE_SUBMIX |
1 << 12 |
头文件中标注"内部用于音频子混音",文档未列入公开标志 |
OBS_SOURCE_CONTROLLABLE_MEDIA |
1 << 13 |
源的媒体内容可被媒体控制条控制 |
OBS_SOURCE_CEA_708 |
1 << 14 |
源提供 CEA-708 字幕数据 |
OBS_SOURCE_SRGB |
1 << 15 |
源理解 sRGB 渲染 |
OBS_SOURCE_CAP_DONT_SHOW_PROPERTIES |
1 << 16 |
创建源时不弹属性对话框(优先使用默认值) |
OBS_SOURCE_REQUIRES_CANVAS |
1 << 17 |
源依赖 canvas 才能工作 |
从源码结构看,libobs 在注册阶段会对部分组合做强制校验(详见第六节):例如音频-only 过滤器会被自动打上 OBS_SOURCE_ASYNC,过渡会被强制加上 OBS_SOURCE_COMPOSITE | OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW。
四、通用信号(Common Source Signals)
以下信号对每种源都可用,信号参数以 ptr(指针)、string、bool、int、float 标注。获取信号处理器的 API 是 obs_source_get_signal_handler()(其生命周期由 libobs 管理,不应手动释放)。
| 信号 | 参数 | 触发时机 |
|---|---|---|
destroy |
ptr source |
源即将被销毁时。不要在该信号中增加引用 |
remove |
ptr source |
调用 obs_source_remove() 时 |
update |
ptr source |
源设置被更新时(29.0.0 起) |
save / load |
ptr source |
源被保存/加载时 |
activate / deactivate |
ptr source |
在主视图激活/停用 |
show / hide |
ptr source |
在任一显示或主视图可见/不可见 |
mute |
ptr source, bool muted |
静音/取消静音 |
push_to_mute_changed |
ptr source, bool enabled |
按键静音开关变化 |
push_to_mute_delay |
ptr source, int delay |
按键静音延迟变化 |
push_to_talk_changed |
ptr source, bool enabled |
按键说话开关变化 |
push_to_talk_delay |
ptr source, int delay |
按键说话延迟变化 |
enable |
ptr source, bool enabled |
源被禁用/启用 |
rename |
ptr source, string new_name, string prev_name |
源被重命名 |
volume |
ptr source, in out float volume |
音量变化 |
update_properties |
ptr source |
通知属性视图等使用者:源的可呈现属性已变化,应通过 obs_source_properties 重新查询。注意它不代表用户设置(settings)变化,后者用 update 信号 |
update_flags |
ptr source, int flags |
源标志变化 |
audio_sync |
ptr source, int out int offset |
音频同步偏移变化 |
audio_balance |
ptr source, in out float balance |
音频平衡变化 |
audio_mixers |
ptr source, in out int mixers |
音频混音器变化 |
audio_activate / audio_deactivate |
ptr source |
源音频激活/失活 |
filter_add / filter_remove |
ptr source, ptr filter |
过滤器被添加/移除(30.0 起) |
reorder_filters |
ptr source |
过滤器被重新排序 |
transition_start |
ptr source |
过渡开始 |
transition_video_stop |
ptr source |
过渡的视频部分停止 |
transition_stop |
ptr source |
过渡停止 |
media_started / media_ended |
ptr source |
媒体开始/结束 |
media_pause / media_play |
ptr source |
媒体暂停/播放 |
media_restart / media_stopped |
ptr source |
媒体重播/停止 |
media_next / media_previous |
ptr source |
媒体源切换到下一/上一媒体 |
4.1 源专属信号(Source-specific Signals)
不同源类型可定义额外的私有信号:
| 信号 | 参数 | 定义于 |
|---|---|---|
slide_changed |
int index, string path |
Image Slide Show——当前显示图片变化时 |
hooked |
ptr source, string title, string class, string executable |
Window Capture (Windows)、Game Capture (Windows)、Application Audio Output Capture (Windows)——成功捕获已存在的窗口时 |
hooked |
ptr source, string name, string class |
Window Capture (Xcomposite)——同上,Linux X11 版本参数不同 |
unhooked |
ptr source |
上述四个捕获源——停止捕获时 |
4.2 源专属过程(Source-specific Procedures)
过程(Procedures)是带输入/输出参数的调用接口:
| 过程 | 参数 | 定义于 |
|---|---|---|
current_index |
out int current_index |
Image Slide Show——当前显示图片的索引 |
total_files |
out int total_files |
Image Slide Show——幻灯片总图片数 |
get_hooked |
out bool hooked, out string title, out string class, out string executable |
Windows 版 Window/Game Capture 与应用音频捕获——当前是否正在捕获某窗口及是哪个 |
get_hooked |
out bool hooked, out string name, out string class |
Window Capture (Xcomposite) |
get_metadata |
in string tag_id, out string tag_data |
VLC Video Source——按标签 id 取元数据 |
restart |
无 | Media Source——重播媒体 |
get_duration |
out int duration |
Media Source——媒体总时长(纳秒) |
get_nb_frames |
out int num_frames |
Media Source——媒体总帧数 |
activate |
in bool active |
Video Capture Device Source (Windows)——激活/停用设备 |
五、通用源函数(General Source Functions)
5.1 注册与类型查询
void obs_register_source(struct obs_source_info *info):注册一种源类型,通常在 obs_module_load() 或程序初始化阶段调用。在头文件中它实际是宏:
#define obs_register_source(info) \
obs_register_source_s(info, sizeof(struct obs_source_info))
(libobs/obs-source.h)传入结构体大小使 libobs 可以做前向兼容的成员裁剪,详见 6.1 节。
const char *obs_source_get_display_name(const char *id):调用get_name回调取本地化名称。uint32_t obs_source_get_output_flags(const obs_source_t *source)/uint32_t obs_get_source_output_flags(const char *id):取实例或类型的能力标志。obs_data_t *obs_get_source_defaults(const char *id):调用get_defaults取默认设置。obs_properties_t *obs_source_properties(const obs_source_t *source)/obs_properties_t *obs_get_source_properties(const char *id):取属性列表(用obs_properties_destroy()释放)。bool obs_source_configurable(const obs_source_t *source)/bool obs_is_source_configurable(const char *id):源是否有可配置属性。enum obs_source_type obs_source_get_type(...)、obs_source_is_scene()、obs_source_is_group():类型判断。const char *obs_source_get_id(...):类型标识;若源带版本,返回形如id_vN的串。obs_source_get_unversioned_id()返回未加版本的 id。enum obs_icon_type obs_source_get_icon_type(const char *id)、obs_source_get_dark_icon(id)、obs_source_get_light_icon(id):图标查询。obs_canvas_t *obs_source_get_canvas(const obs_source_t *source):获取源所属 canvas(引用已递增)。
5.2 创建、引用计数与销毁
| 函数 | 说明 |
|---|---|
obs_source_t *obs_source_create(const char *id, const char *name, obs_data_t *settings, obs_data_t *hotkey_data) |
创建指定类型的源。name 若非唯一会被自动改名为唯一名;settings/hotkey_data 可为 NULL。失败返回 NULL |
obs_source_t *obs_source_create_private(const char *id, const char *name, obs_data_t *settings) |
创建"私有源":不被 obs_enum_sources() 枚举、不被 obs_save_sources() 保存。私有源名可以重复,甚至可为 NULL。文档保留了作者注:该函数的存在是设计缺陷所致——前端应控制源的保存/加载 |
obs_source_t *obs_source_get_ref(obs_source_t *source) |
若源仍有效则返回加一后的引用,否则返回 NULL |
void obs_source_release(obs_source_t *source) |
释放一个引用;最后一个引用释放时源被销毁 |
obs_weak_source_t *obs_source_get_weak_source(obs_source_t *) / obs_source_t *obs_weak_source_get_source(obs_weak_source_t *) |
强/弱引用互转;源已销毁时后者返回 NULL |
void obs_weak_source_addref(obs_weak_source_t *) / void obs_weak_source_release(obs_weak_source_t *) |
增减弱引用 |
void obs_source_remove(obs_source_t *source) |
通知所有引用持有者(经 obs_source_removed() 检查)该源应被释放 |
bool obs_source_removed(const obs_source_t *source) |
true 表示源应被释放 |
bool obs_source_is_hidden(...) / void obs_source_set_hidden(..., bool hidden) |
设置"对用户隐藏"属性(源仍存活但不被引用)。文档标注 33.0 起弃用 |
void obs_source_update(obs_source_t *source, obs_data_t *settings):更新设置并触发 update 回调。文档特别强调线程行为:视频源的 update 回调不会立即执行,而是被延迟到视频线程,以防线程问题。obs_source_reset_settings() 与之相同,但会先清空现有设置。
5.3 设置、名称与查询
obs_data_t *obs_source_get_settings(const obs_source_t *source):返回源设置(引用计数 +1,用完需obs_data_release())。obs_data_t *obs_source_get_private_settings(obs_source_t *item):获取私有前端设置数据,自动保存/加载,返回加引用的对象。const char *obs_source_get_name(const obs_source_t *source)/void obs_source_set_name(obs_source_t *, const char *name):非私有源重命名时若重名会自动改为唯一名。const char *obs_source_get_uuid(const obs_source_t *source):返回源 UUID(29.1 起)。uint32_t obs_source_get_width/height(obs_source_t *):调用对应回调取宽高。enum gs_color_space obs_source_get_color_space(obs_source_t *, size_t count, const enum gs_color_space *preferred_spaces):取源色彩空间,未实现时按GS_CS_SRGB;禁用的过滤器会被跳过,异步视频源可自行决定色彩空间。bool obs_source_get_texcoords_centered(obs_source_t *source):提示源是否会做纹素混合。signal_handler_t *obs_source_get_signal_handler(...)/proc_handler_t *obs_source_get_proc_handler(...):取信号/过程处理器,均不应手动释放。
5.4 音频控制
| 函数组 | 说明 |
|---|---|
obs_source_set_volume / obs_source_get_volume |
有音频输出的源的用户音量 |
obs_source_set_muted / obs_source_muted |
静音开关 |
obs_source_get_speaker_layout |
当前扬声器布局 |
obs_source_set_balance_value / obs_source_get_balance_value |
音频平衡 |
obs_source_set_sync_offset / obs_source_get_sync_offset |
音频同步偏移(纳秒) |
obs_source_set_audio_mixers / obs_source_get_audio_mixers |
源输出到的混音轨位图。例如同时输出到混音器 1 和 3:(1<<0) | (1<<2),即 0x5 |
obs_source_set_monitoring_type / obs_source_get_monitoring_type |
桌面音频监听类型:OBS_MONITORING_TYPE_NONE(不监听)/ OBS_MONITORING_TYPE_MONITOR_ONLY(只送监听设备、不进输出)/ OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT(监听并输出)。33.0 起弃用,改用 obs_source_set_monitoring_enabled / obs_source_get_monitoring_enabled(33.0 新增) |
obs_source_set_audio_active / obs_source_audio_active |
音频激活状态(控制是否出现在混音器中) |
obs_source_enable_push_to_mute / obs_source_push_to_mute_enabled;obs_source_set_push_to_mute_delay / obs_source_get_push_to_mute_delay |
按键静音及其延迟 |
obs_source_enable_push_to_talk / obs_source_push_to_talk_enabled;obs_source_set_push_to_talk_delay / obs_source_get_push_to_talk_delay |
按键说话及其延迟 |
5.5 活动状态、子源枚举与过滤器管理
bool obs_source_active(const obs_source_t *):true 表示源出现在最终混流中。bool obs_source_showing(const obs_source_t *):true 表示源在任意显示上下文或最终输出中可见。void obs_source_inc_showing(...)/obs_source_dec_showing(...):增减"showing"状态,通常在手动把源画到某显示上时使用。bool obs_source_enabled(...)/void obs_source_set_enabled(..., bool enabled):源的启用状态。void obs_source_set_flags(obs_source_t *, uint32_t flags)/uint32_t obs_source_get_flags(...):文档列出的标志为OBS_SOURCE_FLAG_FORCE_MONO(强制音频单声道)。obs_source_enum_active_sources/obs_source_enum_active_tree:枚举源使用的活动子源/整棵子源树,回调即obs_source_enum_proc_t。
过滤器(挂在源上的 OBS_SOURCE_TYPE_FILTER)管理 API:
| 函数 | 说明 |
|---|---|
obs_source_enum_filters(source, callback, param) |
枚举源上的活动过滤器 |
obs_source_get_filter_by_name(source, name) |
按名取过滤器,未找到返回 NULL;返回值的引用已递增 |
obs_source_copy_filters(dst, src) |
复制全部过滤器;重名时新过滤器自动取唯一名 |
obs_source_copy_single_filter(dst, filter) |
复制单个过滤器,重名规则同上 |
size_t obs_source_filter_count(const obs_source_t *) |
过滤器数量 |
obs_data_array_t *obs_source_backup_filters(source) / obs_source_restore_filters(source, array) |
备份/恢复过滤器列表及顺序 |
5.6 采集回调、隔行扫描与交互注入
void obs_source_add_audio_capture_callback(source, obs_source_audio_capture_t cb, void *param)/obs_source_remove_audio_capture_callback(...):注册/移除音频采集回调,可在数据进入时拿到源的原始音频:
typedef void (*obs_source_audio_capture_t)(void *param, obs_source_t *source,
const struct audio_data *audio_data, bool muted);
obs_source_set_deinterlace_mode/obs_source_get_deinterlace_mode:隔行扫描模式,取值为OBS_DEINTERLACE_MODE_DISABLE / DISCARD / RETRO / BLEND / BLEND_2X / LINEAR / LINEAR_2X / YADIF / YADIF_2X。obs_source_set_deinterlace_field_order/obs_source_get_deinterlace_field_order:场序OBS_DEINTERLACE_FIELD_ORDER_TOP(自顶部开始)/OBS_DEINTERLACE_FIELD_ORDER_BOTTOM。- 交互注入:
obs_source_send_mouse_click(source, event, type, mouse_up, click_count)、obs_source_send_mouse_move(source, event, mouse_leave)、obs_source_send_mouse_wheel(source, event, x_delta, y_delta)、obs_source_send_focus(source, focus)、obs_source_send_key_click(source, event, key_up)——前端通过这些函数把用户事件送进OBS_SOURCE_INTERACTION源。 void obs_source_update_properties(obs_source_t *source):通知已打开的属性视图该源的可呈现属性已变化、应刷新(触发update_properties信号)。
六、源实现侧函数(Functions used by sources)
以下函数供源的实现代码在回调内部调用。
6.1 同步绘制与异步数据输出
void obs_source_draw_set_color_matrix(const struct matrix4 *color_matrix, const struct vec3 *color_range_min, const struct vec3 *color_range_max):绘制前设置颜色矩阵信息,分别写入 effect 变量 color_matrix / color_range_min / color_range_max;min/max 传 NULL 时默认 {0,0,0} 与 {1,1,1}。
void obs_source_draw(gs_texture_t *image, int x, int y, uint32_t cx, uint32_t cy, bool flip):同步视频源的精灵绘制辅助函数。image 赋给当前 effect 的 image 变量;cx/cy 为 0 时使用纹理自身宽高;flip 控制垂直翻转。
void obs_source_output_video(obs_source_t *source, const struct obs_source_frame *frame):输出异步视频帧,传 NULL 表示停用纹理。帧结构为:
enum video_format {
VIDEO_FORMAT_NONE,
/* planar 4:2:0 */ VIDEO_FORMAT_I420, VIDEO_FORMAT_NV12,
/* packed 4:2:2 */ VIDEO_FORMAT_YVYU, VIDEO_FORMAT_YUY2, VIDEO_FORMAT_UYVY,
/* packed uncompressed */ VIDEO_FORMAT_RGBA, VIDEO_FORMAT_BGRA,
VIDEO_FORMAT_BGRX, VIDEO_FORMAT_Y800,
/* planar 4:4:4 */ VIDEO_FORMAT_I444,
VIDEO_FORMAT_BGR3,
/* planar 4:2:2 */ VIDEO_FORMAT_I422,
/* planar 4:2:0/4:2:2/4:4:4 with alpha */
VIDEO_FORMAT_I40A, VIDEO_FORMAT_I42A, VIDEO_FORMAT_YUVA, VIDEO_FORMAT_AYUV,
/* 10-bit planar */ VIDEO_FORMAT_I010, VIDEO_FORMAT_P010, VIDEO_FORMAT_I210,
/* 12-bit planar */ VIDEO_FORMAT_I412, VIDEO_FORMAT_YA2L,
/* 16-bit planar */ VIDEO_FORMAT_P216, VIDEO_FORMAT_P416,
/* packed 4:2:2 10-bit / packed 10-bit */
VIDEO_FORMAT_V210, VIDEO_FORMAT_R10L,
};
struct obs_source_frame {
uint8_t *data[MAX_AV_PLANES];
uint32_t linesize[MAX_AV_PLANES];
uint32_t width;
uint32_t height;
uint64_t timestamp;
enum video_format format;
float color_matrix[16];
bool full_range;
uint16_t max_luminance;
float color_range_min[3];
float color_range_max[3];
bool flip;
uint8_t flags;
uint8_t trc; /* enum video_trc */
};
其余辅助:
void obs_source_set_async_rotation(obs_source_t *source, long rotation):为异步视频源设置旋转(0、90、180、-90、270),自动应用到源。void obs_source_preload_video(source, const struct obs_source_frame *frame):预载一帧视频,确保播放一开始就有帧可放。void obs_source_show_preloaded_video(source):显示已预载的帧。void obs_source_output_audio(source, const struct obs_source_audio *audio):输出音频数据。bool obs_source_add_active_child(obs_source_t *parent, obs_source_t *child):父源在子源被添加且处于活动状态时必须调用,确保父源激活时子源被正确激活;返回 false 表示会形成递归。void obs_source_remove_active_child(parent, child):子源被移除或不再活动时调用,确保父源失活时子源被正确失活。
6.2 注册阶段的源码级校验
obs_register_source_s 的实现(libobs/obs-module.c)揭示了注册时 libobs 实际执行的校验与改写规则,插件开发时务必对照:
- 类型分流:INPUT/FILTER/TRANSITION 分别放入
obs->input_types、filter_types、transition_types;OBS_SOURCE_TYPE_SCENE允许存在但不入表(场景类型由 libobs 内部注册);其他类型直接报错。 - id 查重:同 id+version 已存在时告警
Source '%s' already exists! Duplicate library?并拒绝注册。 - 大小校验:传入结构体大小超过 libobs 当前支持的
sizeof(struct obs_source_info)时拒绝(这为"新插件编译于新 libobs、运行于旧 libobs"提供了向前兼容裁剪机制);注册失败时HANDLE_ERROR会调用free_type_data清理数据。 - 自动改写:
- 无
OBS_SOURCE_VIDEO的过滤器被自动打上OBS_SOURCE_ASYNC("把纯音频过滤器一概标记为异步"); - 过渡源:
get_width/get_height被忽略(仅告警),并强制加上OBS_SOURCE_COMPOSITE | OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW; - 组合源同时带
OBS_SOURCE_AUDIO或OBS_SOURCE_ASYNC时注册失败——组合源既不能自己产音频也不能是异步源。
- 无
- 必填回调强制检查:
get_name必须非空;INPUT 类型且为同步视频源时get_width/get_height必填;带OBS_SOURCE_COMPOSITE时audio_render必填。 - 版本化 id:
version非 0 时 id 被改写为"%s_v%d"(如color_source_v2),unversioned_id保留原 id——这解释了obs_source_get_id()为何可能带_vN后缀,以及 image-source 插件能同时注册 v1/v2/v3 的机制。
一个典型的注册写法见 plugins/image-source/image-source.c:结构体以 C designated initializer 方式只填所需回调,然后在 obs_module_load 中注册:
static struct obs_source_info image_source_info = {
.id = "image_source",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB,
.get_name = image_source_get_name,
.create = image_source_create,
.destroy = image_source_destroy,
.update = image_source_update,
.get_defaults = image_source_defaults,
.show = image_source_show,
.hide = image_source_hide,
.get_width = image_source_getwidth,
.get_height = image_source_getheight,
.video_render = image_source_render,
.video_tick = image_source_tick,
.missing_files = image_source_missingfiles,
.get_properties = image_source_properties,
.icon_type = OBS_ICON_TYPE_IMAGE,
.activate = image_source_activate,
.video_get_color_space = image_source_get_color_space,
};
注意它作为同步视频输入完整提供了 get_width/get_height/video_render,与 6.2 节第 5 条的注册校验规则一一对应;missing_files 回调(image-source.c)则展示了如何配合 obs_missing_files_create/obs_missing_file_create 上报缺失文件。
七、过滤器(Filters)
7.1 过滤器视角的查询函数
| 函数 | 说明 |
|---|---|
obs_source_t *obs_filter_get_parent(const obs_source_t *filter) |
返回过滤器作用的父源(不增加引用)。仅在 video_render、filter_audio、filter_video、filter_add、filter_remove 回调内保证有效 |
obs_source_t *obs_filter_get_target(const obs_source_t *filter) |
返回过滤链上的下一个目标源(不增加引用)。仅在 video_render、filter_audio、filter_video、filter_remove 回调内保证有效 |
void obs_source_default_render(obs_source_t *source) |
过滤器可借此绕过一切过滤处理直接渲染非异步父源 |
7.2 前端挂载与排序
void obs_source_filter_add(obs_source_t *source, obs_source_t *filter)/obs_source_filter_remove(source, filter):向源添加/移除过滤器。void obs_source_filter_set_order(source, filter, enum obs_order_movement movement):移动方向为OBS_ORDER_MOVE_UP / OBS_ORDER_MOVE_DOWN / OBS_ORDER_MOVE_TOP / OBS_ORDER_MOVE_BOTTOM。void obs_source_filter_set_index(source, filter, size_t index)(30.0 起):移到指定下标。int obs_source_filter_get_index(source, filter)(30.0 起):返回下标,未找到返回 -1。
7.3 基于 Effect 的过滤器处理模板
对于"通用 effect 过滤器",libobs 提供 begin/end 配对模板,这是文档明确推荐的写法:
// video_render 回调内的标准流程
if (!obs_source_process_filter_begin(filter, GS_RGBA, OBS_ALLOW_DIRECT_RENDER))
return; // 返回 false 表示过滤器被旁路(bypassed),无需再画
// —— 中间:设置你的 effect 参数 ——
obs_source_process_filter_end(filter, effect, width, height);
| 函数 | 说明 |
|---|---|
bool obs_source_process_filter_begin(filter, enum gs_color_format format, enum obs_allow_direct_render allow_direct) |
通用 RGB 过滤器处理器:处理过滤链、必要时把结果渲染到纹理,然后供过滤器绘制。返回 false 表示过滤器因某种原因被旁路 |
bool obs_source_process_filter_begin_with_color_space(filter, format, space, allow_direct) |
同上,但额外指定活动色彩空间 |
void obs_source_process_filter_end(filter, gs_effect_t *effect, uint32_t width, uint32_t height) |
用 effect 的 "Draw" technique 完成绘制 |
void obs_source_process_filter_tech_end(filter, effect, width, height, const char *tech_name) |
用 effect 中指定名称的 technique 完成绘制 |
void obs_source_skip_video_filter(obs_source_t *filter) |
当过滤器无效、无法渲染时跳过之 |
八、过渡(Transitions)
8.1 过渡控制 API
| 函数 | 说明 |
|---|---|
obs_source_t *obs_transition_get_source(transition, enum obs_transition_target target) |
取过渡的两个端点源(引用已递增):OBS_TRANSITION_SOURCE_A 为过渡来源(未过渡时即当前源),OBS_TRANSITION_SOURCE_B 为过渡目标 |
void obs_transition_clear(transition) |
清空过渡 |
obs_source_t *obs_transition_get_active_source(transition) |
取当前活动源(引用递增) |
bool obs_transition_start(transition, enum obs_transition_mode mode, uint32_t duration_ms, obs_source_t *dest) |
启动过渡。mode 目前仅支持 OBS_TRANSITION_MODE_AUTO;若通过 obs_transition_enable_fixed 设置了固定时长,duration_ms 无效 |
bool obs_transition_is_active(transition) |
是否正在过渡中 |
obs_transition_set_size / obs_transition_get_size |
设置/获取过渡尺寸 |
obs_transition_set_scale_type / obs_transition_get_scale_type |
过渡内源的缩放方式:OBS_TRANSITION_SCALE_MAX_ONLY(按宽高比但最大不超过源尺寸)/ OBS_TRANSITION_SCALE_ASPECT(始终缩放、保持宽高比)/ OBS_TRANSITION_SCALE_STRETCH(拉伸填充) |
obs_transition_set_alignment / obs_transition_get_alignment |
两个源在过渡中的对齐方式,位或组合:OBS_ALIGN_CENTER / OBS_ALIGN_LEFT / OBS_ALIGN_RIGHT / OBS_ALIGN_TOP / OBS_ALIGN_BOTTOM |
8.2 过渡实现侧函数
void obs_transition_enable_fixed(transition, bool enable, uint32_t duration_ms)/bool obs_transition_fixed(transition):是否使用固定时长。适用于 stinger 类过渡;置位后obs_transition_start()的duration_ms参数失效。float obs_transition_get_time(transition):当前过渡进度值(0.0f~1.0f),供过渡实现每帧读取。obs_transition_video_render/obs_transition_video_render2:过渡渲染的核心辅助函数。它会把源 A 与源 B 各自渲染为独立纹理,然后通过回调交给你的像素着色器自由混合:
typedef void (*obs_transition_video_render_callback_t)(void *data,
gs_texture_t *a, gs_texture_t *b, float t,
uint32_t cx, uint32_t cy);
回调参数:a/b 为 A/B 源自动渲染出的纹理,t 为进度(0.0f~1.0f),cx/cy 为过渡当前尺寸,data 为实现的私有数据。render2 版本额外接受 placeholder_texture,允许调用方提供替代默认全透明纹理的占位纹理(甚至传 NULL)。
enum gs_color_space obs_transition_video_get_color_space(transition):计算能覆盖两个子源的色彩空间,较宽的空间胜出。bool obs_transition_audio_render(transition, uint64_t *ts_out, struct obs_source_audio_mix *audio, uint32_t mixers, size_t channels, size_t sample_rate, obs_transition_audio_mix_callback_t mix_a, obs_transition_audio_mix_callback_t mix_b):音频过渡辅助函数,通常在obs_source_info.audio_render回调内以其参数调用;两个 mix 回调分别给出 A/B 源在时间t处的淡入淡出系数:
typedef float (*obs_transition_audio_mix_callback_t)(void *data, float t);
void obs_transition_swap_begin(tr_dest, tr_source)/void obs_transition_swap_end(tr_dest, tr_source):无缝切换两个过渡——先调 swap_begin,替换输出端绑定的过渡(如调用obs_set_output_source指向新过渡),再调 swap_end,保证切换过程不影响输出。
九、实现要点清单(结合文档与源码的自检规则)
综合本文档与 libobs/obs-module.c 的注册校验,实现一个新源时可按以下清单自检:
- 注册时机:在
obs_module_load()中调用obs_register_source;id 必须全局唯一,重复注册会被直接拒绝(libobs/obs-module.c)。 - 必填项:
get_name永远必填;同步视频 INPUT 源必填get_width/get_height(并实现video_render,用obs_source_draw()画纹理);OBS_SOURCE_COMPOSITE源必填audio_render与enum_active_sources。 - 异步源:声明
OBS_SOURCE_ASYNC_VIDEO,用obs_source_output_video()按时间戳提交帧;destroy返回后不得再输出帧;纯音频过滤器会自动被标记为异步。 - 自定义绘制:不用单纹理
obs_source_draw()时务必声明OBS_SOURCE_CUSTOM_DRAW,这会关闭"首过滤器直渲源"的优化。 - 可复制性:采集设备、浏览器等不可多开实例的源声明
OBS_SOURCE_DO_NOT_DUPLICATE。 - 生命周期与信号对称:
activate/deactivate与show/hide语义不同(主视图 vs 任一显示),资源申请/释放要挂在正确的钩子上;destroy信号中禁止加引用。 - 保存/加载:需要持久化状态时用
save/load回调操作obs_data_t,加载回调在所有源创建完之后执行,可安全引用兄弟源。 - 多版本演进:修改默认值或属性语义时递增
version,以id_vN注册新类型,避免破坏旧配置——OBS_SOURCE_CAP_OBSOLETE标志用于把旧类型从"可添加源"列表中隐藏。 - 线程:
obs_source_update()对视频源会延迟到视频线程触发update回调,源内部状态更新应假定可能发生在视频线程上下文。
文档原文位于 docs/sphinx/reference-sources.rst,其尾部指向的实现头文件为 libobs/obs-source.h(文档以 libobs/obs-source.h 作为实现源的专用头文件);注册逻辑参考 libobs/obs-module.c,真实源实现示例可进一步阅读 plugins/image-source/image-source.c、过滤器示例可参考 plugins/obs-filters、过渡示例可参考 plugins/obs-transitions。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00