@@ -56,10 +56,7 @@ impl Video {
5656 /// println!("{:#?}", chunk);
5757 /// }
5858 /// ```
59- pub fn stream (
60- & self ,
61- #[ cfg( feature = "ffmpeg" ) ] ffmpeg_args : Option < FFmpegArgs > ,
62- ) -> Result < Box < dyn Stream + Send + Sync > , VideoError > {
59+ pub fn stream ( & self ) -> Result < Box < dyn Stream + Send + Sync > , VideoError > {
6360 let client = self . 0 . get_client ( ) ;
6461
6562 let options = self . 0 . get_options ( ) ;
@@ -81,25 +78,21 @@ impl Video {
8178 let stream = LiveStream :: new ( LiveStreamOptions {
8279 client : Some ( client. clone ( ) ) ,
8380 stream_url : link,
84- } ) ;
85-
86- if stream. is_err ( ) {
87- return Err ( stream. err ( ) . unwrap ( ) ) ;
88- }
81+ } ) ?;
8982
90- return Ok ( Box :: new ( stream. unwrap ( ) ) ) ;
83+ return Ok ( Box :: new ( stream) ) ;
9184 }
9285 #[ cfg( not( feature = "live" ) ) ]
9386 {
9487 return Err ( VideoError :: LiveStreamNotSupported ) ;
9588 }
9689 }
9790
98- let dl_chunk_size = if options. download_options . dl_chunk_size . is_some ( ) {
99- options . download_options . dl_chunk_size . unwrap ( )
100- } else {
101- 1024 * 1024 * 10_u64 // -> Default is 10MB to avoid Youtube throttle (Bigger than this value can be throttle by Youtube)
102- } ;
91+ let dl_chunk_size = options
92+ . download_options
93+ . dl_chunk_size
94+ // 1024 * 1024 * 10_u64 -> Default is 10MB to avoid Youtube throttle (Bigger than this value can be throttle by Youtube)
95+ . unwrap_or ( 1024 * 1024 * 10_u64 ) ;
10396
10497 let start = 0 ;
10598 let end = start + dl_chunk_size;
@@ -114,13 +107,102 @@ impl Video {
114107 if content_length == 0 {
115108 let content_length_response = block_async ! ( client. get( & link) . send( ) )
116109 . map_err ( VideoError :: ReqwestMiddleware ) ?
117- . content_length ( ) ;
110+ . content_length ( )
111+ . ok_or ( VideoError :: VideoNotFound ) ?;
112+
113+ content_length = content_length_response;
114+ }
115+
116+ let stream = NonLiveStream :: new ( NonLiveStreamOptions {
117+ client : Some ( client. clone ( ) ) ,
118+ link,
119+ content_length,
120+ dl_chunk_size,
121+ start,
122+ end,
123+ #[ cfg( feature = "ffmpeg" ) ]
124+ ffmpeg_args : None ,
125+ } ) ?;
118126
119- if content_length_response. is_none ( ) {
120- return Err ( VideoError :: VideoNotFound ) ;
127+ Ok ( Box :: new ( stream) )
128+ }
129+
130+ #[ cfg( feature = "ffmpeg" ) ]
131+ /// Try to turn [`Stream`] implemented [`LiveStream`] or [`NonLiveStream`] depend on the video with [`FFmpegArgs`].
132+ /// If function successfully return can download video with applied ffmpeg filters and formats chunk by chunk
133+ /// # Example
134+ /// ```ignore
135+ /// let video_url = "https://www.youtube.com/watch?v=FZ8BxMU3BYc";
136+ ///
137+ /// let video = Video::new(video_url).unwrap();
138+ ///
139+ /// let stream = video.stream().await.unwrap();
140+ ///
141+ /// while let Some(chunk) = stream.chunk().await.unwrap() {
142+ /// println!("{:#?}", chunk);
143+ /// }
144+ /// ```
145+ pub async fn stream_with_ffmpeg (
146+ & self ,
147+ ffmpeg_args : Option < FFmpegArgs > ,
148+ ) -> Result < Box < dyn Stream + Send + Sync > , VideoError > {
149+ let client = self . 0 . get_client ( ) ;
150+
151+ let options = self . 0 . get_options ( ) ;
152+
153+ let info = block_async ! ( self . 0 . get_info( ) ) ?;
154+ let format = choose_format ( & info. formats , & options)
155+ . map_err ( |_op| VideoError :: VideoSourceNotFound ) ?;
156+
157+ let link = format. url ;
158+
159+ if link. is_empty ( ) {
160+ return Err ( VideoError :: VideoSourceNotFound ) ;
161+ }
162+
163+ // Only check for HLS formats for live streams
164+ if format. is_hls {
165+ #[ cfg( feature = "live" ) ]
166+ {
167+ let stream = LiveStream :: new ( LiveStreamOptions {
168+ client : Some ( client. clone ( ) ) ,
169+ stream_url : link,
170+ } ) ?;
171+
172+ return Ok ( Box :: new ( stream) ) ;
121173 }
174+ #[ cfg( not( feature = "live" ) ) ]
175+ {
176+ return Err ( VideoError :: LiveStreamNotSupported ) ;
177+ }
178+ }
179+
180+ let dl_chunk_size = options
181+ . download_options
182+ . dl_chunk_size
183+ // 1024 * 1024 * 10_u64 -> Default is 10MB to avoid Youtube throttle (Bigger than this value can be throttle by Youtube)
184+ . unwrap_or ( 1024 * 1024 * 10_u64 ) ;
122185
123- content_length = content_length_response. unwrap ( ) ;
186+ let start = 0 ;
187+ let end = start + dl_chunk_size;
188+
189+ let mut content_length = format
190+ . content_length
191+ . unwrap_or ( "0" . to_string ( ) )
192+ . parse :: < u64 > ( )
193+ . unwrap_or ( 0 ) ;
194+
195+ // Get content length from source url if content_length is 0
196+ if content_length == 0 {
197+ let content_length_response = client
198+ . get ( & link)
199+ . send ( )
200+ . await
201+ . map_err ( VideoError :: ReqwestMiddleware ) ?
202+ . content_length ( )
203+ . ok_or ( VideoError :: VideoNotFound ) ?;
204+
205+ content_length = content_length_response;
124206 }
125207
126208 let stream = NonLiveStream :: new ( NonLiveStreamOptions {
@@ -130,28 +212,27 @@ impl Video {
130212 dl_chunk_size,
131213 start,
132214 end,
133- #[ cfg( feature = "ffmpeg" ) ]
134215 ffmpeg_args,
135216 } ) ?;
136217
137218 Ok ( Box :: new ( stream) )
138219 }
139220
140221 /// Download video directly to the file
141- pub fn download < P : AsRef < std:: path:: Path > > (
222+ pub fn download < P : AsRef < std:: path:: Path > > ( & self , path : P ) -> Result < ( ) , VideoError > {
223+ Ok ( block_async ! ( self . 0 . download( path) ) ?)
224+ }
225+
226+ #[ cfg( feature = "ffmpeg" ) ]
227+ /// Download video with ffmpeg args directly to the file
228+ pub async fn download_with_ffmpeg < P : AsRef < std:: path:: Path > > (
142229 & self ,
143230 path : P ,
144- # [ cfg ( feature = "ffmpeg" ) ] ffmpeg_args : Option < FFmpegArgs > ,
231+ ffmpeg_args : Option < FFmpegArgs > ,
145232 ) -> Result < ( ) , VideoError > {
146- #[ cfg( feature = "ffmpeg" ) ]
147- {
148- Ok ( block_async ! ( self . 0 . download( path, ffmpeg_args) ) ?)
149- }
150-
151- #[ cfg( not( feature = "ffmpeg" ) ) ]
152- {
153- Ok ( block_async ! ( self . 0 . download( path) ) ?)
154- }
233+ Ok ( block_async ! ( self
234+ . 0
235+ . download_with_ffmpeg( path, ffmpeg_args) ) ?)
155236 }
156237
157238 /// Get video URL
0 commit comments