|
1 | 1 | use crate::{FPS, recorder::ResizedImageBuffer, recorder_error::RecorderError}; |
2 | | -use x264::{Colorspace, Data, Encoder, Image}; |
| 2 | +use x264::{Colorspace, Data, Encoder, Image, Preset, Setup, Tune}; |
3 | 3 |
|
4 | 4 | /// Represents the result of video encoding operations. |
5 | 5 | /// |
@@ -186,15 +186,19 @@ impl VideoEncoder { |
186 | 186 | assert!(width > 0 && height > 0); |
187 | 187 |
|
188 | 188 | // Create x264 encoder with optimized settings for screen recording |
189 | | - let encoder = Encoder::builder() |
190 | | - .fps(fps.to_u32(), 1) |
191 | | - .build(Colorspace::RGB, width as i32, height as i32) |
192 | | - .map_err(|e| { |
193 | | - RecorderError::VideoEncodingFailed(format!( |
194 | | - "Failed to create x264 encoder: {:?}", |
195 | | - e |
196 | | - )) |
197 | | - })?; |
| 189 | + // Using ultrafast preset with stillimage tune for minimal memory usage |
| 190 | + let encoder = Setup::preset( |
| 191 | + Preset::Ultrafast, // Minimal memory usage and fastest encoding |
| 192 | + Tune::StillImage, // Optimized for screen content (static images) |
| 193 | + true, // fast_decode: Enable fast decoding |
| 194 | + true, // zero_latency: Minimal internal buffering |
| 195 | + ) |
| 196 | + .fps(fps.to_u32(), 1) |
| 197 | + .baseline() // Ensure maximum compatibility |
| 198 | + .build(Colorspace::RGB, width as i32, height as i32) |
| 199 | + .map_err(|e| { |
| 200 | + RecorderError::VideoEncodingFailed(format!("Failed to create x264 encoder: {:?}", e)) |
| 201 | + })?; |
198 | 202 |
|
199 | 203 | Ok(Self { |
200 | 204 | encoder, |
@@ -252,7 +256,6 @@ impl VideoEncoder { |
252 | 256 | // Calculate timestamp in milliseconds (frame_index * 1000 / fps) |
253 | 257 | let timestamp_ms = (self.frame_index * 1000) / self.fps.to_u32() as u64; |
254 | 258 |
|
255 | | - // NOTE: It will eat your memory (about 1G) |
256 | 259 | let (data, _) = self |
257 | 260 | .encoder |
258 | 261 | .encode(timestamp_ms as i64, image) |
|
0 commit comments