Compare commits

...

2 commits

Author SHA1 Message Date
f748b98ccc fix: error with clippy 1.65 2022-11-04 19:59:41 +01:00
a706eb172e fix: stream ordering, downloader progress bar 2022-11-04 19:45:58 +01:00
6 changed files with 45 additions and 47 deletions

View file

@ -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));

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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))
}
}

View file

@ -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),
}
}
}
}
}