screencapturekit/
recording_output.rs

1//! `SCRecordingOutput` - Direct video file recording
2//!
3//! Available on macOS 15.0+
4//! Provides direct encoding of screen capture to video files.
5//!
6//! Requires the `macos_15_0` feature flag to be enabled.
7
8use std::ffi::c_void;
9use std::path::Path;
10
11/// Video codec for recording
12#[repr(i32)]
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
14pub enum SCRecordingOutputCodec {
15    /// H.264 codec
16    #[default]
17    H264 = 0,
18    /// H.265/HEVC codec
19    HEVC = 1,
20}
21
22/// Configuration for recording output
23pub struct SCRecordingOutputConfiguration {
24    ptr: *const c_void,
25}
26
27impl SCRecordingOutputConfiguration {
28    #[must_use]
29    pub fn new() -> Self {
30        let ptr = unsafe { crate::ffi::sc_recording_output_configuration_create() };
31        Self { ptr }
32    }
33
34    /// Set the output file URL
35    pub fn set_output_url(&mut self, path: &Path) {
36        if let Some(path_str) = path.to_str() {
37            if let Ok(c_path) = std::ffi::CString::new(path_str) {
38                unsafe {
39                    crate::ffi::sc_recording_output_configuration_set_output_url(
40                        self.ptr,
41                        c_path.as_ptr(),
42                    );
43                }
44            }
45        }
46    }
47
48    /// Set the video codec
49    pub fn set_video_codec(&mut self, codec: SCRecordingOutputCodec) {
50        unsafe {
51            crate::ffi::sc_recording_output_configuration_set_video_codec(self.ptr, codec as i32);
52        }
53    }
54
55    /// Set the average bitrate in bits per second
56    pub fn set_average_bitrate(&mut self, bitrate: i64) {
57        unsafe {
58            crate::ffi::sc_recording_output_configuration_set_average_bitrate(self.ptr, bitrate);
59        }
60    }
61
62    #[must_use]
63    pub fn as_ptr(&self) -> *const c_void {
64        self.ptr
65    }
66}
67
68impl Default for SCRecordingOutputConfiguration {
69    fn default() -> Self {
70        Self::new()
71    }
72}
73
74impl Clone for SCRecordingOutputConfiguration {
75    fn clone(&self) -> Self {
76        unsafe {
77            Self {
78                ptr: crate::ffi::sc_recording_output_configuration_retain(self.ptr),
79            }
80        }
81    }
82}
83
84impl Drop for SCRecordingOutputConfiguration {
85    fn drop(&mut self) {
86        if !self.ptr.is_null() {
87            unsafe {
88                crate::ffi::sc_recording_output_configuration_release(self.ptr);
89            }
90        }
91    }
92}
93
94impl std::fmt::Debug for SCRecordingOutputConfiguration {
95    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96        f.debug_struct("SCRecordingOutputConfiguration")
97            .field("ptr", &self.ptr)
98            .finish()
99    }
100}
101
102/// Recording output for direct video file encoding
103///
104/// Available on macOS 15.0+
105pub struct SCRecordingOutput {
106    ptr: *const c_void,
107}
108
109impl SCRecordingOutput {
110    /// Create a new recording output with configuration
111    ///
112    /// # Errors
113    /// Returns None if the system is not macOS 15.0+ or creation fails
114    pub fn new(config: &SCRecordingOutputConfiguration) -> Option<Self> {
115        let ptr = unsafe { crate::ffi::sc_recording_output_create(config.as_ptr()) };
116        if ptr.is_null() {
117            None
118        } else {
119            Some(Self { ptr })
120        }
121    }
122
123    #[must_use]
124    pub fn as_ptr(&self) -> *const c_void {
125        self.ptr
126    }
127}
128
129impl Clone for SCRecordingOutput {
130    fn clone(&self) -> Self {
131        unsafe {
132            Self {
133                ptr: crate::ffi::sc_recording_output_retain(self.ptr),
134            }
135        }
136    }
137}
138
139impl Drop for SCRecordingOutput {
140    fn drop(&mut self) {
141        if !self.ptr.is_null() {
142            unsafe {
143                crate::ffi::sc_recording_output_release(self.ptr);
144            }
145        }
146    }
147}
148
149// Safety: SCRecordingOutput wraps an Objective-C object that is thread-safe
150unsafe impl Send for SCRecordingOutput {}
151unsafe impl Sync for SCRecordingOutput {}
152
153// Safety: SCRecordingOutputConfiguration wraps an Objective-C object that is thread-safe
154unsafe impl Send for SCRecordingOutputConfiguration {}
155unsafe impl Sync for SCRecordingOutputConfiguration {}