viser_contextaware/
lib.rs1mod profile;
2
3pub use profile::*;
4
5use serde::{Deserialize, Serialize};
6use std::time::{Duration, Instant};
7use viser_encoding::{Config as EncodingConfig, ProgressSender};
8use viser_hull::{Hull, Point};
9use viser_ladder::{self, Ladder};
10
11#[derive(Debug, Clone)]
13pub struct Config {
14 pub profiles: Vec<Profile>,
15 pub crf_values: Vec<i32>,
16 pub preset: String,
17 pub subsample: i32,
18 pub parallel: i32,
19}
20
21impl Default for Config {
22 fn default() -> Self {
23 Self {
24 profiles: all_profiles(),
25 crf_values: vec![18, 22, 26, 30, 34, 38, 42],
26 preset: "veryfast".into(),
27 subsample: 5,
28 parallel: 2,
29 }
30 }
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct DeviceResult {
35 pub profile: Profile,
36 pub hull: Hull,
37 pub ladder: Ladder,
38 pub points: Vec<Point>,
39 pub trial_count: usize,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct Result {
44 pub source: String,
45 pub devices: Vec<DeviceResult>,
46 pub duration: Duration,
47}
48
49#[derive(Debug, Clone)]
50pub struct Progress {
51 pub device_done: usize,
52 pub device_total: usize,
53 pub device_name: String,
54}
55
56pub async fn analyze(
58 source: &str,
59 cfg: Config,
60 progress_tx: Option<tokio::sync::mpsc::Sender<Progress>>,
61) -> anyhow::Result<Result> {
62 let start = Instant::now();
63 let mut devices = Vec::new();
64 let sender = ProgressSender::new(progress_tx);
65
66 for (i, profile) in cfg.profiles.iter().enumerate() {
67 let pt_cfg = viser_pertitle::Config {
68 encoding: EncodingConfig {
69 resolutions: profile.resolutions.clone(),
70 crf_values: cfg.crf_values.clone(),
71 codecs: profile.codecs.clone(),
72 preset: cfg.preset.clone(),
73 subsample: cfg.subsample,
74 parallel: cfg.parallel,
75 ..Default::default()
76 },
77 ladder_opts: profile.ladder_opts.clone(),
78 vmaf_model: profile.vmaf_model.clone(),
79 checkpoint_path: String::new(),
80 };
81
82 let pt_result = viser_pertitle::analyze(source, pt_cfg, None)
83 .await
84 .map_err(|e| anyhow::anyhow!("analysis for {} failed: {e}", profile.name))?;
85
86 let device_ladder = viser_ladder::select(&pt_result.hull, &profile.ladder_opts);
87
88 devices.push(DeviceResult {
89 profile: profile.clone(),
90 hull: pt_result.hull,
91 ladder: device_ladder,
92 points: pt_result.points,
93 trial_count: pt_result.trial_count,
94 });
95
96 sender.send(Progress {
97 device_done: i + 1,
98 device_total: cfg.profiles.len(),
99 device_name: profile.name.clone(),
100 });
101 }
102
103 Ok(Result { source: source.to_string(), devices, duration: start.elapsed() })
104}