| Crates.io | libobs-wrapper |
| lib.rs | libobs-wrapper |
| version | 4.0.2 |
| created_at | 2024-08-05 08:54:35.362247+00 |
| updated_at | 2025-09-17 19:44:47.733464+00 |
| description | A safe wrapper around libobs |
| homepage | |
| repository | https://github.com/joshprk/libobs-rs |
| max_upload_size | |
| id | 1325691 |
| size | 377,531 |
A safe, ergonomic Rust wrapper around the OBS (Open Broadcaster Software) Studio library. This crate provides a high-level interface for recording and streaming functionality using OBS's powerful capabilities, without having to deal with unsafe C/C++ code directly.
blocking feature)The library needs OBS binaries in your target directory. There are multiple ways to set this up:
Install the cargo-obs-build tool:
cargo install cargo-obs-build
Add the following to your Cargo.toml:
[package.metadata]
# The libobs version to use (can either be a specific version or "latest")
libobs-version = "31.0.3"
# Optional: The directory to store the OBS build
# libobs-cache-dir = "../obs-build"
Install OBS in your target directory:
# For debug builds
cargo obs-build --out-dir target/debug
# For release builds
cargo obs-build --out-dir target/release
# For testing
cargo obs-build --out-dir target/(debug|release)/deps
The library includes a bootstrapper that can download and install OBS binaries at runtime, which is useful for distributing applications without requiring users to install OBS separately.
Add a placeholder obs.dll file to your executable directory (eg. target/release/). That file will be replaced by the bootstrap during runtime:
obs.dllEnable the bootstrapper feature in your Cargo.toml:
[dependencies]
libobs-wrapper = { version = "4.0.1", features = ["bootstrapper"] }
async-trait = "0.1" # For implementing the bootstrap status handler
indicatif = "0.17" # Optional: For progress bars
use indicatif::{ProgressBar, ProgressStyle};
use libobs_wrapper::{
bootstrap::{
ObsBootstrapperOptions,
status_handler::ObsBootstrapStatusHandler,
},
context::ObsContext,
};
use std::{sync::Arc, time::Duration};
#[derive(Debug, Clone)]
struct ObsBootstrapProgress(Arc<ProgressBar>);
impl ObsBootstrapProgress {
pub fn new() -> Self {
let bar = ProgressBar::new(200).with_style(
ProgressStyle::with_template(
"[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
)
.unwrap(),
);
bar.set_message("Initializing bootstrapper...");
bar.enable_steady_tick(Duration::from_millis(50));
Self(Arc::new(bar))
}
pub fn done(&self) {
self.0.finish();
}
}
#[async_trait::async_trait]
impl ObsBootstrapStatusHandler for ObsBootstrapProgress {
async fn handle_downloading(&mut self, prog: f32, msg: String) -> anyhow::Result<()> {
self.0.set_message(msg);
self.0.set_position((prog * 100.0) as u64);
Ok(())
}
async fn handle_extraction(&mut self, prog: f32, msg: String) -> anyhow::Result<()> {
self.0.set_message(msg);
self.0.set_position(100 + (prog * 100.0) as u64);
Ok(())
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create a progress handler
let handler = ObsBootstrapProgress::new();
// Initialize OBS with bootstrapper
let context = ObsContext::builder()
.enable_bootstrapper(handler.clone(), ObsBootstrapperOptions::default())
.start()
.await?;
// Handle potential restart
let context = match context {
libobs_wrapper::context::ObsContextReturn::Done(c) => c,
libobs_wrapper::context::ObsContextReturn::Restart => {
println!("OBS has been downloaded and extracted. The application will now restart.");
return Ok(());
}
};
handler.done();
println!("OBS initialized successfully!");
// Now you can use the context for recording, etc.
Ok(())
}
With this approach, the bootstrapper will:
If the bootstrapper returns ObsContextReturn::Restart, your application should exit and will be automatically restarted with the updated binaries.
Here's a simple example of recording a monitor screen (assuming the bootstrapper feature is enabled):
use libobs_wrapper::{
context::ObsContext,
data::ObsData,
utils::{StartupInfo, OutputInfo},
sources::MonitorCaptureSourceBuilder,
data::video::ObsVideoInfoBuilder,
encoders::video::ObsVideoEncoder,
encoders::audio::ObsAudioEncoder,
};
use std::time::Duration;
async fn record_screen() -> Result<(), Box<dyn std::error::Error>> {
// Initialize OBS with default settings
let handler = ObsBootstrapConsoleHandler::default();
let context = ObsContext::builder()
.enable_bootstrapper(handler.clone(), ObsBootstrapperOptions::default())
.start()
.await
.unwrap();
let context = match context {
libobs_wrapper::context::ObsContextReturn::Done(c) => c,
libobs_wrapper::context::ObsContextReturn::Restart => {
println!("OBS has been downloaded and extracted. The application will now restart.");
return;
}
};
// Configure output (recording to file)
let mut output_settings = context.data().await?;
output_settings.set_string("path", "recording.mp4");
let output_info = OutputInfo::new("ffmpeg_muxer", "recording_output",
Some(output_settings), None);
let mut output = context.output(output_info).await?;
// Configure video encoder
let mut video_settings = context.data().await?;
video_settings.set_int("bitrate", 6000);
video_settings.set_string("rate_control", "CBR");
video_settings.set_string("preset", "medium");
// Get video handler and attach encoder to output
let video_handler = context.get_video_ptr().await?;
output.video_encoder(
VideoEncoderInfo::new(ObsVideoEncoderType::OBS_X264, "video_encoder",
Some(video_settings), None),
video_handler
).await?;
// Configure audio encoder
let mut audio_settings = context.data().await?;
audio_settings.set_int("bitrate", 160);
// Get audio handler and attach encoder to output
let audio_handler = context.get_audio_ptr().await?;
output.audio_encoder(
AudioEncoderInfo::new("ffmpeg_aac", "audio_encoder",
Some(audio_settings), None),
0, audio_handler
).await?;
// Create a scene and add a monitor capture source
let mut scene = context.scene("recording_scene").await?;
// Get available monitors and set up capture for the first one
let monitors = MonitorCaptureSourceBuilder::get_monitors()?;
if !monitors.is_empty() {
let monitor = &monitors[0];
let capture_source = MonitorCaptureSourceBuilder::new("screen_capture")
.set_monitor(monitor)
.add_to_scene(&mut scene)
.await?;
// Set the scene as active and start recording
scene.add_and_set(0).await?;
output.start().await?;
println!("Recording started");
std::thread::sleep(Duration::from_secs(10));
println!("Recording stopped");
output.stop().await?;
} else {
println!("No monitors found");
}
Ok(())
}
For more advanced usage examples, check out:
For even easier source creation and management, consider using the libobs-sources crate which builds on top of this wrapper.
blocking - Provides a blocking API instead of async (useful for applications that don't need async)bootstrapper - Enables the OBS bootstrapper for runtime download and installationIf you're experiencing crashes or missing DLL errors:
The library handles most memory management automatically, but you should avoid resetting the OBS context repeatedly as this can cause small memory leaks (due to an OBS limitation). Also notice that dropping Obs structs leads to a blocking call to the runtime.
This project is licensed under the MIT License - see the LICENSE file for details.