aria_kit/speaker/
voices.rs1mod grid;
8mod pyannote;
9mod timeline;
10
11use std::ops::Range;
12
13use super::Label;
14
15pub use pyannote::{Chunk, Grouping, PyannoteVoices, Standing, Voiceprint};
16
17pub trait Voices {
22 fn attribute(&self, spans: &[Range<u64>]) -> Vec<Option<Label>>;
25}
26
27pub fn attribute_spans(voices: &impl Voices, spans: &[Option<Range<u64>>]) -> Vec<Option<Label>> {
34 let timed: Vec<Range<u64>> = spans.iter().flatten().cloned().collect();
35 let mut answers = voices.attribute(&timed).into_iter();
36 spans
37 .iter()
38 .map(|span| span.as_ref().and_then(|_| answers.next().flatten()))
39 .collect()
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct Spoken {
45 pub span: Range<u64>,
46 pub speaker: Label,
47}
48
49#[derive(Debug, Clone, Default, PartialEq, Eq)]
56pub struct Revision {
57 pub merges: Vec<Merged>,
58}
59
60impl Revision {
61 pub fn revised(&self) -> bool {
62 !self.merges.is_empty()
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct Merged {
69 pub from: Label,
70 pub into: Label,
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 struct Positional(std::cell::RefCell<Vec<Range<u64>>>);
79
80 impl Voices for Positional {
81 fn attribute(&self, spans: &[Range<u64>]) -> Vec<Option<Label>> {
82 self.0.borrow_mut().extend_from_slice(spans);
83 spans
84 .iter()
85 .map(|span| Some(Label::Anonymous(span.start as u32)))
86 .collect()
87 }
88 }
89
90 #[test]
91 fn a_paragraph_with_no_span_is_never_asked_about() {
92 let voices = Positional(Vec::new().into());
93 let named = attribute_spans(&voices, &[Some(10..20), None, Some(30..40)]);
94
95 assert_eq!(
96 voices.0.borrow().as_slice(),
97 [10..20, 30..40],
98 "the track hears only the spans somebody measured"
99 );
100 assert_eq!(
101 named,
102 [Some(Label::Anonymous(10)), None, Some(Label::Anonymous(30))],
103 "and its answers land back on the paragraphs they were about"
104 );
105 }
106
107 #[test]
108 fn a_track_that_answers_short_leaves_the_rest_unnamed() {
109 struct Silent;
110 impl Voices for Silent {
111 fn attribute(&self, _spans: &[Range<u64>]) -> Vec<Option<Label>> {
112 Vec::new()
113 }
114 }
115 assert_eq!(attribute_spans(&Silent, &[Some(0..10), None]), [None, None]);
116 }
117}