aboutsummaryrefslogtreecommitdiff
path: root/tools/src/bin/gen_meta.rs
blob: b09f4a1e8fb9544ed756c7eb88c86c8f52c8a454 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use anyhow::{anyhow, bail};
use clap::Parser;
use jellycommon::{ItemInfo, Source, SourceTrack};
use std::{collections::BTreeMap, fs::File, io::Write, path::PathBuf};
use webm_iterable::{
    matroska_spec::{Master, MatroskaSpec},
    WebmIterator,
};

#[derive(Parser)]
struct Args {
    #[clap(short = 'I', long)]
    identifier: String,
    #[clap(short = 'O', long)]
    write_json: bool,
    #[clap(short, long)]
    title: String,
    #[clap(short = 'i', long)]
    inputs: Vec<PathBuf>,
}

fn main() -> anyhow::Result<()> {
    let args = Args::parse();

    let mut source = vec![];
    for fname in args.inputs {
        let mut tracks = BTreeMap::new();
        let mut input = File::open(fname.clone()).unwrap();
        for tag in WebmIterator::new(&mut input, &[MatroskaSpec::TrackEntry(Master::Start)]) {
            let tag = tag?;
            match tag {
                MatroskaSpec::TrackEntry(master) => {
                    let (
                        mut index,
                        mut language,
                        mut codec,
                        mut kind,
                        mut sample_rate,
                        mut channels,
                        mut width,
                        mut height,
                    ) = (None, None, None, None, None, None, None, None);
                    for c in master.get_children() {
                        match c {
                            MatroskaSpec::CodecID(b) => codec = Some(b),
                            MatroskaSpec::Language(v) => language = Some(v),
                            MatroskaSpec::TrackNumber(v) => index = Some(v),
                            MatroskaSpec::TrackType(v) => kind = Some(v),
                            MatroskaSpec::Audio(master) => {
                                for c in master.get_children() {
                                    match c {
                                        MatroskaSpec::Channels(v) => channels = Some(v as usize),
                                        MatroskaSpec::SamplingFrequency(v) => sample_rate = Some(v),
                                        _ => (),
                                    }
                                }
                            }
                            MatroskaSpec::Video(master) => {
                                for c in master.get_children() {
                                    match c {
                                        MatroskaSpec::PixelWidth(v) => width = Some(v as usize),
                                        MatroskaSpec::PixelHeight(v) => height = Some(v as usize),
                                        _ => (),
                                    }
                                }
                            }
                            _ => (),
                        }
                    }
                    tracks.insert(
                        index.unwrap(),
                        match kind.ok_or(anyhow!("track type required"))? {
                            1 => SourceTrack::Video {
                                language: language.unwrap(),
                                codec: codec.unwrap(),
                                width: width.unwrap(),
                                height: height.unwrap(),
                            },
                            2 => SourceTrack::Audio {
                                channels: channels.unwrap(),
                                codec: codec.unwrap(),
                                sample_rate: sample_rate.unwrap(),
                                language: language.unwrap(),
                            },
                            _ => bail!("invalid track type"),
                        },
                    );
                }
                MatroskaSpec::Tags(Master::End) => break,
                _ => (),
            }
        }
        source.push(Source {
            file: fname.clone(),
            tracks,
        })
    }

    let k = serde_json::to_string_pretty(&ItemInfo {
        title: args.title,
        source,
    })?;

    if args.write_json {
        let mut f = File::create(format!("{}.json", args.identifier))?;
        f.write_all(k.as_bytes())?;
    } else {
        println!("{k}")
    }

    Ok(())
}