The V-Streaming Plugin Development Kit (PDK) enables third-party developers to create plugins that extend the functionality of V-Streaming. Plugins can add new capture sources, audio/video effects, streaming destinations, UI themes, integrations, and utilities.
- Getting Started
- Plugin Architecture
- Plugin Categories
- API Reference
- Creating Your First Plugin
- Plugin Configuration
- Testing Plugins
- Distributing Plugins
- Best Practices
- Rust 1.70 or later
- V-Streaming 1.0.0 or later
- Basic understanding of Rust and async/await
- Create a new Rust project:
cargo new --lib my-vstreaming-plugin
cd my-vstreaming-plugin- Add V-Streaming PDK to
Cargo.toml:
[dependencies]
vstreaming-pdk = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"- Create your plugin implementation
Unloaded → Loading → Loaded → Initialized → Running → Paused → Stopping → Unloaded
↓
Error
- Plugin Metadata: Information about your plugin
- Plugin Context: API client for communicating with V-Streaming
- Plugin Implementation: The core functionality
- Plugin Configuration: User-configurable settings
Add new capture sources (e.g., virtual cameras, screen sharing services, game-specific capture).
Capabilities:
AddCaptureSources
Example Use Cases:
- Virtual camera capture
- Remote screen sharing
- Console-specific capture cards
Process audio with custom effects (e.g., noise reduction, voice effects).
Capabilities:
ProcessAudio
Example Use Cases:
- Noise suppression
- Voice changer
- Audio restoration
Apply video effects and filters (e.g., color grading, visual effects).
Capabilities:
ProcessVideo
Example Use Cases:
- LUT application
- Blur effects
- Visual distortions
Stream to custom platforms or services.
Capabilities:
SendStream
Example Use Cases:
- Custom streaming platforms
- Local network streaming
- Recording services
Customize the V-Streaming interface appearance.
Capabilities:
ModifyUI
Example Use Cases:
- Dark/light themes
- Custom color schemes
- Layout modifications
Integrate with third-party services (e.g., Twitch, Discord, Slack).
Capabilities:
AccessChat,SendChat
Example Use Cases:
- Twitch chat integration
- Discord notifications
- Social media posting
General-purpose utilities and helpers.
Example Use Cases:
- File management
- Batch operations
- System monitoring
All plugins must implement the Plugin trait:
pub trait Plugin: Send + Sync {
/// Get plugin metadata
fn metadata(&self) -> PluginMetadata;
/// Initialize the plugin
fn initialize(&mut self, context: PluginContext) -> Result<(), PluginError>;
/// Start the plugin
fn start(&mut self) -> Result<(), PluginError>;
/// Stop the plugin
fn stop(&mut self) -> Result<(), PluginError>;
/// Get current plugin state
fn state(&self) -> PluginState;
/// Handle a command from V-Streaming
fn handle_command(
&mut self,
command: &str,
params: serde_json::Value,
) -> Result<serde_json::Value, PluginError>;
/// Handle an event from V-Streaming
fn handle_event(&mut self, event: &str, data: serde_json::Value) -> Result<(), PluginError>;
/// Get plugin configuration
fn get_config(&self) -> PluginConfig;
/// Update plugin configuration
fn update_config(&mut self, config: PluginConfig) -> Result<(), PluginError>;
/// Clean up plugin resources
fn cleanup(&mut self) -> Result<(), PluginError>;
}The PluginContext provides an api field with methods for communicating with V-Streaming:
pub struct PluginApiClient {
/// Event emitter
event_emitter: EventEmitter,
/// Command executor
command_executor: CommandExecutor,
}
impl PluginApiClient {
/// Send a command to V-Streaming
pub async fn send_command(
&self,
command: &str,
params: serde_json::Value,
) -> Result<serde_json::Value, PluginError>;
/// Emit an event
pub fn emit(&self, event: &str, data: serde_json::Value);
/// Subscribe to an event
pub fn subscribe(&self, event: &str, callback: EventCallback);
}enumerate_capture_sources: List available capture sourcesstart_capture: Start capturing from a sourcestop_capture: Stop capturing
enumerate_audio_devices: List audio devicescreate_audio_track: Create a new audio trackapply_audio_effect: Apply an audio effect
create_scene: Create a new sceneadd_layer: Add a layer to a sceneset_layer_blend_mode: Set layer blend mode
start_streaming: Start streamingstop_streaming: Stop streamingget_streaming_stats: Get streaming statistics
stream_started: Streaming startedstream_stopped: Streaming stoppedstream_error: Streaming error occurred
chat_message: New chat message receivedchat_command: Chat command received
capture_started: Capture startedcapture_stopped: Capture stoppedcapture_error: Capture error occurred
use vstreaming_pdk::{Plugin, PluginMetadata, PluginCategory, PluginCapability, BasePlugin};
use serde_json::Value;
fn create_metadata() -> PluginMetadata {
PluginMetadata {
id: "com.example.my-plugin".to_string(),
name: "My Plugin".to_string(),
version: "1.0.0".to_string(),
description: "A simple example plugin".to_string(),
author: "Your Name".to_string(),
license: "MIT".to_string(),
min_api_version: "1.0.0".to_string(),
homepage_url: Some("https://example.com".to_string()),
repository_url: Some("https://github.com/example/my-plugin".to_string()),
category: PluginCategory::AudioEffect,
capabilities: vec![PluginCapability::ProcessAudio],
config_schema: None,
}
}struct MyPlugin {
base: BasePlugin,
// Add your plugin-specific fields here
custom_setting: bool,
}
impl MyPlugin {
fn new() -> Self {
let metadata = create_metadata();
Self {
base: BasePlugin::new(metadata),
custom_setting: true,
}
}
}
impl Plugin for MyPlugin {
fn metadata(&self) -> PluginMetadata {
self.base.metadata()
}
fn initialize(&mut self, context: PluginContext) -> Result<(), PluginError> {
self.base.initialize(context)?;
// Your initialization code here
Ok(())
}
fn start(&mut self) -> Result<(), PluginError> {
self.base.start()?;
// Your start code here
Ok(())
}
fn stop(&mut self) -> Result<(), PluginError> {
self.base.stop()?;
// Your stop code here
Ok(())
}
fn state(&self) -> PluginState {
self.base.state()
}
fn handle_command(
&mut self,
command: &str,
params: Value,
) -> Result<Value, PluginError> {
match command {
"get_custom_setting" => {
Ok(json!({ "custom_setting": self.custom_setting }))
}
"set_custom_setting" => {
self.custom_setting = params["value"].as_bool().unwrap_or(false);
Ok(json!({ "success": true }))
}
_ => self.base.handle_command(command, params),
}
}
fn handle_event(&mut self, event: &str, data: Value) -> Result<(), PluginError> {
match event {
"stream_started" => {
// Handle stream started event
println!("Stream started: {:?}", data);
}
_ => {}
}
Ok(())
}
fn get_config(&self) -> PluginConfig {
self.base.get_config()
}
fn update_config(&mut self, config: PluginConfig) -> Result<(), PluginError> {
self.base.update_config(config)
}
fn cleanup(&mut self) -> Result<(), PluginError> {
self.base.cleanup()
}
}use vstreaming_pdk::{Plugin, PluginManager};
use std::sync::Arc;
use tokio::sync::Mutex;
// Plugin factory function
#[no_mangle]
pub extern "C" fn create_plugin() -> *mut dyn Plugin {
let plugin = MyPlugin::new();
Box::into_raw(Box::new(plugin))
}
// Plugin cleanup function
#[no_mangle]
pub extern "C" fn destroy_plugin(plugin: *mut dyn Plugin) {
if !plugin.is_null() {
unsafe {
let _ = Box::from_raw(plugin);
}
}
}Define a JSON Schema for your plugin's configuration:
let config_schema = json!({
"type": "object",
"properties": {
"custom_setting": {
"type": "boolean",
"default": true,
"description": "A custom boolean setting"
},
"threshold": {
"type": "number",
"minimum": 0,
"maximum": 100,
"default": 50,
"description": "A threshold value"
}
},
"required": ["custom_setting"]
});fn update_config(&mut self, config: PluginConfig) -> Result<(), PluginError> {
// Access settings
if let Some(custom_setting) = config.settings.get("custom_setting") {
self.custom_setting = custom_setting.as_bool().unwrap_or(true);
}
Ok(())
}#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_plugin_metadata() {
let metadata = create_metadata();
assert_eq!(metadata.id, "com.example.my-plugin");
}
#[test]
fn test_plugin_initialization() {
let mut plugin = MyPlugin::new();
assert_eq!(plugin.state(), PluginState::Unloaded);
}
}Use V-Streaming's test harness to test plugin integration:
cargo test --test integration_testsmy-plugin/
├── Cargo.toml
├── src/
│ └── lib.rs
├── README.md
├── LICENSE
└── manifest.json
{
"id": "com.example.my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"description": "A simple example plugin",
"author": "Your Name",
"license": "MIT",
"min_vstreaming_version": "1.0.0",
"files": {
"windows": "target/release/my_plugin.dll",
"linux": "target/release/libmy_plugin.so",
"macos": "target/release/libmy_plugin.dylib"
},
"homepage_url": "https://example.com",
"repository_url": "https://github.com/example/my-plugin",
"icon": "icon.png"
}# Windows
cargo build --release
# Linux
cargo build --release
# macOS
cargo build --releaseAlways handle errors gracefully:
fn handle_command(&mut self, command: &str, params: Value) -> Result<Value, PluginError> {
match command {
"my_command" => {
self.validate_params(¶ms)?;
Ok(json!({ "success": true }))
}
_ => Err(PluginError::CommandNotSupported {
command: command.to_string()
})
}
}Clean up resources properly:
fn cleanup(&mut self) -> Result<(), PluginError> {
// Close connections
// Free memory
// Stop threads
Ok(())
}- Use async/await for I/O operations
- Cache frequently accessed data
- Avoid blocking the main thread
Use structured logging:
use tracing::{info, error, debug};
info!("Plugin initialized: {}", self.metadata().id);
error!("Failed to process command: {}", command);
debug!("Processing frame: {}", frame_number);- Validate all input
- Use secure connections
- Don't expose sensitive data
- Write unit tests for all functions
- Write integration tests for plugin interactions
- Test error handling
- Document all public APIs
- Provide examples in README
- Include inline comments for complex logic
- Documentation: https://docs.vstreaming.com/pdk
- GitHub Issues: https://github.com/vantisCorp/V-Streaming/issues
- Discord: https://discord.gg/vstreaming
- Email: support@vstreaming.com
V-Streaming PDK is licensed under the MIT License. Your plugin can use any license you choose.
- Initial release
- Core plugin API
- Plugin manager
- Documentation