aboutsummaryrefslogtreecommitdiff
path: root/tools/src/bin/gen_meta.rs
blob: e7aa559c397d530b4f03a983b1d03e8dfa3b4f12 (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
113
114
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)]
    input: PathBuf,
}

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

    let mut tracks = BTreeMap::new();
    let mut input = File::open(args.input.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,
                    mut name,
                ) = (None, 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),
                                    MatroskaSpec::PixelHeight(v) => height = Some(v),
                                    _ => (),
                                }
                            }
                        }
                        MatroskaSpec::Name(v) => name = Some(v),
                        _ => (),
                    }
                }
                tracks.insert(
                    index.unwrap(),
                    match kind.ok_or(anyhow!("track type required"))? {
                        1 => SourceTrack::Video {
                            language: language.unwrap_or("none".to_string()),
                            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(),
                        },
                        17 => SourceTrack::Subtitles {
                            language: name.unwrap(),
                            codec: codec.unwrap(),
                        },
                        _ => bail!("invalid track type"),
                    },
                );
            }
            MatroskaSpec::Tags(Master::End) => break,
            _ => (),
        }
    }

    let k = serde_json::to_string_pretty(&ItemInfo {
        title: args.title,
        source: Source {
            path: args.input.clone(),
            tracks,
        },
    })?;

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

    Ok(())
}