···
1
1
-
use crate::synchronization::sync::Syncable;
2
2
-
use serde::Deserialize;
3
3
-
use serde_aux::field_attributes::deserialize_number_from_string;
4
4
-
use std::{
5
5
-
collections::HashMap, io::Read, path::PathBuf, process::Stdio,
6
6
-
};
7
7
-
8
8
-
use super::sync::TimestampMS;
9
9
-
10
10
-
pub struct CueMarkersSynchronizer {
11
11
-
pub path: PathBuf,
12
12
-
}
13
13
-
14
14
-
#[derive(Debug, Deserialize)]
15
15
-
struct FFprobeChapterTags {
16
16
-
title: String,
17
17
-
}
18
18
-
19
19
-
#[derive(Debug, Deserialize)]
20
20
-
struct FFprobeChapter {
21
21
-
// id: usize,
22
22
-
// time_base: String,
23
23
-
24
24
-
// start: usize,
25
25
-
#[serde(deserialize_with = "deserialize_number_from_string")]
26
26
-
start_time: f32,
27
27
-
28
28
-
// end: usize,
29
29
-
// #[serde(deserialize_with = "deserialize_number_from_string")]
30
30
-
// end_time: f32,
31
31
-
32
32
-
tags: FFprobeChapterTags,
33
33
-
}
34
34
-
35
35
-
#[derive(Debug, Deserialize)]
36
36
-
struct FFprobeOutput {
37
37
-
chapters: Vec<FFprobeChapter>,
38
38
-
}
39
39
-
40
40
-
impl Syncable for CueMarkersSynchronizer {
41
41
-
fn new(path: impl Into<PathBuf>) -> Self {
42
42
-
Self { path: path.into() }
43
43
-
}
44
44
-
45
45
-
fn load(
46
46
-
&self,
47
47
-
progress: Option<&indicatif::ProgressBar>,
48
48
-
) -> super::sync::SyncData {
49
49
-
let mut ffprobe = std::process::Command::new("ffprobe")
50
50
-
.args(["-v", "error"])
51
51
-
.args(["-i", &self.path.to_string_lossy()])
52
52
-
.args(["-output_format", "json"])
53
53
-
.arg("-show_chapters")
54
54
-
.stdout(Stdio::piped())
55
55
-
.spawn()
56
56
-
.expect(&format!(
57
57
-
"Couldn't run ffprobe to get chapters of {:?}",
58
58
-
self.path
59
59
-
));
60
60
-
61
61
-
let mut raw_output = String::new();
62
62
-
ffprobe
63
63
-
.stdout
64
64
-
.take()
65
65
-
.expect("Coudln't get stdout of ffprobe run")
66
66
-
.read_to_string(&mut raw_output)
67
67
-
.expect("Couldn't read ffprobe stdout");
68
68
-
69
69
-
let output: FFprobeOutput =
70
70
-
serde_json::from_str(&raw_output).expect("Invalid ffprobe output");
71
71
-
72
72
-
super::sync::SyncData {
73
73
-
stems: HashMap::new(),
74
74
-
bpm: None,
75
75
-
markers: output
76
76
-
.chapters
77
77
-
.iter()
78
78
-
.map(|ch| {
79
79
-
(
80
80
-
(ch.start_time.to_owned() * 1_000.0) as TimestampMS,
81
81
-
ch.tags.title.clone(),
82
82
-
)
83
83
-
})
84
84
-
.collect(),
85
85
-
}
86
86
-
}
87
87
-
}
1
1
+
use crate::synchronization::sync::Syncable;
2
2
+
use serde::Deserialize;
3
3
+
use serde_aux::field_attributes::deserialize_number_from_string;
4
4
+
use std::{collections::HashMap, io::Read, path::PathBuf, process::Stdio};
5
5
+
6
6
+
use super::sync::TimestampMS;
7
7
+
8
8
+
pub struct CueMarkersSynchronizer {
9
9
+
pub path: PathBuf,
10
10
+
}
11
11
+
12
12
+
#[derive(Debug, Deserialize)]
13
13
+
struct FFprobeChapterTags {
14
14
+
title: String,
15
15
+
}
16
16
+
17
17
+
#[derive(Debug, Deserialize)]
18
18
+
struct FFprobeChapter {
19
19
+
// id: usize,
20
20
+
// time_base: String,
21
21
+
22
22
+
// start: usize,
23
23
+
#[serde(deserialize_with = "deserialize_number_from_string")]
24
24
+
start_time: f32,
25
25
+
26
26
+
// end: usize,
27
27
+
// #[serde(deserialize_with = "deserialize_number_from_string")]
28
28
+
// end_time: f32,
29
29
+
tags: FFprobeChapterTags,
30
30
+
}
31
31
+
32
32
+
#[derive(Debug, Deserialize)]
33
33
+
struct FFprobeOutput {
34
34
+
chapters: Vec<FFprobeChapter>,
35
35
+
}
36
36
+
37
37
+
impl Syncable for CueMarkersSynchronizer {
38
38
+
fn new(path: impl Into<PathBuf>) -> Self {
39
39
+
Self { path: path.into() }
40
40
+
}
41
41
+
42
42
+
fn load(
43
43
+
&self,
44
44
+
progress: Option<&indicatif::ProgressBar>,
45
45
+
) -> super::sync::SyncData {
46
46
+
let mut ffprobe = std::process::Command::new("ffprobe")
47
47
+
.args(["-v", "error"])
48
48
+
.args(["-i", &self.path.to_string_lossy()])
49
49
+
.args(["-output_format", "json"])
50
50
+
.arg("-show_chapters")
51
51
+
.stdout(Stdio::piped())
52
52
+
.spawn()
53
53
+
.expect(&format!(
54
54
+
"Couldn't run ffprobe to get chapters of {:?}",
55
55
+
self.path
56
56
+
));
57
57
+
58
58
+
let mut raw_output = String::new();
59
59
+
ffprobe
60
60
+
.stdout
61
61
+
.take()
62
62
+
.expect("Coudln't get stdout of ffprobe run")
63
63
+
.read_to_string(&mut raw_output)
64
64
+
.expect("Couldn't read ffprobe stdout");
65
65
+
66
66
+
let output: FFprobeOutput =
67
67
+
serde_json::from_str(&raw_output).expect("Invalid ffprobe output");
68
68
+
69
69
+
super::sync::SyncData {
70
70
+
stems: HashMap::new(),
71
71
+
bpm: None,
72
72
+
markers: output
73
73
+
.chapters
74
74
+
.iter()
75
75
+
.map(|ch| {
76
76
+
(
77
77
+
(ch.start_time.to_owned() * 1_000.0) as TimestampMS,
78
78
+
ch.tags.title.clone(),
79
79
+
)
80
80
+
})
81
81
+
.collect(),
82
82
+
}
83
83
+
}
84
84
+
}