ff_pipeline/
encoder_config.rs1use ff_encode::BitrateMode;
4use ff_filter::HwAccel;
5use ff_format::{AudioCodec, VideoCodec};
6
7#[non_exhaustive]
13pub struct EncoderConfig {
14 pub video_codec: VideoCodec,
16
17 pub audio_codec: AudioCodec,
19
20 pub bitrate_mode: BitrateMode,
22
23 pub resolution: Option<(u32, u32)>,
35
36 pub framerate: Option<f64>,
40
41 pub hardware: Option<HwAccel>,
45}
46
47impl EncoderConfig {
48 #[must_use]
51 pub fn builder() -> EncoderConfigBuilder {
52 EncoderConfigBuilder::new()
53 }
54}
55
56pub struct EncoderConfigBuilder {
60 video_codec: VideoCodec,
61 audio_codec: AudioCodec,
62 bitrate_mode: BitrateMode,
63 resolution: Option<(u32, u32)>,
64 framerate: Option<f64>,
65 hardware: Option<HwAccel>,
66}
67
68impl EncoderConfigBuilder {
69 fn new() -> Self {
70 Self {
71 video_codec: VideoCodec::H264,
72 audio_codec: AudioCodec::Aac,
73 bitrate_mode: BitrateMode::Crf(23),
74 resolution: None,
75 framerate: None,
76 hardware: None,
77 }
78 }
79
80 #[must_use]
82 pub fn video_codec(mut self, codec: VideoCodec) -> Self {
83 self.video_codec = codec;
84 self
85 }
86
87 #[must_use]
89 pub fn audio_codec(mut self, codec: AudioCodec) -> Self {
90 self.audio_codec = codec;
91 self
92 }
93
94 #[must_use]
96 pub fn bitrate_mode(mut self, mode: BitrateMode) -> Self {
97 self.bitrate_mode = mode;
98 self
99 }
100
101 #[must_use]
103 pub fn crf(mut self, crf: u32) -> Self {
104 self.bitrate_mode = BitrateMode::Crf(crf);
105 self
106 }
107
108 #[must_use]
110 pub fn resolution(mut self, width: u32, height: u32) -> Self {
111 self.resolution = Some((width, height));
112 self
113 }
114
115 #[must_use]
117 pub fn framerate(mut self, fps: f64) -> Self {
118 self.framerate = Some(fps);
119 self
120 }
121
122 #[must_use]
124 pub fn hardware(mut self, hw: HwAccel) -> Self {
125 self.hardware = Some(hw);
126 self
127 }
128
129 #[must_use]
131 pub fn build(self) -> EncoderConfig {
132 EncoderConfig {
133 video_codec: self.video_codec,
134 audio_codec: self.audio_codec,
135 bitrate_mode: self.bitrate_mode,
136 resolution: self.resolution,
137 framerate: self.framerate,
138 hardware: self.hardware,
139 }
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn builder_should_use_h264_aac_crf23_as_defaults() {
149 let config = EncoderConfig::builder().build();
150 assert!(matches!(config.video_codec, VideoCodec::H264));
151 assert!(matches!(config.audio_codec, AudioCodec::Aac));
152 assert!(matches!(config.bitrate_mode, BitrateMode::Crf(23)));
153 assert!(config.resolution.is_none());
154 assert!(config.framerate.is_none());
155 assert!(config.hardware.is_none());
156 }
157
158 #[test]
159 fn builder_should_store_all_fields() {
160 let config = EncoderConfig::builder()
161 .video_codec(VideoCodec::H265)
162 .audio_codec(AudioCodec::Opus)
163 .bitrate_mode(BitrateMode::Cbr(4_000_000))
164 .resolution(1280, 720)
165 .framerate(30.0)
166 .build();
167
168 assert!(matches!(config.video_codec, VideoCodec::H265));
169 assert!(matches!(config.audio_codec, AudioCodec::Opus));
170 assert!(matches!(config.bitrate_mode, BitrateMode::Cbr(4_000_000)));
171 assert_eq!(config.resolution, Some((1280, 720)));
172 assert_eq!(config.framerate, Some(30.0));
173 }
174
175 #[test]
176 fn crf_convenience_should_set_crf_mode() {
177 let config = EncoderConfig::builder().crf(28).build();
178 assert!(matches!(config.bitrate_mode, BitrateMode::Crf(28)));
179 }
180}