1use serde::Deserialize;
2
3#[derive(Debug, Clone, Deserialize)]
4pub struct VideoMetadataResponse {
5 pub player_response: String
6}
7
8#[derive(Debug, Clone, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct VideoMetadata {
11 pub response_context: ResponseContext,
12 pub playability_status: PlayabilityStatus,
13 pub streaming_data: Option<StreamingData>,
14 pub playback_tracking: Option<PlaybackTracking>,
15 pub video_details: VideoDetails,
16 #[serde(default)]
17 pub annotations: Vec<Annotation>,
18 pub player_config: Option<PlayerConfig>,
19 pub storyboards: Option<Storyboards>,
20 pub microformat: Microformat,
21 pub tracking_params: String,
22 pub attestation: Option<Attestation>,
23 #[serde(default)]
24 pub messages: Vec<Message>,
25 pub endscreen: Option<Endscreen>,
26}
27
28#[derive(Debug, Clone, Deserialize)]
29#[serde(rename_all = "camelCase")]
30pub struct Annotation {
31 pub player_annotations_expanded_renderer: Option<PlayerAnnotationsExpandedRenderer>,
32}
33
34#[derive(Debug, Clone, Deserialize)]
35#[serde(rename_all = "camelCase")]
36pub struct PlayerAnnotationsExpandedRenderer {
37 pub featured_channel: FeaturedChannel,
38 pub allow_swipe_dismiss: bool,
39 pub annotation_id: String,
40}
41
42#[derive(Debug, Clone, Deserialize)]
43#[serde(rename_all = "camelCase")]
44pub struct FeaturedChannel {
45 pub start_time_ms: String,
46 pub end_time_ms: String,
47 pub watermark: WatermarkClass,
48 pub tracking_params: String,
49 pub navigation_endpoint: FeaturedChannelNavigationEndpoint,
50 pub channel_name: String,
51 pub subscribe_button: SubscribeButtonClass,
52}
53
54#[derive(Debug, Clone, Deserialize)]
55#[serde(rename_all = "camelCase")]
56pub struct FeaturedChannelNavigationEndpoint {
57 pub click_tracking_params: String,
58 pub browse_endpoint: BrowseEndpoint,
59}
60
61#[derive(Debug, Clone, Deserialize)]
62#[serde(rename_all = "camelCase")]
63pub struct BrowseEndpoint {
64 pub browse_id: String,
65}
66
67#[derive(Debug, Clone, Deserialize)]
68#[serde(rename_all = "camelCase")]
69pub struct SubscribeButtonClass {
70 pub subscribe_button_renderer: SubscribeButtonRenderer,
71}
72
73#[derive(Debug, Clone, Deserialize)]
74#[serde(rename_all = "camelCase")]
75pub struct SubscribeButtonRenderer {
76 pub button_text: MessageTitle,
77 pub subscribed: bool,
78 pub enabled: bool,
79 #[serde(rename = "type")]
80 pub subscribe_button_renderer_type: String,
81 pub channel_id: String,
82 pub show_preferences: bool,
83 pub subscribed_button_text: MessageTitle,
84 pub unsubscribed_button_text: MessageTitle,
85 pub tracking_params: String,
86 pub unsubscribe_button_text: MessageTitle,
87 pub service_endpoints: Vec<ServiceEndpoint>,
88 pub sign_in_endpoint: Option<SigninEndpoint>,
89}
90
91#[derive(Debug, Clone, Deserialize)]
92pub struct MessageTitle {
93 pub runs: Vec<Run>,
94}
95
96#[derive(Debug, Clone, Deserialize)]
97pub struct Run {
98 pub text: String,
99}
100
101#[derive(Debug, Clone, Deserialize)]
102#[serde(rename_all = "camelCase")]
103pub struct ServiceEndpoint {
104 pub click_tracking_params: String,
105 pub subscribe_endpoint: Option<SubscribeEndpoint>,
106 pub unsubscribe_endpoint: Option<SubscribeEndpoint>,
107}
108
109#[derive(Debug, Clone, Deserialize)]
110#[serde(rename_all = "camelCase")]
111pub struct SubscribeEndpoint {
112 pub channel_ids: Vec<String>,
113 pub params: String,
114}
115
116#[derive(Debug, Clone, Deserialize)]
117#[serde(rename_all = "camelCase")]
118pub struct SigninEndpoint {
119 pub click_tracking_params: String,
120 pub web_navigation_endpoint_data: Option<WebNavigationEndpointData>,
121}
122
123#[derive(Debug, Clone, Deserialize)]
124pub struct WebNavigationEndpointData {
125 pub url: String,
126}
127
128#[derive(Debug, Clone, Deserialize)]
129pub struct WatermarkClass {
130 pub thumbnails: Vec<ThumbnailElement>,
131}
132
133#[derive(Debug, Clone, Deserialize)]
134pub struct ThumbnailElement {
135 pub url: String,
136 pub width: i64,
137 pub height: i64,
138}
139
140#[derive(Debug, Clone, Deserialize)]
141#[serde(rename_all = "camelCase")]
142pub struct Attestation {
143 pub player_attestation_renderer: PlayerAttestationRenderer,
144}
145
146#[derive(Debug, Clone, Deserialize)]
147#[serde(rename_all = "camelCase")]
148pub struct PlayerAttestationRenderer {
149 pub challenge: String,
150 pub botguard_data: BotguardData,
151}
152
153#[derive(Debug, Clone, Deserialize)]
154#[serde(rename_all = "camelCase")]
155pub struct BotguardData {
156 pub program: String,
157 pub interpreter_url: String,
158}
159
160#[derive(Debug, Clone, Deserialize)]
161#[serde(rename_all = "camelCase")]
162pub struct Endscreen {
163 pub endscreen_renderer: EndscreenRenderer,
164}
165
166#[derive(Debug, Clone, Deserialize)]
167#[serde(rename_all = "camelCase")]
168pub struct EndscreenRenderer {
169 pub elements: Vec<Element>,
170 pub start_ms: String,
171 pub tracking_params: String,
172}
173
174#[derive(Debug, Clone, Deserialize)]
175#[serde(rename_all = "camelCase")]
176pub struct Element {
177 pub endscreen_element_renderer: EndscreenElementRenderer,
178}
179
180#[derive(Debug, Clone, Deserialize)]
181#[serde(rename_all = "camelCase")]
182pub struct EndscreenElementRenderer {
183 pub style: EndcardStyle,
184 pub image: WatermarkClass,
185 pub icon: Option<Icon>,
186 pub left: f64,
187 pub width: f64,
188 pub top: f64,
189 pub aspect_ratio: f64,
190 pub start_ms: String,
191 pub end_ms: String,
192 pub title: Title,
193 pub metadata: Description,
194 pub call_to_action: Option<Description>,
195 pub dismiss: Option<Description>,
196 pub endpoint: Endpoint,
197 pub hovercard_button: Option<SubscribeButtonClass>,
198 pub tracking_params: String,
199 pub is_subscribe: Option<bool>,
200 pub signin_endpoint: Option<SigninEndpoint>,
201 pub use_classic_subscribe_button: Option<bool>,
202 pub id: String,
203 pub video_duration: Option<Description>,
204 pub playlist_length: Option<Description>,
205}
206
207#[derive(Debug, Clone, Deserialize)]
208#[serde(rename_all = "UPPERCASE")]
209pub enum EndcardStyle {
210 Channel,
211 Video,
212 Playlist,
213 Website
214}
215
216#[derive(Debug, Clone, Deserialize)]
217#[serde(rename_all = "camelCase")]
218pub struct Description {
219 pub simple_text: String,
220}
221
222#[derive(Debug, Clone, Deserialize)]
223#[serde(rename_all = "camelCase")]
224pub struct Endpoint {
225 pub click_tracking_params: String,
226 pub browse_endpoint: Option<BrowseEndpoint>,
227 pub watch_endpoint: Option<WatchEndpoint>,
228}
229
230#[derive(Debug, Clone, Deserialize)]
231#[serde(rename_all = "camelCase")]
232pub struct WatchEndpoint {
233 pub video_id: String,
234 pub playlist_id: Option<String>,
235}
236
237#[derive(Debug, Clone, Deserialize)]
238pub struct Icon {
239 pub thumbnails: Vec<WebNavigationEndpointData>,
240}
241
242#[derive(Debug, Clone, Deserialize)]
243#[serde(rename_all = "camelCase")]
244pub struct Title {
245 pub accessibility: Accessibility,
246 pub simple_text: String,
247}
248
249#[derive(Debug, Clone, Deserialize)]
250#[serde(rename_all = "camelCase")]
251pub struct Accessibility {
252 pub accessibility_data: AccessibilityData,
253}
254
255#[derive(Debug, Clone, Deserialize)]
256pub struct AccessibilityData {
257 pub label: String,
258}
259
260#[derive(Debug, Clone, Deserialize)]
261#[serde(rename_all = "camelCase")]
262pub struct Message {
263 pub mealbar_promo_renderer: MealbarPromoRenderer,
264}
265
266#[derive(Debug, Clone, Deserialize)]
267#[serde(rename_all = "camelCase")]
268pub struct MealbarPromoRenderer {
269 pub message_texts: Vec<MessageTitle>,
270 pub action_button: ActionButtonClass,
271 pub dismiss_button: ActionButtonClass,
272 pub trigger_condition: String,
273 pub style: String,
274 pub tracking_params: String,
275 pub impression_endpoints: Vec<ImpressionEndpointElement>,
276 pub is_visible: bool,
277 pub message_title: MessageTitle,
278}
279
280#[derive(Debug, Clone, Deserialize)]
281#[serde(rename_all = "camelCase")]
282pub struct ActionButtonClass {
283 pub button_renderer: ButtonRenderer,
284}
285
286#[derive(Debug, Clone, Deserialize)]
287#[serde(rename_all = "camelCase")]
288pub struct ButtonRenderer {
289 pub style: String,
290 pub size: String,
291 pub text: MessageTitle,
292 pub service_endpoint: ImpressionEndpointElement,
293 pub navigation_endpoint: Option<ButtonRendererNavigationEndpoint>,
294 pub tracking_params: String,
295}
296
297#[derive(Debug, Clone, Deserialize)]
298#[serde(rename_all = "camelCase")]
299pub struct ButtonRendererNavigationEndpoint {
300 pub click_tracking_params: String,
301 pub url_endpoint: Option<UrlEndpoint>,
302}
303
304#[derive(Debug, Clone, Deserialize)]
305pub struct UrlEndpoint {
306 pub url: String,
307 pub target: String,
308}
309
310#[derive(Debug, Clone, Deserialize)]
311#[serde(rename_all = "camelCase")]
312pub struct ImpressionEndpointElement {
313 pub click_tracking_params: String,
314 pub feedback_endpoint: FeedbackEndpoint,
315}
316
317#[derive(Debug, Clone, Deserialize)]
318#[serde(rename_all = "camelCase")]
319pub struct FeedbackEndpoint {
320 pub feedback_token: String,
321 pub ui_actions: UiActions,
322}
323
324#[derive(Debug, Clone, Deserialize)]
325#[serde(rename_all = "camelCase")]
326pub struct UiActions {
327 pub hide_enclosing_container: bool,
328}
329
330#[derive(Debug, Clone, Deserialize)]
331#[serde(rename_all = "camelCase")]
332pub struct Microformat {
333 pub player_microformat_renderer: PlayerMicroformatRenderer,
334}
335
336#[derive(Debug, Clone, Deserialize)]
337#[serde(rename_all = "camelCase")]
338pub struct PlayerMicroformatRenderer {
339 pub thumbnail: WatermarkClass,
340 pub embed: Embed,
341 pub title: Description,
342 pub description: Option<Description>,
343 pub length_seconds: String,
344 pub owner_profile_url: String,
345 pub external_channel_id: String,
346 pub available_countries: Vec<String>,
347 pub is_unlisted: bool,
348 pub has_ypc_metadata: bool,
349 pub view_count: String,
350 pub category: String,
351 pub publish_date: String,
352 pub owner_channel_name: String,
353 pub upload_date: String,
354}
355
356#[derive(Debug, Clone, Deserialize)]
357#[serde(rename_all = "camelCase")]
358pub struct Embed {
359 pub iframe_url: String,
360 pub flash_url: String,
361 pub width: i64,
362 pub height: i64,
363 pub flash_secure_url: String,
364}
365
366#[derive(Debug, Clone, Deserialize)]
367#[serde(rename_all = "camelCase")]
368pub struct PlayabilityStatus {
369 pub status: PlaybackStatus,
370 #[serde(default)]
371 pub playable_in_embed: bool,
372 pub context_params: String,
373}
374
375#[derive(Debug, Clone, Deserialize)]
376#[serde(rename_all = "UPPERCASE")]
377pub enum PlaybackStatus {
378 Ok,
379 Unplayable
380}
381
382#[derive(Debug, Clone, Deserialize)]
383#[serde(rename_all = "camelCase")]
384pub struct PlaybackTracking {
385 pub videostats_playback_url: PtrackingUrlClass,
386 pub videostats_delayplay_url: PtrackingUrlClass,
387 pub videostats_watchtime_url: PtrackingUrlClass,
388 pub ptracking_url: PtrackingUrlClass,
389 pub qoe_url: PtrackingUrlClass,
390 pub set_awesome_url: AtrUrlClass,
391 pub atr_url: AtrUrlClass,
392 pub youtube_remarketing_url: Option<AtrUrlClass>,
393 pub google_remarketing_url: Option<AtrUrlClass>,
394}
395
396#[derive(Debug, Clone, Deserialize)]
397#[serde(rename_all = "camelCase")]
398pub struct AtrUrlClass {
399 pub base_url: String,
400 pub elapsed_media_time_seconds: i64,
401}
402
403#[derive(Debug, Clone, Deserialize)]
404#[serde(rename_all = "camelCase")]
405pub struct PtrackingUrlClass {
406 pub base_url: String,
407}
408
409#[derive(Debug, Clone, Deserialize)]
410#[serde(rename_all = "camelCase")]
411pub struct PlayerConfig {
412 pub audio_config: AudioConfig,
413 pub stream_selection_config: Option<StreamSelectionConfig>,
414 pub media_common_config: MediaCommonConfig,
415 pub web_player_config: WebPlayerConfig,
416}
417
418#[derive(Debug, Clone, Deserialize)]
419#[serde(rename_all = "camelCase")]
420pub struct AudioConfig {
421 pub loudness_db: Option<f64>,
422 pub perceptual_loudness_db: Option<f64>,
423 pub enable_per_format_loudness: bool,
424}
425
426#[derive(Debug, Clone, Deserialize)]
427#[serde(rename_all = "camelCase")]
428pub struct MediaCommonConfig {
429 pub dynamic_readahead_config: DynamicReadaheadConfig,
430}
431
432#[derive(Debug, Clone, Deserialize)]
433#[serde(rename_all = "camelCase")]
434pub struct DynamicReadaheadConfig {
435 pub max_read_ahead_media_time_ms: i64,
436 pub min_read_ahead_media_time_ms: i64,
437 pub read_ahead_growth_rate_ms: i64,
438}
439
440#[derive(Debug, Clone, Deserialize)]
441#[serde(rename_all = "camelCase")]
442pub struct StreamSelectionConfig {
443 pub max_bitrate: String,
444}
445
446#[derive(Debug, Clone, Deserialize)]
447#[serde(rename_all = "camelCase")]
448pub struct WebPlayerConfig {
449 pub web_player_actions_porting: WebPlayerActionsPorting,
450}
451
452#[derive(Debug, Clone, Deserialize)]
453#[serde(rename_all = "camelCase")]
454pub struct WebPlayerActionsPorting {
455 pub get_share_panel_command: GetSharePanelCommand,
456 pub subscribe_command: SubscribeCommand,
457 pub unsubscribe_command: UnsubscribeCommand,
458 pub add_to_watch_later_command: AddToWatchLaterCommand,
459 pub remove_from_watch_later_command: RemoveFromWatchLaterCommand,
460}
461
462#[derive(Debug, Clone, Deserialize)]
463#[serde(rename_all = "camelCase")]
464pub struct AddToWatchLaterCommand {
465 pub click_tracking_params: String,
466 pub playlist_edit_endpoint: AddToWatchLaterCommandPlaylistEditEndpoint,
467}
468
469#[derive(Debug, Clone, Deserialize)]
470#[serde(rename_all = "camelCase")]
471pub struct AddToWatchLaterCommandPlaylistEditEndpoint {
472 pub playlist_id: String,
473 pub actions: Vec<PurpleAction>,
474}
475
476#[derive(Debug, Clone, Deserialize)]
477#[serde(rename_all = "camelCase")]
478pub struct PurpleAction {
479 pub added_video_id: String,
480 pub action: String,
481}
482
483#[derive(Debug, Clone, Deserialize)]
484#[serde(rename_all = "camelCase")]
485pub struct GetSharePanelCommand {
486 pub click_tracking_params: String,
487 pub web_player_share_entity_service_endpoint: WebPlayerShareEntityServiceEndpoint,
488}
489
490#[derive(Debug, Clone, Deserialize)]
491#[serde(rename_all = "camelCase")]
492pub struct WebPlayerShareEntityServiceEndpoint {
493 pub serialized_share_entity: String,
494}
495
496#[derive(Debug, Clone, Deserialize)]
497#[serde(rename_all = "camelCase")]
498pub struct RemoveFromWatchLaterCommand {
499 pub click_tracking_params: String,
500 pub playlist_edit_endpoint: RemoveFromWatchLaterCommandPlaylistEditEndpoint,
501}
502
503#[derive(Debug, Clone, Deserialize)]
504#[serde(rename_all = "camelCase")]
505pub struct RemoveFromWatchLaterCommandPlaylistEditEndpoint {
506 pub playlist_id: String,
507 pub actions: Vec<FluffyAction>,
508}
509
510#[derive(Debug, Clone, Deserialize)]
511#[serde(rename_all = "camelCase")]
512pub struct FluffyAction {
513 pub action: String,
514 pub removed_video_id: String,
515}
516
517#[derive(Debug, Clone, Deserialize)]
518#[serde(rename_all = "camelCase")]
519pub struct SubscribeCommand {
520 pub click_tracking_params: String,
521 pub subscribe_endpoint: SubscribeEndpoint,
522}
523
524#[derive(Debug, Clone, Deserialize)]
525#[serde(rename_all = "camelCase")]
526pub struct UnsubscribeCommand {
527 pub click_tracking_params: String,
528 pub unsubscribe_endpoint: SubscribeEndpoint,
529}
530
531#[derive(Debug, Clone, Deserialize)]
532#[serde(rename_all = "camelCase")]
533pub struct ResponseContext {
534 pub service_tracking_params: Vec<ServiceTrackingParam>,
535}
536
537#[derive(Debug, Clone, Deserialize)]
538pub struct ServiceTrackingParam {
539 pub service: String,
540 pub params: Vec<Param>,
541}
542
543#[derive(Debug, Clone, Deserialize)]
544pub struct Param {
545 pub key: String,
546 pub value: String,
547}
548
549#[derive(Debug, Clone, Deserialize)]
550#[serde(rename_all = "camelCase")]
551pub struct Storyboards {
552 pub player_storyboard_spec_renderer: PlayerStoryboardSpecRenderer,
553}
554
555#[derive(Debug, Clone, Deserialize)]
556pub struct PlayerStoryboardSpecRenderer {
557 pub spec: String,
558}
559
560#[derive(Debug, Clone, Deserialize)]
561#[serde(rename_all = "camelCase")]
562pub struct StreamingData {
563 pub expires_in_seconds: String,
564 pub formats: Vec<Format>,
565 pub adaptive_formats: Vec<Format>,
566 pub probe_url: Option<String>,
567}
568
569#[derive(Debug, Clone, Deserialize)]
570#[serde(rename_all = "camelCase")]
571pub struct Format {
572 pub itag: i64,
573 pub mime_type: String,
574 pub bitrate: i64,
575 pub width: Option<i64>,
576 pub height: Option<i64>,
577 pub init_range: Option<Range>,
578 pub index_range: Option<Range>,
579 pub last_modified: String,
580 pub content_length: Option<String>,
581 pub quality: String,
582 pub fps: Option<i64>,
583 pub quality_label: Option<String>,
584 pub projection_type: ProjectionType,
585 pub average_bitrate: Option<i64>,
586 pub approx_duration_ms: Option<String>,
587 pub cipher: Option<String>,
588 pub color_info: Option<ColorInfo>,
589 pub high_replication: Option<bool>,
590 pub audio_quality: Option<String>,
591 pub audio_sample_rate: Option<String>,
592 pub audio_channels: Option<i64>,
593}
594
595#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
596#[serde(rename_all = "lowercase")]
597pub enum VideoQuality {
598 Small,
599 Medium,
600 Large
601}
602
603#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
604pub enum AudioQuality {
605 #[serde(rename = "AUDIO_QUALITY_LOW")]
606 Low,
607 #[serde(rename = "AUDIO_QUALITY_MEDIUM")]
608 Medium
609}
610
611#[derive(Debug, Clone, Deserialize)]
612#[serde(rename_all = "camelCase")]
613pub struct ColorInfo {
614 pub primaries: String,
615 pub transfer_characteristics: String,
616 pub matrix_coefficients: String,
617}
618
619#[derive(Debug, Clone, Deserialize)]
620pub struct Range {
621 pub start: String,
622 pub end: String,
623}
624
625#[derive(Debug, Clone, Deserialize)]
626#[serde(rename_all = "camelCase")]
627pub struct VideoDetails {
628 pub video_id: String,
629 pub title: String,
630 pub length_seconds: String,
631 #[serde(default)]
632 pub keywords: Vec<String>,
633 pub channel_id: String,
634 pub is_owner_viewing: bool,
635 pub short_description: String,
636 pub is_crawlable: bool,
637 pub thumbnail: WatermarkClass,
638 pub average_rating: f64,
639 pub allow_ratings: bool,
640 pub view_count: String,
641 pub author: String,
642 pub is_private: bool,
643 pub is_unplugged_corpus: bool,
644 pub is_live_content: bool,
645}
646
647#[derive(Debug, Clone, Deserialize)]
648#[serde(rename_all = "UPPERCASE")]
649pub enum ProjectionType {
650 Rectangular,
651}