Skip to main content

pylibobs

Python bindings for libobs — the core C library of OBS Studio.

Lets Python scripts and apps drive libobs directly: initialize OBS, build scenes, configure encoders, mix audio, and record / stream — all without OBS Studio's UI running.

Status: beta. The public API is feature-complete and covered by tests. Reference counting semantics match OBS 32's obs_*_get_ref() model.


Why?

Existing options:

  • obspython runs inside OBS only — you can't pip install it or use it from a normal Python app.
  • obsws-python / simpleobsws talk to OBS via WebSocket — requires OBS to be running, and only exposes what the WebSocket API allows.

pylibobs links libobs directly (via cffi), so your Python process is the OBS host.


License

Copyright (C) 2026 Jonata Bolzan Loss and contributors.

pylibobs is licensed under GPL v2 or later, inherited from libobs. See LICENSE for the full text.

The published wheels bundle libobs's compiled binaries (also GPLv2+), so the wheel as distributed is covered by GPLv2+. Anything you build on top of pylibobs must be GPL-compatible if you redistribute it. Personal use carries no obligation.


Installation

pip install pylibobs

That's it on Windows / macOS / Linux. The wheel ships with bundled libobs binaries (libobs plus its plugin DLLs and data files, sourced from the official OBS Studio release on PyPI's build server). You don't need to install OBS Studio.

Linux: pylibobs 33 bundles OBS 33's official Linux build, which OBS publishes for Ubuntu 26.04 only. The wheel needs glibc 2.43+ and the system FFmpeg 8 / x264 libraries of that generation (Ubuntu 26.04 or newer, or an equally recent distribution). On older systems pip cannot use the wheel; install the last release for OBS 32 instead:

pip install "pylibobs<33"

Without that pin, pip falls back to building pylibobs 33 from source there, and stops with an error pointing to this command: the source package carries no libobs. To use pylibobs 33 with a system-installed OBS 33 instead, set PYLIBOBS_ALLOW_SYSTEM_LIBOBS=1 when installing.

If you're installing from sdist (rare — only when no wheel is published for your platform), or you want to use a system-installed OBS, the loader falls back through:

  1. $LIBOBS_PATH environment variable (explicit override)
  2. Bundled libs inside the wheel — pylibobs/_libs/<platform>/<arch>/
  3. ctypes.util.find_library("obs")
  4. Well-known OBS Studio install paths

Maintainers / contributors can refresh the bundled libs by running:

python scripts/fetch_libs.py                  # current platform
python scripts/fetch_libs.py --all            # every platform
python scripts/fetch_libs.py --version 33.0.0 # pin OBS version

This downloads libobs from the official OBS GitHub release. The _libs/ tree is .gitignored and only populated during wheel builds.


Quick start

import time
from pylibobs import (
    OBSContext, OBSData, Source, Scene, Output,
    VideoEncoder, AudioEncoder,
)

with OBSContext() as obs:
    obs.set_video(width=1920, height=1080, fps_num=60)
    obs.set_audio()
    obs.load_modules()

    scene = Scene.create("main")
    cap = Source.create("monitor_capture", "Desktop", {"monitor": 0})
    scene.add(cap)

    venc = VideoEncoder.create("obs_x264", "video", {"crf": 23, "preset": "veryfast"})
    aenc = AudioEncoder.create("ffmpeg_aac", "audio", {"bitrate": 192})

    out = Output.create("ffmpeg_muxer", "rec", {"path": "out.mkv"})
    out.set_video_encoder(venc)
    out.set_audio_encoder(aenc)
    out.start()

    time.sleep(10)
    out.stop()

See examples/ for full recording and streaming scripts.

pylibobs-studio (tkinter, stdlib only)

examples/pylibobs_studio.py is a complete OBS-style desktop application built on nothing but the Python standard library:

python examples/pylibobs_studio.py

Features:

Pane What it does
Live preview libobs's D3D11 renderer draws directly into a tkinter Frame via its native HWND (Frame.winfo_id() → Display.from_window(hwnd, w, h)). No Qt, no GTK, no extra deps.
Scenes Add / remove scenes; selecting one routes it to the program output.
Sources Per-scene list; add via a type-picker dialog populated from enum_input_types(), with auto-launched monitor/window/file pickers for the source types that need them. Reorder, toggle visibility, remove.
Audio mixer One row per audio-capable source: live VU meter (green / yellow / red), volume slider on an IEC dB curve, mute toggle. Levels come from a VolumeMeter queue read on the tk main loop.
Recording Standard MKV recording with live frames / bytes / dropped-frames in the status bar.

The whole app is ~600 lines in a single file. Use it as a starting point for your own pylibobs-based applications.


API overview

Class Wraps Notes
OBSContext obs_startup / obs_shutdown, video/audio reset Use as a context manager.
OBSData obs_data_t Dict-like; OBSData({"k": "v"})
Source obs_source_t Source.create(kind, name, settings)
Scene / SceneItem obs_scene_t / obs_sceneitem_t Add sources, set visibility, iterate items
VideoEncoder / AudioEncoder obs_encoder_t Per-type factory
Service obs_service_t RTMP/streaming targets
Output obs_output_t File or stream sinks; start()/stop()
Display obs_display_t Live preview into a native window (HWND)

Testing

pip install -e ".[dev]"

# Unit tests (mocked cffi layer — fast, no libobs needed)
pytest tests/unit

# Integration tests (need a real libobs)
pytest tests/integration -m integration

# On Linux CI with no display:
Xvfb :99 -screen 0 1920x1080x24 &
DISPLAY=:99 pytest tests/integration -m integration

CI runs the full matrix on Windows, Linux, and macOS — see .github/workflows/ci.yml.


Project layout

pylibobs/
├── pylibobs/
│   ├── _lib.py            # Library locator
│   ├── _ffi.py            # cffi instance
│   ├── _declarations.py   # C API declarations for cdef()
│   ├── context.py         # OBSContext
│   ├── data.py            # OBSData
│   ├── source.py          # Source
│   ├── scene.py           # Scene / SceneItem
│   ├── encoder.py         # VideoEncoder / AudioEncoder
│   ├── service.py         # Service
│   ├── output.py          # Output
│   └── _libs/             # Bundled libobs binaries (after fetch_libs.py)
├── tests/unit/            # Mocked tests
├── tests/integration/     # Real libobs tests
├── scripts/fetch_libs.py  # Pull libobs from OBS releases
└── examples/              # record_to_file.py, stream_to_rtmp.py

Moving from pylibobs 32 (OBS 32) to 33

  • Audio monitoring is on/off. OBS 33 replaced the three monitoring types with obs_source_set/get_monitoring_enabled (the old calls are deprecated). Use Source.monitoring_enabled. Monitor only (heard, but kept out of recordings and streams) is now monitoring plus mute: Source.set_monitor_only().
  • Old scene collections: a source saved with monitor only loads in OBS 33 as monitored and in the output — its audio now reaches recordings and streams. Mute those sources (or call set_monitor_only()) after loading if that matters.
  • Plugins moved to obs-modules/core/ (Linux), core/<module>/ (Windows) and PlugIns/*.plugin (macOS). pylibobs finds them in all of these and in the 32.x layouts; OBSContext.failed_modules lists any module that would not load.
  • Images: the gs_image_file/2/3/4 functions are gone; raw callers use gs_image_file_ex_* (ffi.new("gs_image_file_ex_t *")).
  • obs_add_core_module was removed; obs_source_set_hidden / is_hidden and obs_load_all_modules are deprecated (the latter does nothing any more).

Coverage / known gaps

pylibobs targets libobs 33.0.0 and declares every function it exports (1381 obs_* / gs_* / signal_* / proc_* / calldata_* / audio_output_* / video_output_* symbols), reachable via pylibobs._ffi.get_lib(). 1155 of them carry their full C signature; the remaining 226 are declared as void f(void) placeholders because scripts/generate_cdef.py cannot parse their headers yet — they resolve, but need a curated signature in _declarations.py before they can be called correctly. Pythonic class-based wrappers cover the common workflows:

  • Lifecycle, video/audio init, scenes, sources, scene items, transforms (pos/scale/rot/crop/bounds)
  • Outputs (file + RTMP streaming), encoders (incl. ROI hints and EncoderCaps), services
  • Live preview (Display attached to a native window via HWND)
  • Filters, transitions, hotkeys, fader + VU meter, audio monitoring (Source.monitoring_enabled, set_monitor_only())
  • Type lookups: display names, defaults, encoder capabilities, themed source icons (32.2+)
  • Raw audio/video callbacks (numpy-friendly), audio resampler, media remux
  • Properties API (read + edit, with type-aware widgets in examples/pylibobs_studio.py)
  • Save / load whole scene collections to JSON

What's intentionally raw-only (callable via get_lib() but no class wrapper):

  • The 290 gs_* graphics primitives — exposing them invites GPU-thread bugs; use obs_render_main_texture() instead.
  • Property builders (obs_properties_add_*) — only useful for C plugin authors.
  • Multi-canvas API (obs_canvas_*), obs_view_*, codec bitstream parsers (obs_avc_* / obs_av1_*).

Contributing

git clone https://github.com/jonata/pylibobs.git
cd pylibobs
python -m venv .venv && source .venv/bin/activate    # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
python scripts/fetch_libs.py                          # download bundled libobs
pytest                                                # 100+ tests, mock + integration

The integration suite needs process isolation (libobs can't gracefully restart inside a single process); use the included runner:

python scripts/run_tests.py

Release process

pylibobs is versioned after the libobs it bundles: pylibobs X.Y.Z ships libobs X.Y.Z. A release that only changes pylibobs, on the same libobs, adds a fourth number (X.Y.Z.1, X.Y.Z.2, …). Moving to a new libobs resets to its version.

  1. Set the same version in pyproject.toml and pylibobs/__init__.py; when moving to a new libobs, also update DEFAULT_OBS_TAG in scripts/fetch_libs.py. python scripts/check_version.py checks they agree.
  2. Tag the commit v<version> (e.g. v33.0.0) and push the tag. GitHub Actions:
    • Refuses to build unless the tag, both version strings and DEFAULT_OBS_TAG agree
    • Builds platform-specific wheels with bundled libobs (Windows x64 / Linux x86_64 / macOS Apple Silicon)
    • Builds the sdist
    • Publishes to PyPI via Trusted Publishing (no token needed in repo secrets)
    • Attaches all wheels to a GitHub Release with auto-generated notes

To set up Trusted Publishing on PyPI for this repo, register pylibobs as a project on PyPI, then in Project settings → Publishing, add a "GitHub Actions" trusted publisher pointing at <owner>/pylibobs / workflow release.yml / environment pypi.


Contributions welcome — PRs against main.

Metadata

Release files for pylibobs 33.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pylibobs 33.0.0
File Size Uploaded Provenance Actions
pylibobs-33.0.0.tar.gz 112.3 kB With provenance Details for pylibobs-33.0.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for pylibobs 33.0.0
File Interpreter ABI Platform Actions
pylibobs-33.0.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details for pylibobs-33.0.0-py3-none-win_amd64.whl
pylibobs-33.0.0-py3-none-manylinux_2_43_x86_64.whl Python 3 none Linux glibc 2.43+ x86-64 Details for pylibobs-33.0.0-py3-none-manylinux_2_43_x86_64.whl
pylibobs-33.0.0-py3-none-macosx_13_0_arm64.whl Python 3 none macOS 13.0+ ARM64 Details for pylibobs-33.0.0-py3-none-macosx_13_0_arm64.whl

Total release size: 85.1 MB

Release files / pylibobs-33.0.0.tar.gz

Download URL pylibobs-33.0.0.tar.gz
Size 112.3 kB
Tags Source
SHA-256 checksum
How to use checksums
5973832d62e0fe16577f7760e965482c91143c007dee4f51713a3e53be956792
BLAKE2b-256 checksum
How to use checksums
68f4a74f28269a28331ba26d404fc34d96913f71e49f9580c8f6e9ccccc7b3d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Release files / pylibobs-33.0.0-py3-none-win_amd64.whl

Download URL pylibobs-33.0.0-py3-none-win_amd64.whl
Size 32.8 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
80b5ada458ddea2253680deca97d92cb620fe28117a33f0483d24d091eb99efd
BLAKE2b-256 checksum
How to use checksums
0c57f5b2859caff56b436cece9d8ee86f95c5f37eb200d9a633c653fd694d052
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Release files / pylibobs-33.0.0-py3-none-manylinux_2_43_x86_64.whl

Download URL pylibobs-33.0.0-py3-none-manylinux_2_43_x86_64.whl
Size 6.6 MB
Tags Linux glibc 2.43+ x86-64 Python 3
SHA-256 checksum
How to use checksums
e0faa7ebea70f3b184eaabfd5876864efde2cb2e2d13ed15b8661dfc38463ef9
BLAKE2b-256 checksum
How to use checksums
773338563c214ad55414473d37bd737488ec65c696177b1d0aeff20fe4feab18
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Release files / pylibobs-33.0.0-py3-none-macosx_13_0_arm64.whl

Download URL pylibobs-33.0.0-py3-none-macosx_13_0_arm64.whl
Size 45.6 MB
Tags Python 3 macOS 13.0+ ARM64
SHA-256 checksum
How to use checksums
11843cfeeddfd674007c1e524b5d4fb035762bd0a2616fe49e533a1817f04c76
BLAKE2b-256 checksum
How to use checksums
20b2fef9a65b9bf68fb4c1231eee3c696ae68a89f59cda8de5d44878fb0a7940
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Security for pylibobs 33.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 4 files in this release have been uploaded with provenance metadata.

Select from 4 files

Attestation for pylibobs-33.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page