yt_dlp/model/types/
caption.rs1use std::fmt;
4use std::hash::{Hash, Hasher};
5
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10pub struct AutomaticCaption {
11 #[serde(rename = "ext")]
13 pub extension: Extension,
14 pub url: String,
16 pub name: Option<String>,
18}
19
20#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
22#[serde(rename_all = "snake_case")]
23pub enum Extension {
24 Json,
26 Json3,
28 Srv1,
30 Srv2,
32 Srv3,
34 Ttml,
36 #[default]
38 Vtt,
39 Srt,
41 Ass,
43 Ssa,
45 #[serde(other)]
47 Unknown,
48}
49
50impl Extension {
51 pub fn as_str(&self) -> &'static str {
57 match self {
58 Extension::Json => "json",
59 Extension::Json3 => "json3",
60 Extension::Srv1 => "srv1",
61 Extension::Srv2 => "srv2",
62 Extension::Srv3 => "srv3",
63 Extension::Ttml => "ttml",
64 Extension::Vtt => "vtt",
65 Extension::Srt => "srt",
66 Extension::Ass => "ass",
67 Extension::Ssa => "ssa",
68 Extension::Unknown => "unknown",
69 }
70 }
71}
72
73impl fmt::Display for AutomaticCaption {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(
76 f,
77 "AutomaticCaption(lang={}, ext={:?})",
78 self.name.as_deref().unwrap_or("unknown"),
79 self.extension
80 )
81 }
82}
83
84impl Hash for AutomaticCaption {
85 fn hash<H: Hasher>(&self, state: &mut H) {
86 self.url.hash(state);
87 self.name.hash(state);
88 std::mem::discriminant(&self.extension).hash(state);
89 }
90}
91
92impl fmt::Display for Extension {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 f.write_str(self.as_str())
95 }
96}
97
98impl Eq for Extension {}
100
101impl Hash for Extension {
103 fn hash<H: Hasher>(&self, state: &mut H) {
104 std::mem::discriminant(self).hash(state);
105 }
106}
107
108#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
110pub struct Subtitle {
111 pub language_code: Option<String>,
113 pub language_name: Option<String>,
115 pub url: String,
117 #[serde(rename = "ext")]
119 pub extension: Extension,
120 #[serde(default)]
122 pub is_automatic: bool,
123}
124
125impl Subtitle {
126 pub fn from_automatic_caption(caption: &AutomaticCaption, language_code: String) -> Self {
137 Self {
138 language_code: Some(language_code),
139 language_name: caption.name.clone(),
140 url: caption.url.clone(),
141 extension: caption.extension.clone(),
142 is_automatic: true,
143 }
144 }
145
146 pub fn is_format(&self, format: &Extension) -> bool {
156 &self.extension == format
157 }
158
159 pub fn file_extension(&self) -> &str {
165 self.extension.as_str()
166 }
167}
168
169impl fmt::Display for Subtitle {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 write!(
173 f,
174 "Subtitle(lang={}, format={}, auto={})",
175 self.language_name
176 .as_deref()
177 .or(self.language_code.as_deref())
178 .unwrap_or("unknown"),
179 self.file_extension(),
180 self.is_automatic
181 )
182 }
183}
184
185impl Hash for Subtitle {
187 fn hash<H: Hasher>(&self, state: &mut H) {
188 self.language_code.hash(state);
189 self.url.hash(state);
190 std::mem::discriminant(&self.extension).hash(state);
191 }
192}