Expand description
§oxvif
An async Rust client library for the ONVIF IP camera protocol.
ONVIF (Open Network Video Interface Forum) is the industry standard for interoperability between IP-based security cameras. This library provides a complete async client covering device management, media streaming, PTZ control, imaging, on-screen display, events, recording, search, and replay — all over SOAP/HTTP(S) with WS-Security and HTTP Digest authentication.
§ONVIF Profile coverage
| Profile | Description | Coverage | Notes |
|---|---|---|---|
| Profile S | Video streaming | ~95% | All core operations implemented |
| Profile T | Advanced streaming (H.265, focus, OSD, audio) | ~95% | HTTP Digest Auth, Media2 audio/metadata/analytics config, PTZ compat; Analytics rules and DeviceIO not yet implemented |
| Profile G | Recording & playback | ~85% | Read/search/replay + full recording/job write management; live-source job binding not yet implemented |
§Supported services
- Device — capabilities, scopes, device info, hostname, NTP, reboot, user management, network interfaces/protocols/DNS/gateway, relay outputs, storage configurations, system log/URIs, factory default, discovery mode, auxiliary commands (wiper/IR lamp)
- Media1 / Media2 — profiles, RTSP/snapshot URIs, video + audio config, OSD, metadata config, audio decoder/output config, video source modes, unified AddConfiguration/RemoveConfiguration
- PTZ — absolute/relative/continuous move, presets, home position, status, configurations, nodes, compatible configurations
- Imaging — brightness/contrast/exposure settings, focus move/stop/status
- Events — pull-point subscriptions, event polling, renew, unsubscribe,
continuous
event_stream, synchronization point - Recording — list stored recordings; create/delete recordings, tracks, and recording jobs
- Search — find recordings by scope, collect results, end search
- Replay — get RTSP playback URI for a stored recording
- WS-Discovery — UDP multicast probe to find cameras on the local network
§Architecture
┌──────────────────────────────────────────────────────┐
│ OnvifSession │
│ caches service URLs — delegates every call │
├──────────────────────────────────────────────────────┤
│ OnvifClient │
│ stateless — you supply service URLs per call │
├──────────────────────────────────────────────────────┤
│ soap::SoapEnvelope │ soap::WsSecurityToken │ ← SOAP layer
├──────────────────────────────────────────────────────┤
│ Transport trait │ ← HTTP abstraction
│ (HttpTransport / mock in tests) │
└──────────────────────────────────────────────────────┘§Quick start
Two ways to use oxvif — pick whichever suits your workflow.
§OnvifSession — URL caching handled for you
OnvifSession calls GetCapabilities once at construction and caches all
service URLs. No URL parameters needed for individual methods.
use oxvif::{OnvifSession, OnvifError};
async fn run() -> Result<(), OnvifError> {
let session = OnvifSession::builder("http://192.168.1.100/onvif/device_service")
.with_credentials("admin", "password")
.with_clock_sync() // syncs WS-Security timestamp with device clock
.build()
.await?;
let profiles = session.get_profiles().await?;
let uri = session.get_stream_uri(&profiles[0].token).await?;
println!("RTSP stream: {}", uri.uri);
let status = session.ptz_get_status(&profiles[0].token).await?;
println!("Pan: {:?} Tilt: {:?}", status.pan, status.tilt);
Ok(())
}§OnvifClient — direct control, you manage service URLs
OnvifClient is stateless and gives direct control over every call.
You fetch and forward service URLs yourself for full routing control.
use oxvif::{OnvifClient, OnvifError};
async fn run() -> Result<(), OnvifError> {
let client = OnvifClient::new("http://192.168.1.100/onvif/device_service")
.with_credentials("admin", "password");
let dt = client.get_system_date_and_time().await?;
let client = client.with_utc_offset(dt.utc_offset_secs());
let caps = client.get_capabilities().await?;
let media_url = caps.media.url.as_deref().unwrap();
let profiles = client.get_profiles(media_url).await?;
let uri = client.get_stream_uri(media_url, &profiles[0].token).await?;
println!("RTSP stream: {}", uri.uri);
Ok(())
}§Testing without a real camera
Implement transport::Transport to inject any XML fixture:
use oxvif::transport::{Transport, TransportError};
use async_trait::async_trait;
use std::sync::Arc;
struct MockTransport { xml: String }
#[async_trait]
impl Transport for MockTransport {
async fn soap_post(&self, _url: &str, _action: &str, _body: String)
-> Result<String, TransportError>
{
Ok(self.xml.clone())
}
}
let client = oxvif::OnvifClient::new("http://ignored")
.with_transport(Arc::new(MockTransport { xml: "<s:Envelope/>".into() }));Re-exports§
pub use client::OnvifClient;pub use client::notification_listener;pub use discovery::DiscoveredDevice;pub use discovery::DiscoveryEvent;pub use discovery::probe_unicast;pub use error::OnvifError;pub use session::OnvifSession;pub use session::OnvifSessionBuilder;pub use types::AnalyticsCapabilities;pub use types::AudioDecoderConfiguration;pub use types::AudioEncoderConfiguration;pub use types::AudioEncoderConfigurationOptions;pub use types::AudioEncoderOptions;pub use types::AudioEncoding;pub use types::AudioOutputConfiguration;pub use types::AudioSource;pub use types::AudioSourceConfiguration;pub use types::BoundsRange;pub use types::Capabilities;pub use types::DeviceCapabilities;pub use types::DeviceInfo;pub use types::DeviceIoCapabilities;pub use types::DnsInformation;pub use types::EncoderInstanceInfo;pub use types::EventProperties;pub use types::EventsCapabilities;pub use types::FindRecordingResults;pub use types::FloatRange;pub use types::FocusMove;pub use types::H264Configuration;pub use types::H264Options;pub use types::H265Configuration;pub use types::H265Options;pub use types::Hostname;pub use types::ImagingCapabilities;pub use types::ImagingMoveOptions;pub use types::ImagingOptions;pub use types::ImagingSettings;pub use types::ImagingStatus;pub use types::IntRange;pub use types::IoCapabilities;pub use types::JpegOptions;pub use types::Media2Capabilities;pub use types::MediaCapabilities;pub use types::MediaProfile;pub use types::MediaProfile2;pub use types::MetadataConfiguration;pub use types::MetadataConfigurationOptions;pub use types::MulticastConfiguration;pub use types::NetworkCapabilities;pub use types::NetworkGateway;pub use types::NetworkInterface;pub use types::NetworkProtocol;pub use types::NotificationMessage;pub use types::NtpInfo;pub use types::OnvifService;pub use types::OsdColor;pub use types::OsdConfiguration;pub use types::OsdOptions;pub use types::OsdPosition;pub use types::OsdTextString;pub use types::PtzCapabilities;pub use types::PtzConfiguration;pub use types::PtzConfigurationOptions;pub use types::PtzNode;pub use types::PtzPreset;pub use types::PtzSpaceRange;pub use types::PtzSpeed;pub use types::PtzStatus;pub use types::PullPointSubscription;pub use types::PushSubscription;pub use types::RecordingCapabilities;pub use types::RecordingConfiguration;pub use types::RecordingInformation;pub use types::RecordingItem;pub use types::RecordingJob;pub use types::RecordingJobConfiguration;pub use types::RecordingJobState;pub use types::RecordingSourceInformation;pub use types::RecordingTrack;pub use types::RelayOutput;pub use types::ReplayCapabilities;pub use types::Resolution;pub use types::SearchCapabilities;pub use types::SecurityCapabilities;pub use types::SetDateTimeRequest;pub use types::SnapshotUri;pub use types::SourceBounds;pub use types::StorageConfiguration;pub use types::StreamUri;pub use types::StreamingCapabilities;pub use types::SystemCapabilities;pub use types::SystemDateTime;pub use types::SystemLog;pub use types::SystemUris;pub use types::User;pub use types::UtcDateTime;pub use types::VideoEncoderConfiguration;pub use types::VideoEncoderConfiguration2;pub use types::VideoEncoderConfigurationOptions;pub use types::VideoEncoderConfigurationOptions2;pub use types::VideoEncoderInstances;pub use types::VideoEncoderOptions2;pub use types::VideoEncoding;pub use types::VideoRateControl;pub use types::VideoRateControl2;pub use types::VideoSource;pub use types::VideoSourceConfiguration;pub use types::VideoSourceConfigurationOptions;pub use types::VideoSourceMode;
Modules§
- client
- High-level ONVIF client.
- discovery
- WS-Discovery — UDP multicast device probe.
- error
- Top-level error type for the oxvif library.
- session
- High-level session wrapper around
OnvifClient. - soap
- SOAP protocol layer for ONVIF.
- transport
- HTTP transport abstraction for SOAP over HTTP/HTTPS.
- types
- Typed response structs for all ONVIF operations.