I am just learning streams and async rust so this might be a stupid mistake in my code. So I am trying to use rustube to download a youtube video , as a fail safe if the asset (video) is not there. However..
- When I use video.download(...) on the main thread the progress gets stuck at 100%. and I use
progress_bar.finish_with_message("Finished downloading asset!")
to tell that the video is finished downloading but it gets stuck at 100% but doesn't show message even after an hour. - When I use the same code on a new thread using
tokio::spawn
andtokio::join!
,progress bar goes till 100% and displays message"Finished downloading asset!"
. But after that it deletes the .webm that it has created. This leaves with no file downloaded. And no , I don't delete the file after download.
This is my Cargo.toml
[dependencies]
#....
# For progress bar
indicatif = "0.17.6"
# For downloading neccessary youtube videos
rustube = { version = "0.6.0" , features = ["callback"]}
And my main.rs
#[tokio::main]
async fn main() {
assets::download_background_videos().await;
}
Where my asset.rs
is
use tokio::{
spawn,
try_join
};
use indicatif::{ProgressBar,ProgressStyle};
use rustube::{
Video,
Id,
Callback,
};
use crate::AssetsError;
const VIDEOS_DIR : &str = "assets/videos";
pub(in crate) async fn download_background_videos() -> Result<(),AssetsError> {
// just prints checking assets and if assets is already present
// Using main thread (1.)
check_download_vid_with_id("Pt5_GSKIWQM").await?;
// And the one using new thread (2.)
let mc = spawn(check_download_vid_with_id("Pt5_GSKIWQM"));
try_join!(mc)
// prints Finished checking for assets!
Ok(())
}
// Function that rly downloads stuff
async fn check_download_vid_with_id(id : &str) -> Result<(),AssetsError> {
let _dir = format!("{VIDEOS_DIR}/{id}.mp4");
let path = Path::new(&_dir);
match path.exists() {
true => Ok(()),
false => {
let _id = Id::from_str(id).unwrap();
let _video = Video::from_id(_id.into_owned()).await.unwrap();
match _video.best_video() {
None => Err(AssetsError::VideoStreamUnavailable),
Some(stream) => {
let _content_length = stream.content_length().await.unwrap();
let progress_bar = ProgressBar::new(_content_length);
progress_bar.set_style(ProgressStyle::with_template("[{elapsed_precise}] {bar:40.cyan/blue} {percent}% {msg}").unwrap());
let callback = {
let _progress_bar = progress_bar.clone();
Callback::new()
.connect_on_progress_closure_slow(move |arg| {
_progress_bar.inc(arg.current_chunk as u64);
_progress_bar.set_length(_progress_bar.length().unwrap()/*(arg.content_length.unwrap() - _progress_bar.length().unwrap()).abs()*/);
})
.connect_on_complete_closure(move |_| progress_bar.finish_with_message("Finished downloading asset!") )
};
stream.download_to_dir_with_callback(VIDEOS_DIR,callback).await.map(|_| Ok(()))?
}
}
}
}
}
AssetsError
is just a custom error type I have made using thiserror
crate and it is as follows :
use thiserror::Error;
#[derive(Error,Debug)]
pub(in crate) enum AssetsError {
#[error("Failed to create asset directory : {}",.0)]
CreatingDirectory(#[from] std::io::Error),
#[error("Failed to find video stream , maybe check for internet connection")]
VideoStreamUnavailable,
#[error("Failed to download video due to , {}",.0)]
DownloadError(#[from] rustube::Error),
}
So I still do not get why it doesn't downloads the file and gets stuck in the first place? Any help is appriciated