Compare commits
2 commits
6e2ba71f33
...
f748b98ccc
Author | SHA1 | Date | |
---|---|---|---|
f748b98ccc | |||
a706eb172e |
6 changed files with 45 additions and 47 deletions
|
@ -49,8 +49,7 @@ async fn download_single_video(
|
|||
main: Option<ProgressBar>,
|
||||
) -> Result<()> {
|
||||
let pb = multi.add(ProgressBar::new(1));
|
||||
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()
|
||||
pb.set_style(ProgressStyle::with_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, Subtitle, VideoCodec,
|
||||
VideoFormat, VideoPlayer, VideoPlayerDetails, VideoStream,
|
||||
AudioCodec, AudioFormat, AudioStream, AudioTrack, ChannelId, QualityOrd, Subtitle,
|
||||
VideoCodec, VideoFormat, VideoPlayer, VideoPlayerDetails, VideoStream,
|
||||
},
|
||||
param::Language,
|
||||
util,
|
||||
|
@ -244,9 +244,9 @@ impl MapResponse<VideoPlayer> for response::Player {
|
|||
}
|
||||
}
|
||||
|
||||
video_streams.sort();
|
||||
video_only_streams.sort();
|
||||
audio_streams.sort();
|
||||
video_streams.sort_by(QualityOrd::quality_cmp);
|
||||
video_only_streams.sort_by(QualityOrd::quality_cmp);
|
||||
audio_streams.sort_by(QualityOrd::quality_cmp);
|
||||
|
||||
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};
|
||||
use std::{borrow::Cow, cmp::Ordering, ffi::OsString, ops::Range, path::PathBuf, time::Duration};
|
||||
|
||||
use fancy_regex::Regex;
|
||||
use futures::stream::{self, StreamExt};
|
||||
use indicatif::ProgressBar;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
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.to_owned())
|
||||
.open(&output_path_tmp)
|
||||
.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,7 +391,13 @@ 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,6 +6,7 @@ mod paginator;
|
|||
pub mod richtext;
|
||||
|
||||
pub use convert::FromYtItem;
|
||||
pub use ordering::QualityOrd;
|
||||
pub use paginator::Paginator;
|
||||
use serde_with::serde_as;
|
||||
|
||||
|
@ -191,7 +192,7 @@ pub struct VideoStream {
|
|||
}
|
||||
|
||||
/// Audio stream
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
pub struct AudioStream {
|
||||
/// Audio stream URL
|
||||
|
|
|
@ -4,30 +4,26 @@ use crate::model::AudioCodec;
|
|||
|
||||
use super::{AudioStream, VideoStream};
|
||||
|
||||
impl PartialOrd for VideoStream {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(
|
||||
match (self.width * self.height).cmp(&(other.width * other.height)) {
|
||||
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) {
|
||||
Ordering::Less => Ordering::Less,
|
||||
Ordering::Greater => Ordering::Greater,
|
||||
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),
|
||||
},
|
||||
Ordering::Equal => self.average_bitrate.cmp(&other.average_bitrate),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
impl QualityOrd for AudioStream {
|
||||
fn quality_cmp(&self, other: &Self) -> Ordering {
|
||||
fn cmp_bitrate(s: &AudioStream) -> u32 {
|
||||
match s.codec {
|
||||
// Opus is more efficient
|
||||
|
@ -36,12 +32,6 @@ impl PartialOrd for AudioStream {
|
|||
}
|
||||
}
|
||||
|
||||
Some(cmp_bitrate(self).cmp(&cmp_bitrate(other)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for AudioStream {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
cmp_bitrate(self).cmp(&cmp_bitrate(other))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
//! Filters for selecting audio/video streams
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::{cmp::Ordering, collections::HashSet};
|
||||
|
||||
use crate::model::{
|
||||
AudioCodec, AudioFormat, AudioStream, VideoCodec, VideoFormat, VideoPlayer, VideoStream,
|
||||
AudioCodec, AudioFormat, AudioStream, QualityOrd, VideoCodec, VideoFormat, VideoPlayer,
|
||||
VideoStream,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
@ -302,14 +303,15 @@ 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 > 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),
|
||||
},
|
||||
(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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue