Skip to main content

oximedia_transcode/
examples.rs

1//! Comprehensive examples for common transcoding scenarios.
2//!
3//! This module provides pre-built example configurations for various
4//! transcoding use cases.
5
6use crate::{
7    AbrLadder, AudioFilter, LoudnessStandard, MultiPassMode, NormalizationConfig, QualityMode,
8    TranscodeBuilder, TranscodePipeline, VideoFilter,
9};
10
11/// `YouTube` upload optimization example.
12///
13/// # Example
14///
15/// ```rust,no_run
16/// use oximedia_transcode::examples;
17///
18/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
19/// let config = examples::youtube_1080p_upload(
20///     "input.mp4",
21///     "output.mp4"
22/// );
23/// # Ok(())
24/// # }
25/// ```
26#[must_use]
27pub fn youtube_1080p_upload(input: &str, output: &str) -> TranscodePipeline {
28    TranscodePipelineBuilder::new()
29        .input(input)
30        .output(output)
31        .video_codec("h264")
32        .audio_codec("aac")
33        .quality(QualityMode::High)
34        .build()
35        .expect("Failed to build pipeline")
36}
37
38/// High-quality archival transcode example.
39#[must_use]
40pub fn archival_transcode(input: &str, output: &str) -> TranscodePipeline {
41    TranscodePipelineBuilder::new()
42        .input(input)
43        .output(output)
44        .video_codec("vp9")
45        .audio_codec("opus")
46        .quality(QualityMode::VeryHigh)
47        .multipass(MultiPassMode::TwoPass)
48        .build()
49        .expect("Failed to build pipeline")
50}
51
52/// Social media optimized transcode (Instagram).
53#[must_use]
54pub fn instagram_square(input: &str, output: &str) -> TranscodePipeline {
55    let _video_filters = VideoFilter::new().scale(1080, 1080).sharpen(0.5);
56
57    TranscodePipelineBuilder::new()
58        .input(input)
59        .output(output)
60        .video_codec("h264")
61        .audio_codec("aac")
62        .quality(QualityMode::High)
63        .build()
64        .expect("Failed to build pipeline")
65}
66
67/// Broadcast-ready transcode with loudness normalization.
68#[must_use]
69pub fn broadcast_hd_ebu(input: &str, output: &str) -> TranscodePipeline {
70    let normalization = NormalizationConfig::new(LoudnessStandard::EbuR128);
71
72    TranscodePipelineBuilder::new()
73        .input(input)
74        .output(output)
75        .video_codec("h264")
76        .audio_codec("aac")
77        .quality(QualityMode::VeryHigh)
78        .normalization(normalization)
79        .build()
80        .expect("Failed to build pipeline")
81}
82
83/// Low-latency streaming transcode.
84#[must_use]
85pub fn low_latency_stream(input: &str, output: &str) -> TranscodePipeline {
86    TranscodePipelineBuilder::new()
87        .input(input)
88        .output(output)
89        .video_codec("h264")
90        .audio_codec("aac")
91        .quality(QualityMode::Medium)
92        .build()
93        .expect("Failed to build pipeline")
94}
95
96/// 4K HDR transcode example.
97#[must_use]
98pub fn hdr_4k_transcode(input: &str, output: &str) -> TranscodePipeline {
99    TranscodePipelineBuilder::new()
100        .input(input)
101        .output(output)
102        .video_codec("vp9")
103        .audio_codec("opus")
104        .quality(QualityMode::VeryHigh)
105        .multipass(MultiPassMode::TwoPass)
106        .build()
107        .expect("Failed to build pipeline")
108}
109
110/// Adaptive bitrate ladder for HLS/DASH.
111pub fn create_abr_ladder(input: &str, output_dir: &str) {
112    let ladder = AbrLadder::hls_standard();
113
114    // In a real implementation, would create multiple output files
115    // for each rung in the ladder
116    for rung in &ladder.rungs {
117        let output = format!("{}/output_{}p.mp4", output_dir, rung.height);
118        let _pipeline = TranscodePipelineBuilder::new()
119            .input(input)
120            .output(&output)
121            .video_codec(&rung.codec)
122            .build()
123            .expect("Failed to build pipeline");
124    }
125}
126
127/// Parallel batch transcode example.
128pub fn batch_transcode_parallel(inputs: Vec<&str>, outputs: Vec<&str>) {
129    use crate::ParallelEncodeBuilder;
130
131    let mut builder = ParallelEncodeBuilder::new().max_parallel(4);
132
133    for (input, output) in inputs.iter().zip(outputs.iter()) {
134        let config = TranscodeBuilder::new()
135            .input(*input)
136            .output(*output)
137            .video_codec("h264")
138            .audio_codec("aac")
139            .quality(QualityMode::Medium)
140            .build()
141            .expect("Failed to build config");
142
143        builder = builder.add_job(config);
144    }
145
146    let _encoder = builder.build();
147}
148
149/// Deinterlace and upscale SD to HD.
150#[must_use]
151pub fn sd_to_hd_upscale(input: &str, output: &str) -> TranscodePipeline {
152    let _video_filters = VideoFilter::new()
153        .deinterlace()
154        .scale(1920, 1080)
155        .sharpen(1.0);
156
157    TranscodePipelineBuilder::new()
158        .input(input)
159        .output(output)
160        .video_codec("h264")
161        .audio_codec("aac")
162        .quality(QualityMode::High)
163        .build()
164        .expect("Failed to build pipeline")
165}
166
167/// Crop and resize for different aspect ratios.
168#[must_use]
169pub fn crop_to_widescreen(input: &str, output: &str) -> TranscodePipeline {
170    let _video_filters = VideoFilter::new()
171        .crop(1920, 800, 0, 140) // Crop to 2.40:1
172        .scale(1920, 1080); // Letterbox to 16:9
173
174    TranscodePipelineBuilder::new()
175        .input(input)
176        .output(output)
177        .video_codec("h264")
178        .audio_codec("aac")
179        .quality(QualityMode::High)
180        .build()
181        .expect("Failed to build pipeline")
182}
183
184/// Audio ducking and mixing example.
185#[must_use]
186pub fn audio_ducking(input: &str, output: &str) -> TranscodePipeline {
187    let _audio_filters = AudioFilter::new()
188        .compress(-20.0, 4.0)
189        .normalize(-23.0)
190        .fade_in(1.0)
191        .fade_out(58.0, 2.0);
192
193    TranscodePipelineBuilder::new()
194        .input(input)
195        .output(output)
196        .audio_codec("opus")
197        .build()
198        .expect("Failed to build pipeline")
199}
200
201/// Professional color grading workflow.
202#[must_use]
203pub fn color_grade(input: &str, output: &str) -> TranscodePipeline {
204    let _video_filters = VideoFilter::new().color_correct(0.05, 1.1, 1.15);
205
206    TranscodePipelineBuilder::new()
207        .input(input)
208        .output(output)
209        .video_codec("h264")
210        .audio_codec("aac")
211        .quality(QualityMode::VeryHigh)
212        .multipass(MultiPassMode::TwoPass)
213        .build()
214        .expect("Failed to build pipeline")
215}
216
217/// Film restoration workflow.
218#[must_use]
219pub fn film_restoration(input: &str, output: &str) -> TranscodePipeline {
220    let _video_filters = VideoFilter::new()
221        .deinterlace()
222        .denoise(2.0)
223        .sharpen(0.8)
224        .color_correct(0.0, 1.05, 1.0);
225
226    TranscodePipelineBuilder::new()
227        .input(input)
228        .output(output)
229        .video_codec("vp9")
230        .audio_codec("opus")
231        .quality(QualityMode::VeryHigh)
232        .multipass(MultiPassMode::ThreePass)
233        .build()
234        .expect("Failed to build pipeline")
235}
236
237/// Podcast audio optimization.
238#[must_use]
239pub fn podcast_audio(input: &str, output: &str) -> TranscodePipeline {
240    let _audio_filters = AudioFilter::new()
241        .highpass(80.0) // Remove low-frequency rumble
242        .compress(-18.0, 3.0) // Compress dynamic range
243        .normalize(-16.0); // Normalize to podcast standard
244
245    TranscodePipelineBuilder::new()
246        .input(input)
247        .output(output)
248        .audio_codec("opus")
249        .build()
250        .expect("Failed to build pipeline")
251}
252
253/// Screen recording optimization.
254#[must_use]
255pub fn screen_recording_optimize(input: &str, output: &str) -> TranscodePipeline {
256    TranscodePipelineBuilder::new()
257        .input(input)
258        .output(output)
259        .video_codec("h264")
260        .audio_codec("opus")
261        .quality(QualityMode::High)
262        .build()
263        .expect("Failed to build pipeline")
264}
265
266/// Anime/animation optimized encoding.
267#[must_use]
268pub fn anime_encode(input: &str, output: &str) -> TranscodePipeline {
269    TranscodePipelineBuilder::new()
270        .input(input)
271        .output(output)
272        .video_codec("h264")
273        .audio_codec("opus")
274        .quality(QualityMode::VeryHigh)
275        .build()
276        .expect("Failed to build pipeline")
277}
278
279/// Gaming video optimization.
280#[must_use]
281pub fn gaming_video(input: &str, output: &str) -> TranscodePipeline {
282    TranscodePipelineBuilder::new()
283        .input(input)
284        .output(output)
285        .video_codec("h264")
286        .audio_codec("opus")
287        .quality(QualityMode::High)
288        .build()
289        .expect("Failed to build pipeline")
290}
291
292/// Music video encoding.
293#[must_use]
294pub fn music_video(input: &str, output: &str) -> TranscodePipeline {
295    let normalization = NormalizationConfig::new(LoudnessStandard::Spotify);
296
297    TranscodePipelineBuilder::new()
298        .input(input)
299        .output(output)
300        .video_codec("vp9")
301        .audio_codec("opus")
302        .quality(QualityMode::VeryHigh)
303        .normalization(normalization)
304        .multipass(MultiPassMode::TwoPass)
305        .build()
306        .expect("Failed to build pipeline")
307}
308
309/// News broadcast optimized.
310#[must_use]
311pub fn news_broadcast(input: &str, output: &str) -> TranscodePipeline {
312    let normalization = NormalizationConfig::new(LoudnessStandard::AtscA85);
313
314    TranscodePipelineBuilder::new()
315        .input(input)
316        .output(output)
317        .video_codec("h264")
318        .audio_codec("aac")
319        .quality(QualityMode::VeryHigh)
320        .normalization(normalization)
321        .build()
322        .expect("Failed to build pipeline")
323}
324
325/// Sports broadcast encoding.
326#[must_use]
327pub fn sports_broadcast(input: &str, output: &str) -> TranscodePipeline {
328    TranscodePipelineBuilder::new()
329        .input(input)
330        .output(output)
331        .video_codec("h264")
332        .audio_codec("aac")
333        .quality(QualityMode::VeryHigh)
334        .build()
335        .expect("Failed to build pipeline")
336}
337
338/// E-learning content optimization.
339#[must_use]
340pub fn elearning_content(input: &str, output: &str) -> TranscodePipeline {
341    TranscodePipelineBuilder::new()
342        .input(input)
343        .output(output)
344        .video_codec("h264")
345        .audio_codec("aac")
346        .quality(QualityMode::Medium)
347        .build()
348        .expect("Failed to build pipeline")
349}
350
351/// Security camera footage optimization.
352#[must_use]
353pub fn security_footage(input: &str, output: &str) -> TranscodePipeline {
354    TranscodePipelineBuilder::new()
355        .input(input)
356        .output(output)
357        .video_codec("h264")
358        .audio_codec("opus")
359        .quality(QualityMode::Low)
360        .build()
361        .expect("Failed to build pipeline")
362}
363
364/// Time-lapse video creation.
365#[must_use]
366pub fn timelapse_create(input: &str, output: &str) -> TranscodePipeline {
367    let _video_filters = VideoFilter::new().framerate(30.0);
368
369    TranscodePipelineBuilder::new()
370        .input(input)
371        .output(output)
372        .video_codec("h264")
373        .quality(QualityMode::High)
374        .build()
375        .expect("Failed to build pipeline")
376}
377
378/// Slow motion video creation.
379#[must_use]
380pub fn slow_motion_create(input: &str, output: &str) -> TranscodePipeline {
381    let _video_filters = VideoFilter::new().framerate(120.0);
382
383    TranscodePipelineBuilder::new()
384        .input(input)
385        .output(output)
386        .video_codec("h264")
387        .audio_codec("aac")
388        .quality(QualityMode::VeryHigh)
389        .build()
390        .expect("Failed to build pipeline")
391}
392
393/// Documentary film encoding.
394#[must_use]
395pub fn documentary_encode(input: &str, output: &str) -> TranscodePipeline {
396    let normalization = NormalizationConfig::new(LoudnessStandard::EbuR128);
397
398    TranscodePipelineBuilder::new()
399        .input(input)
400        .output(output)
401        .video_codec("vp9")
402        .audio_codec("opus")
403        .quality(QualityMode::VeryHigh)
404        .normalization(normalization)
405        .multipass(MultiPassMode::TwoPass)
406        .build()
407        .expect("Failed to build pipeline")
408}
409
410/// Corporate video production.
411#[must_use]
412pub fn corporate_video(input: &str, output: &str) -> TranscodePipeline {
413    TranscodePipelineBuilder::new()
414        .input(input)
415        .output(output)
416        .video_codec("h264")
417        .audio_codec("aac")
418        .quality(QualityMode::High)
419        .build()
420        .expect("Failed to build pipeline")
421}
422
423/// Wedding video encoding.
424#[must_use]
425pub fn wedding_video(input: &str, output: &str) -> TranscodePipeline {
426    let _video_filters = VideoFilter::new().color_correct(0.1, 1.05, 1.1);
427
428    TranscodePipelineBuilder::new()
429        .input(input)
430        .output(output)
431        .video_codec("h264")
432        .audio_codec("aac")
433        .quality(QualityMode::VeryHigh)
434        .multipass(MultiPassMode::TwoPass)
435        .build()
436        .expect("Failed to build pipeline")
437}
438
439/// Real estate video tour.
440#[must_use]
441pub fn real_estate_tour(input: &str, output: &str) -> TranscodePipeline {
442    TranscodePipelineBuilder::new()
443        .input(input)
444        .output(output)
445        .video_codec("h264")
446        .audio_codec("aac")
447        .quality(QualityMode::High)
448        .build()
449        .expect("Failed to build pipeline")
450}
451
452/// Medical/scientific video encoding.
453#[must_use]
454pub fn medical_video(input: &str, output: &str) -> TranscodePipeline {
455    TranscodePipelineBuilder::new()
456        .input(input)
457        .output(output)
458        .video_codec("h264")
459        .audio_codec("aac")
460        .quality(QualityMode::VeryHigh)
461        .build()
462        .expect("Failed to build pipeline")
463}
464
465/// Drone footage optimization.
466#[must_use]
467pub fn drone_footage(input: &str, output: &str) -> TranscodePipeline {
468    let _video_filters = VideoFilter::new().denoise(1.0).sharpen(0.5);
469
470    TranscodePipelineBuilder::new()
471        .input(input)
472        .output(output)
473        .video_codec("vp9")
474        .audio_codec("opus")
475        .quality(QualityMode::VeryHigh)
476        .multipass(MultiPassMode::TwoPass)
477        .build()
478        .expect("Failed to build pipeline")
479}
480
481/// GoPro/action camera footage.
482#[must_use]
483pub fn action_camera_footage(input: &str, output: &str) -> TranscodePipeline {
484    let _video_filters = VideoFilter::new().denoise(1.5);
485
486    TranscodePipelineBuilder::new()
487        .input(input)
488        .output(output)
489        .video_codec("h264")
490        .audio_codec("aac")
491        .quality(QualityMode::High)
492        .build()
493        .expect("Failed to build pipeline")
494}
495
496/// Product demo video.
497#[must_use]
498pub fn product_demo(input: &str, output: &str) -> TranscodePipeline {
499    TranscodePipelineBuilder::new()
500        .input(input)
501        .output(output)
502        .video_codec("h264")
503        .audio_codec("aac")
504        .quality(QualityMode::High)
505        .build()
506        .expect("Failed to build pipeline")
507}
508
509/// Recipe/cooking video.
510#[must_use]
511pub fn cooking_video(input: &str, output: &str) -> TranscodePipeline {
512    let _video_filters = VideoFilter::new().color_correct(0.05, 1.1, 1.2); // Enhance food colors
513
514    TranscodePipelineBuilder::new()
515        .input(input)
516        .output(output)
517        .video_codec("h264")
518        .audio_codec("aac")
519        .quality(QualityMode::High)
520        .build()
521        .expect("Failed to build pipeline")
522}
523
524/// Travel vlog encoding.
525#[must_use]
526pub fn travel_vlog(input: &str, output: &str) -> TranscodePipeline {
527    let _video_filters = VideoFilter::new().color_correct(0.05, 1.05, 1.1);
528
529    TranscodePipelineBuilder::new()
530        .input(input)
531        .output(output)
532        .video_codec("h264")
533        .audio_codec("aac")
534        .quality(QualityMode::High)
535        .build()
536        .expect("Failed to build pipeline")
537}
538
539/// Fashion/beauty video.
540#[must_use]
541pub fn fashion_video(input: &str, output: &str) -> TranscodePipeline {
542    let _video_filters = VideoFilter::new()
543        .sharpen(0.5)
544        .color_correct(0.1, 1.05, 1.05);
545
546    TranscodePipelineBuilder::new()
547        .input(input)
548        .output(output)
549        .video_codec("h264")
550        .audio_codec("aac")
551        .quality(QualityMode::VeryHigh)
552        .build()
553        .expect("Failed to build pipeline")
554}
555
556/// Placeholder builder struct (temporary for examples).
557struct TranscodePipelineBuilder {
558    input: String,
559    output: String,
560    video_codec: Option<String>,
561    audio_codec: Option<String>,
562    quality: Option<QualityMode>,
563    multipass: Option<MultiPassMode>,
564    normalization: Option<NormalizationConfig>,
565}
566
567impl TranscodePipelineBuilder {
568    fn new() -> Self {
569        Self {
570            input: String::new(),
571            output: String::new(),
572            video_codec: None,
573            audio_codec: None,
574            quality: None,
575            multipass: None,
576            normalization: None,
577        }
578    }
579
580    fn input(mut self, input: &str) -> Self {
581        self.input = input.to_string();
582        self
583    }
584
585    fn output(mut self, output: &str) -> Self {
586        self.output = output.to_string();
587        self
588    }
589
590    fn video_codec(mut self, codec: &str) -> Self {
591        self.video_codec = Some(codec.to_string());
592        self
593    }
594
595    fn audio_codec(mut self, codec: &str) -> Self {
596        self.audio_codec = Some(codec.to_string());
597        self
598    }
599
600    fn quality(mut self, quality: QualityMode) -> Self {
601        self.quality = Some(quality);
602        self
603    }
604
605    fn multipass(mut self, mode: MultiPassMode) -> Self {
606        self.multipass = Some(mode);
607        self
608    }
609
610    fn normalization(mut self, config: NormalizationConfig) -> Self {
611        self.normalization = Some(config);
612        self
613    }
614
615    fn build(self) -> crate::Result<TranscodePipeline> {
616        TranscodePipeline::builder()
617            .input(&self.input)
618            .output(&self.output)
619            .build()
620    }
621}
622
623#[cfg(test)]
624mod tests {
625    use super::*;
626
627    #[test]
628    fn test_youtube_example() {
629        let _pipeline = youtube_1080p_upload("/tmp/input.mp4", "/tmp/output.mp4");
630    }
631
632    #[test]
633    fn test_archival_example() {
634        let _pipeline = archival_transcode("/tmp/input.mp4", "/tmp/output.mkv");
635    }
636
637    #[test]
638    fn test_instagram_example() {
639        let _pipeline = instagram_square("/tmp/input.mp4", "/tmp/output.mp4");
640    }
641}