Compare commits
	
		
			No commits in common. "f748b98ccc9e48f49bd7732552071f0db3bdee0a" and "6e2ba71f33a828d3dc6c66a0a942b329ecfef857" have entirely different histories.
		
	
	
		
			
				f748b98ccc
			
			...
			
				6e2ba71f33
			
		
	
		
					 6 changed files with 47 additions and 45 deletions
				
			
		|  | @ -49,7 +49,8 @@ async fn download_single_video( | |||
|     main: Option<ProgressBar>, | ||||
| ) -> Result<()> { | ||||
|     let pb = multi.add(ProgressBar::new(1)); | ||||
|     pb.set_style(ProgressStyle::with_template("{msg}\n{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})").unwrap() | ||||
|     pb.set_style(ProgressStyle::default_bar() | ||||
|         .template("{msg}\n{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})").unwrap() | ||||
|         .progress_chars("#>-")); | ||||
|     pb.set_message(format!("Fetching player data for {}", video_title)); | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,8 +12,8 @@ use crate::{ | |||
|     deobfuscate::Deobfuscator, | ||||
|     error::{DeobfError, Error, ExtractionError}, | ||||
|     model::{ | ||||
|         AudioCodec, AudioFormat, AudioStream, AudioTrack, ChannelId, QualityOrd, Subtitle, | ||||
|         VideoCodec, VideoFormat, VideoPlayer, VideoPlayerDetails, VideoStream, | ||||
|         AudioCodec, AudioFormat, AudioStream, AudioTrack, ChannelId, Subtitle, VideoCodec, | ||||
|         VideoFormat, VideoPlayer, VideoPlayerDetails, VideoStream, | ||||
|     }, | ||||
|     param::Language, | ||||
|     util, | ||||
|  | @ -244,9 +244,9 @@ impl MapResponse<VideoPlayer> for response::Player { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         video_streams.sort_by(QualityOrd::quality_cmp); | ||||
|         video_only_streams.sort_by(QualityOrd::quality_cmp); | ||||
|         audio_streams.sort_by(QualityOrd::quality_cmp); | ||||
|         video_streams.sort(); | ||||
|         video_only_streams.sort(); | ||||
|         audio_streams.sort(); | ||||
| 
 | ||||
|         let subtitles = self.captions.map_or(Vec::new(), |captions| { | ||||
|             captions | ||||
|  |  | |||
|  | @ -1,10 +1,10 @@ | |||
| //! YouTube audio/video downloader
 | ||||
| 
 | ||||
| use std::{borrow::Cow, cmp::Ordering, ffi::OsString, ops::Range, path::PathBuf, time::Duration}; | ||||
| use std::{borrow::Cow, cmp::Ordering, ffi::OsString, ops::Range, path::PathBuf}; | ||||
| 
 | ||||
| use fancy_regex::Regex; | ||||
| use futures::stream::{self, StreamExt}; | ||||
| use indicatif::{ProgressBar, ProgressStyle}; | ||||
| use indicatif::ProgressBar; | ||||
| use log::{debug, info}; | ||||
| use once_cell::sync::Lazy; | ||||
| use rand::Rng; | ||||
|  | @ -150,7 +150,7 @@ async fn download_single_file<P: Into<PathBuf>>( | |||
|     let mut file = fs::OpenOptions::new() | ||||
|         .append(true) | ||||
|         .create(true) | ||||
|         .open(&output_path_tmp) | ||||
|         .open(output_path_tmp.to_owned()) | ||||
|         .await?; | ||||
| 
 | ||||
|     if is_gvideo && size.is_some() { | ||||
|  | @ -159,7 +159,7 @@ async fn download_single_file<P: Into<PathBuf>>( | |||
|         download_chunks_by_header(http, &mut file, url, size, offset, pb).await?; | ||||
|     } | ||||
| 
 | ||||
|     fs::rename(&output_path_tmp, &output_path).await?; | ||||
|     fs::rename(output_path_tmp, output_path).await?; | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
|  | @ -391,13 +391,7 @@ pub async fn download_video( | |||
|             download_streams(&downloads, http, pb.clone()).await?; | ||||
| 
 | ||||
|             pb.set_message(format!("Converting {}", title)); | ||||
|             pb.set_style( | ||||
|                 ProgressStyle::with_template("{msg}\n{spinner:.green} [{elapsed_precise}]") | ||||
|                     .unwrap(), | ||||
|             ); | ||||
|             pb.enable_steady_tick(Duration::from_millis(100)); | ||||
|             convert_streams(&downloads, output_path, ffmpeg).await?; | ||||
|             pb.disable_steady_tick(); | ||||
| 
 | ||||
|             // Delete original files
 | ||||
|             stream::iter(&downloads) | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ mod paginator; | |||
| pub mod richtext; | ||||
| 
 | ||||
| pub use convert::FromYtItem; | ||||
| pub use ordering::QualityOrd; | ||||
| pub use paginator::Paginator; | ||||
| use serde_with::serde_as; | ||||
| 
 | ||||
|  | @ -192,7 +191,7 @@ pub struct VideoStream { | |||
| } | ||||
| 
 | ||||
| /// Audio stream
 | ||||
| #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] | ||||
| #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] | ||||
| #[non_exhaustive] | ||||
| pub struct AudioStream { | ||||
|     /// Audio stream URL
 | ||||
|  |  | |||
|  | @ -4,26 +4,30 @@ use crate::model::AudioCodec; | |||
| 
 | ||||
| use super::{AudioStream, VideoStream}; | ||||
| 
 | ||||
| pub trait QualityOrd { | ||||
|     fn quality_cmp(&self, other: &Self) -> Ordering; | ||||
| } | ||||
| 
 | ||||
| impl QualityOrd for VideoStream { | ||||
|     fn quality_cmp(&self, other: &Self) -> Ordering { | ||||
|         match (self.width * self.height).cmp(&(other.width * other.height)) { | ||||
|             Ordering::Less => Ordering::Less, | ||||
|             Ordering::Greater => Ordering::Greater, | ||||
|             Ordering::Equal => match self.codec.cmp(&other.codec) { | ||||
| impl PartialOrd for VideoStream { | ||||
|     fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | ||||
|         Some( | ||||
|             match (self.width * self.height).cmp(&(other.width * other.height)) { | ||||
|                 Ordering::Less => Ordering::Less, | ||||
|                 Ordering::Greater => Ordering::Greater, | ||||
|                 Ordering::Equal => self.average_bitrate.cmp(&other.average_bitrate), | ||||
|                 Ordering::Equal => match self.codec.cmp(&other.codec) { | ||||
|                     Ordering::Less => Ordering::Less, | ||||
|                     Ordering::Greater => Ordering::Greater, | ||||
|                     Ordering::Equal => self.average_bitrate.cmp(&other.average_bitrate), | ||||
|                 }, | ||||
|             }, | ||||
|         } | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl QualityOrd for AudioStream { | ||||
|     fn quality_cmp(&self, other: &Self) -> Ordering { | ||||
| impl Ord for VideoStream { | ||||
|     fn cmp(&self, other: &Self) -> Ordering { | ||||
|         self.partial_cmp(other).unwrap() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl PartialOrd for AudioStream { | ||||
|     fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | ||||
|         fn cmp_bitrate(s: &AudioStream) -> u32 { | ||||
|             match s.codec { | ||||
|                 // Opus is more efficient
 | ||||
|  | @ -32,6 +36,12 @@ impl QualityOrd for AudioStream { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         cmp_bitrate(self).cmp(&cmp_bitrate(other)) | ||||
|         Some(cmp_bitrate(self).cmp(&cmp_bitrate(other))) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Ord for AudioStream { | ||||
|     fn cmp(&self, other: &Self) -> Ordering { | ||||
|         self.partial_cmp(other).unwrap() | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,10 +1,9 @@ | |||
| //! Filters for selecting audio/video streams
 | ||||
| 
 | ||||
| use std::{cmp::Ordering, collections::HashSet}; | ||||
| use std::collections::HashSet; | ||||
| 
 | ||||
| use crate::model::{ | ||||
|     AudioCodec, AudioFormat, AudioStream, QualityOrd, VideoCodec, VideoFormat, VideoPlayer, | ||||
|     VideoStream, | ||||
|     AudioCodec, AudioFormat, AudioStream, VideoCodec, VideoFormat, VideoPlayer, VideoStream, | ||||
| }; | ||||
| 
 | ||||
| #[derive(Debug, Default, Clone)] | ||||
|  | @ -303,15 +302,14 @@ impl VideoPlayer { | |||
|                 (Some(video_only_stream), self.select_audio_stream(filter)) | ||||
|             } | ||||
|             (Some(video_stream), None) => (Some(video_stream), None), | ||||
|             (Some(video_stream), Some(video_only_stream)) => { | ||||
|                 match video_only_stream.quality_cmp(video_stream) { | ||||
|                     Ordering::Greater => match self.select_audio_stream(filter) { | ||||
|                         Some(audio_stream) => (Some(video_only_stream), Some(audio_stream)), | ||||
|                         None => (Some(video_stream), None), | ||||
|                     }, | ||||
|                     _ => (Some(video_stream), None), | ||||
|                 } | ||||
|             } | ||||
|             (Some(video_stream), Some(video_only_stream)) => match video_only_stream > video_stream | ||||
|             { | ||||
|                 true => match self.select_audio_stream(filter) { | ||||
|                     Some(audio_stream) => (Some(video_only_stream), Some(audio_stream)), | ||||
|                     None => (Some(video_stream), None), | ||||
|                 }, | ||||
|                 false => (Some(video_stream), None), | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue