OBS Studio 场景集编排实战:基于 CLI-Anything Agent Harness 用 JSON 场景集驱动直播与录制配置
【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything
导读
OBS Studio(Open Broadcaster Software)是免费开源的直播推流与视频录制软件,其「场景集(Scene Collection)」承载了全部场景、素材与输出设置。CLI-Anything 仓库下的 OBS Studio Agent Harness 为这一配置对象提供了一套有状态命令行接口:无需安装 OBS 本体即可通过 JSON 场景集文件完成场景、素材、滤镜、转场、推流与录制的全量编排,既适合人工在终端高效批处理,也适合以--json输出模式被 Agent 与 LLM 消费。阅读本文后,你将掌握该 Harness 的完整命令面、JSON 场景集文件结构、Source/Filter 类型注册表与参数约束,并学会从零搭建一个可推流可录制的直播工程。
核心操作文档位于 obs-studio/agent-harness/OBS.md,本文所有命令与结构均以该文档为骨架,并结合同目录下源码与测试进行纵深验证。
关键概念:从场景集到滤镜
该 Harness 将 OBS 的图形化操作抽象为 6 个核心对象:
| 概念 | 说明 |
|---|---|
| Scene Collection(场景集) | 一个工程文件,包含所有场景、素材与设置,即一个.json工程 |
| Scene(场景) | 场景内素材的组合,可在直播过程中切换 |
| Source(素材) | 放置在场景内的视频/音频/图像元素 |
| Filter(滤镜) | 施加于素材的效果(视频或音频处理) |
| Transition(转场) | 场景切换时使用的视觉效果 |
| Audio Source(音频素材) | 全局音频输入/输出,带音量与监听控制 |
工程以 JSON 形式持久化,源码侧的默认工程结构定义于 core/project.py(_default_project),版本号为1.0。
仓库位置与运行前提
OBS.md 记录的 Harness 目录为obs-studio/agent-harness,其内部源码布局如下:
obs-studio/agent-harness/ ├── OBS.md # 标准操作手册(本文主体) ├── setup.py └── cli_anything/ └── obs_studio/ ├── obs_studio_cli.py # CLI 入口(Click + REPL) ├── core/ # project/scenes/sources/filters/audio/transitions/output/session ├── utils/ # obs_utils.py 校验工具、repl_skin.py ├── tests/ # test_core.py、test_full_e2e.py 等 └── skills/SKILL.md # 面向 Agent 的技能说明按 README.md 与 OBS.md,依赖仅需click与prompt_toolkit:
pip install click prompt_toolkit说明:OBS.md / README 中记录的运行方式
python3 -m cli.obs_cli基于安装后(post-install)的包布局;当前仓库内检入的源码入口位于 cli_anything/obs_studio/obs_studio_cli.py,模块内部统一以cli_anything.obs_studio.*组织 import。project / scene / source / filter / audio / transition / output / session这一命令面在两种布局下完全一致。
端到端实战:搭建一个完整直播流工程
OBS.md 给出了完整的「创建流设置」操作序列。以下命令在 harness 目录下按序执行,即可得到一份含绿幕摄像头、游戏捕获、叠加层、转场与推流/录制配置的工程文件:
cd obs-studio/agent-harness # 1. 创建工程 python3 -m cli.obs_cli project new --name "my_stream" -o stream.json # 2. 添加带色度键的摄像头 python3 -m cli.obs_cli --project stream.json source add video_capture --name "Webcam" python3 -m cli.obs_cli --project stream.json filter add chroma_key -S 0 -p similarity=400 # 3. 添加游戏捕获 python3 -m cli.obs_cli --project stream.json source add display_capture --name "Game" # 4. 添加叠加层(水印/边框图) python3 -m cli.obs_cli --project stream.json source add image --name "Overlay" -S file=/path/to/overlay.png # 5. 建立备用场景 python3 -m cli.obs_cli --project stream.json scene add --name "BRB" python3 -m cli.obs_cli --project stream.json scene add --name "Starting Soon" # 6. 配置推流输出 python3 -m cli.obs_cli --project stream.json output streaming --service twitch --key "live_xxx" python3 -m cli.obs_cli --project stream.json output settings --preset balanced # 7. 配置录制 python3 -m cli.obs_cli --project stream.json output recording --format mp4 --quality high # 8. 保存 python3 -m cli.obs_cli --project stream.json project save命令细节要点(对应 obs_studio_cli.py 中的 Click 定义):
--project stream.json会先加载既有工程,使每条命令都是对同一状态的连续修改;所有单次命令结束后若状态被修改,会经auto_save_on_exit自动回写文件(可通过--dry-run关闭落盘);source add的类型参数是一个受限选择(ClickChoice),取值以 sources.py 中SOURCE_TYPES的键为准;filter add的-S 0指场景内第 0 号素材,-p key=value指定滤镜参数,-s可指定场景下标(默认 0);source add/filter add的-S与-p均支持多次出现,以拼装多组key=value。
交互式 REPL
除一次性命令外,可直接进入有状态 REPL:
python3 -m cli.obs_cli repl --project stream.jsonREPL 内部对每行输入做shlex切分后复用同一套cli.main子命令(obs_studio_cli.py),支持help查看命令分组、quit/exit/q退出;配合session undo/session redo可随时回退误操作。
JSON 场景集文件格式详解
OBS.md 给出了工程的 JSON 示例结构,这也是project new落盘的完整形态:
{ "version": "1.0", "name": "my_stream", "settings": { "output_width": 1920, "output_height": 1080, "fps": 30, "video_bitrate": 6000, "audio_bitrate": 160, "encoder": "x264" }, "scenes": [ { "id": 0, "name": "Main Scene", "sources": [ { "id": 0, "name": "Camera", "type": "video_capture", "visible": true, "locked": false, "position": {"x": 0, "y": 0}, "size": {"width": 1920, "height": 1080}, "crop": {"top": 0, "bottom": 0, "left": 0, "right": 0}, "rotation": 0, "opacity": 1.0, "filters": [], "settings": {} } ] } ], "transitions": [ {"name": "Cut", "type": "cut", "duration": 0}, {"name": "Fade", "type": "fade", "duration": 300} ], "active_scene": 0, "audio_sources": [], "streaming": {"service": "twitch", "server": "auto", "key": ""}, "recording": {"path": "./recordings/", "format": "mkv", "quality": "high"} }各字段与源码默认值的对应关系(见 core/project.py):
| 字段 | 说明 | 默认/取值约束 |
|---|---|---|
version | 场景集格式版本 | 固定1.0 |
settings.output_width/height | 输出分辨率 | 默认1920x1080,须为正整数 |
settings.fps | 帧率 | 默认30,须 ≥ 1 |
settings.video_bitrate | 视频码率(kbps) | 默认6000,须 ≥ 100 |
settings.audio_bitrate | 音频码率(kbps) | 默认160,须 ≥ 32 |
settings.encoder | 编码器 | 默认x264,合法值x264, x265, nvenc, qsv, amd, svt-av1 |
scenes[].sources[] | 素材对象 | 字段见下方「素材对象字段」 |
scenes[].sources[].filters[] | 滤镜链 | 默认空 |
active_scene | 当前激活场景下标 | 默认0 |
transitions[] | 转场列表 | 默认含Cut(0ms)与Fade(300ms) |
streaming | 推流配置 | {service, server, key},service 默认twitch |
recording | 录制配置 | {path, format, quality},默认./recordings/、mkv、high |
audio_sources | 全局音频素材 | 默认空数组 |
metadata | 创建/修改时间与软件标识 | created/modifiedISO 时间戳、software: "obs-cli 1.0" |
其中校验逻辑集中实现于 core/project.py(create_project)与 utils/obs_utils.py 的validate_*系列:分辨率、帧率、码率与编码器不合法会直接抛ValueError,素材的尺寸、裁剪与不透明度等同样有界校验。
素材对象字段与可用属性
每个素材对象由 sources.py 的_default_source生成,字段含id / name / type / visible / locked / position(x,y) / size(width,height) / crop(top,bottom,left,right) / rotation / opacity / filters / settings。
source set <index> <prop> <value>仅允许修改 5 个属性:name、visible、locked、opacity、rotation,其中opacity须在0.0~1.0内(见 sources.py);source transform <index>支持-p x,y、--size WxH、--crop top,bottom,left,right、--rotation deg,裁剪四边必须为非负整数;- 同名冲突由
unique_name自动追加.001式后缀,id由现有最大 id + 1 生成(obs_utils.py)。
Source 类型注册表
OBS.md 列出了 12 种素材类型;结合 sources.py 的SOURCE_TYPES注册表,可补全其内置默认参数:
| 类型 | 说明 | 默认参数(源码确认) |
|---|---|---|
video_capture | 摄像头/采集卡 | device:""、resolution:"1920x1080"、fps:30 |
display_capture | 全屏捕获 | display:0、capture_cursor:true |
window_capture | 单窗口捕获 | window:""、capture_cursor:true |
image | 静态图片 | file:""、unload_when_hidden:true |
media | 视频/音频文件 | local_file:""、looping:false、restart_on_activate:true |
browser | 网页素材 | url:""、width:800、height:600、css:"" |
text | 文本叠加 | text:""、font:"Sans Serif"、size:36、color:"#FFFFFF" |
color | 纯色背景 | color:"#000000"、width:1920、height:1080 |
audio_input | 麦克风输入 | device:"" |
audio_output | 桌面音频输出 | device:"" |
group | 素材分组 | items:[] |
scene | 嵌套场景 | scene_name:"" |
新增素材时可用-S key=value覆盖这些默认 settings(例如上文第 4 步的-S file=/path/to/overlay.png),也可用-p x,y与--size WxH直接指定位置和尺寸;-s <scene_index>指定放入哪个场景。
Filter 类型注册表与参数约束
OBS.md 的滤镜清单按视频/音频分类。源码侧每类滤镜都定义了可写参数及其类型、默认值与取值范围,见 filters.py 的FILTER_TYPES。添加滤镜时-p key=value传入的参数会经过_validate_filter_params做类型强转、越界与枚举校验——传了未注册的参数或超出范围的数值会直接报错。
| 类型 | 分类 | 说明 | 关键参数(默认值/取值范围) |
|---|---|---|---|
color_correction | video | 伽马/对比度/亮度/饱和度 | gamma(-3~3, 0)、contrast(-4~4, 0)、brightness(-1~1, 0)、saturation(-1~5, 0)、hue_shift(-180~180, 0)、opacity(0~1, 1) |
chroma_key | video | 绿/蓝幕抠像 | key_color_type∈{green,blue,magenta,custom}、similarity(1~1000, 400)、smoothness(1~1000, 80)、spill(1~1000, 100) |
color_key | video | 按指定色抠像 | key_color:"#00FF00"、similarity(400)、smoothness(80) |
lut | video | 套用颜色 LUT 文件 | path:""、amount(0~1, 1.0) |
image_mask | video | 透明度/混合蒙版 | path:""、type∈{alpha,blend} |
crop_pad | video | 裁剪边缘 | top/bottom/left/right(0~8192, 0) |
scroll | video | 滚动效果 | speed_x/speed_y(-5000~5000, 0)、loop(bool, true) |
sharpen | video | 锐化 | sharpness(0~1, 0.08) |
noise_suppress | audio | 噪声抑制 | method∈{rnnoise,speex,nvafx}、suppress_level(-60~0, -30) |
gain | audio | 音量增益 | db(-30~30, 0) |
compressor | audio | 动态范围压缩 | ratio(1~32, 10)、threshold(-60~0, -18)、attack(1~500, 6)、release(1~1000, 60)、output_gain(-30~30, 0) |
noise_gate | audio | 噪声门 | open_threshold(-96~0, -26)、close_threshold(-96~0, -32)、attack(25)、hold(200)、release(150) |
limiter | audio | 限制器 | threshold(-60~0, -6)、release(60) |
例如在 OBS.md 的命令中对 0 号素材-S 0添加chroma_key并设置similarity=400,等价于走 filters.py 的add_filter流程:自动补齐其余默认参数(key_color_type=green、smoothness=80、spill=100),随后可用filter set <filter_index> <param> <value>逐个微调;同素材可叠加多条滤镜形成链,filter list/filter list-available -c video|audio用于查看现状与可用集。
全局音频、转场与输出配置
音频素材
OBS.md 提到的全局音频素材由 core/audio.py 管理,命令面见 obs_studio_cli.py:
# 添加麦克风输入 python3 -m cli.obs_cli --project stream.json audio add --name "Mic" --type input --volume 1.0 # 音量(0.0~3.0,1.0 为 100%) python3 -m cli.obs_cli --project stream.json audio volume 0 1.5 # 静音/取消静音 python3 -m cli.obs_cli --project stream.json audio mute 0 python3 -m cli.obs_cli --project stream.json audio unmute 0 # 监听模式 python3 -m cli.obs_cli --project stream.json audio monitor 0 monitor_and_output监听模式仅允许none / monitor_only / monitor_and_output三值;底层音频对象还支持声道平衡(balance-1.0~1.0)与同步偏移(sync_offset,毫秒)。
转场
转场注册表(core/transitions.py)含 7 种类型:cut(0ms)、fade(300ms)、swipe(500ms)、slide(500ms)、stinger(1000ms)、fade_to_color(300ms)、luma_wipe(500ms)。默认工程预置Cut与Fade;约束为:时长非负、至少保留一个转场。使用示例:
python3 -m cli.obs_cli --project stream.json transition add stinger -n "Intro" -d 1000 python3 -m cli.obs_cli --project stream.json transition duration 2 800 python3 -m cli.obs_cli --project stream.json transition set-active 2 python3 -m cli.obs_cli --project stream.json transition list编码预设与录制
output settings --preset balanced这类预设来自 core/output.py 的ENCODING_PRESETS,一键决定编码器与码率组合:
| preset 名称 | encoder | video_bitrate | audio_bitrate |
|---|---|---|---|
ultrafast | x264 | 2500 | 128 |
fast | x264 | 4500 | 160 |
balanced | x264 | 6000 | 160 |
quality | x264 | 8000 | 192 |
high_quality | x264 | 12000 | 320 |
nvenc_fast | nvenc | 6000 | 160 |
nvenc_quality | nvenc | 10000 | 192 |
recording_high | x264 | 20000 | 320 |
推流服务限定twitch / youtube / facebook / custom(output streaming),录制容器限定mkv / mp4 / mov / flv / ts,录制质量限定low / medium / high / lossless(output recording)。set_output_settings支持「先应用预设、再以单参数覆盖」的灵活组合,例如固定nvenc_quality预设后再单独调高视频码率;所有离散取值不合法都会抛出带合法值列表的ValueError(output.py)。
有状态会话:undo/redo、自动保存与原子落盘
「有状态」是这套 Harness 的关键设计。Session(core/session.py)为每次修改前先调用snapshot记录整份工程的深拷贝快照(含操作描述与时间戳),从而提供:
- 最多 50 层 undo 栈(
MAX_UNDO = 50),每次新修改会清空 redo 栈; session status查看当前是否加载工程、是否被修改、undo/redo 深度;- 每个「一次命令」(
project new / scene add / source add / filter add / output ...等)内部都会sess.snapshot(...)再调用对应 core 函数; - 命令退出时的
auto_save_on_exit回调:只要非 REPL、非--dry-run、状态被修改且存在工程路径,即自动保存。
落盘采用带独占文件锁(fcntl.flock LOCK_EX)的原子写入,锁不可用时自动降级(session.py),从而规避多进程/Agent 并发写同一 JSON 时产生半截文件的风险。
全局入口还提供两个面向 Agent 的重要开关(obs_studio_cli.py):
--json:所有命令输出结构化 JSON(错误也输出{"error": ..., "type": ...});--dry-run:执行命令但不落盘,适合演练与预检。
测试:无 OBS 本体的完整验证
OBS.md 强调所有测试均无需安装 OBS Studio——因为 Harness 只操作 JSON 场景集。测试说明见 tests/TEST.md:test_core.py含 117 个单元测试(project/scenes/sources/filters/audio/transitions/output/session 共 8 个测试类),test_full_e2e.py含 36 个端到端测试,覆盖「绿幕摄像头搭建、4 层素材堆叠、滤镜链、转场工作流、输出配置、保存加载往返、undo/redo、边界场景(非法裁剪、空场景删素材、大场景集)」等,合计153 项。仓库内测试源码位于 tests/test_core.py 与 tests/test_full_e2e.py。
运行方式(在 harness 根目录下,可按仓库实际测试路径执行):
# 全部测试 python3 -m pytest cli_anything/obs_studio/tests/ -v # 仅单元测试 python3 -m pytest cli_anything/obs_studio/tests/test_core.py -v # 仅 E2E 测试 python3 -m pytest cli_anything/obs_studio/tests/test_full_e2e.py -v若按安装后的包布局执行 OBS.md 记录的命令,则为python3 -m pytest cli/tests/ -v。
面向 Agent 与 LLM 的调用约定
打包发布的技能文档 skills/SKILL.md 面向 AI Agent 给出了可执行的调用规范,与本 Harness 的 CLI 设计一致,可直接用于构建「Agent-Native」工作流:
- 始终使用
--json:所有命令输出可解析的 JSON(含错误对象),便于程序化消费; - 检查返回码:0 表示成功,非 0 表示失败;
- 解析 stderr:失败信息写在标准错误;
- 使用绝对路径:所有文件操作传绝对路径,规避工作目录歧义;
- 验证输出存在:导出/保存后确认文件已生成;
- 善用状态管理:对交互式场景使用 REPL 配合
session undo/redo,对一次性任务用--project连续命令 + 末尾project save; - 先试后写:不确定的改动可先加
--dry-run预演,确认无误再去掉该标志正式执行。
小结
围绕 OBS.md 的 SOP 骨架,本文完整覆盖了:从project new到output recording的流搭建命令链、JSON 场景集的结构化字段语义、12 种 Source 与 13 种 Filter 的类型注册及参数范围、7 种转场、8 组编码预设,以及支撑这一切的有状态 Session 机制(快照式 undo/redo、自动保存、加锁原子写)。由于整套工具只读写 JSON 场景集文件,它天然适合三种场景:脚本化批处理直播工程、无 OBS 环境下的配置预演、以及 Agent/LLM 以--json模式自主编排直播与录制资源。进一步的架构细节可继续阅读 README.md,实现级验证则对应 core 下的各模块与 153 项测试。
【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考