@@ -3,7 +3,9 @@ mod image;
33mod path;
44mod slide;
55mod video;
6+ mod watch;
67
8+ use crate :: slide:: Slide ;
79use clap:: Parser ;
810use serde:: Deserialize ;
911use serde_json:: json;
@@ -12,6 +14,7 @@ use std::path::Path;
1214use std:: path:: PathBuf ;
1315use tracing:: subscriber:: SetGlobalDefaultError ;
1416use transformrs:: Provider ;
17+ use watch:: watch;
1518
1619#[ derive( Clone , Debug , Default , Deserialize ) ]
1720struct Config {
@@ -110,7 +113,7 @@ enum Task {
110113
111114#[ derive( Parser ) ]
112115#[ command( author, version, about = "Text and image to video" ) ]
113- struct Arguments {
116+ pub ( crate ) struct Arguments {
114117 #[ command( subcommand) ]
115118 task : Task ,
116119
@@ -124,7 +127,7 @@ struct Arguments {
124127
125128 /// Enable caching.
126129 #[ arg( long, default_value = "true" ) ]
127- cache : bool ,
130+ cache : Option < bool > ,
128131
129132 /// Release.
130133 ///
@@ -215,25 +218,9 @@ fn copy_input_with_includes(dir: &str, input: &PathBuf) -> PathBuf {
215218 output_path
216219}
217220
218- #[ tokio:: main]
219- async fn main ( ) {
220- let args = Arguments :: parse ( ) ;
221- if args. verbose {
222- init_subscriber ( tracing:: Level :: DEBUG ) . unwrap ( ) ;
223- } else {
224- init_subscriber ( tracing:: Level :: INFO ) . unwrap ( ) ;
225- }
226-
227- let dir = & args. out_dir ;
228- let path = Path :: new ( dir) ;
229- if !path. exists ( ) {
230- std:: fs:: create_dir_all ( path) . unwrap ( ) ;
231- }
232- let input = match args. task {
233- Task :: Build ( args) => args. input ,
234- Task :: Watch ( args) => args. input ,
235- } ;
236- let copied_input = copy_input_with_includes ( dir, & input) ;
221+ pub ( crate ) async fn build ( input : PathBuf , args : & Arguments ) -> Vec < Slide > {
222+ let out_dir = & args. out_dir ;
223+ let copied_input = copy_input_with_includes ( out_dir, & input) ;
237224 let config = parse_config ( & copied_input) ;
238225
239226 let provider = config. provider . map ( |p| provider_from_str ( & p) ) ;
@@ -254,25 +241,49 @@ async fn main() {
254241 if slides. is_empty ( ) {
255242 panic ! ( "No slides found in input file: {}" , input. display( ) ) ;
256243 }
257- image:: generate_images ( & copied_input, dir ) ;
244+ image:: generate_images ( & copied_input, out_dir ) ;
258245 let audio_ext = tts_config
259246 . output_format
260247 . clone ( )
261248 . unwrap_or ( "mp3" . to_string ( ) ) ;
249+ let cache = args. cache . unwrap ( ) ;
262250 audio:: generate_audio_files (
263251 & provider,
264- dir ,
252+ out_dir ,
265253 & slides,
266- args . cache ,
254+ cache,
267255 & tts_config,
268256 & config. model ,
269257 & audio_ext,
270258 )
271259 . await ;
272- // Using mkv by default because it supports more audio formats.
273- let output = "out.mkv" ;
274- video:: generate_video ( dir, & slides, args. cache , & tts_config, output, & audio_ext) ;
260+ let output = "out.mp4" ;
261+ video:: generate_video ( out_dir, & slides, cache, & tts_config, output, & audio_ext) ;
275262 if args. release {
276- video:: generate_release_video ( dir, output, "release.mp4" , & args. audio_codec ) ;
263+ video:: generate_release_video ( out_dir, output, "release.mp4" , & args. audio_codec ) ;
264+ }
265+ slides
266+ }
267+
268+ #[ tokio:: main]
269+ async fn main ( ) {
270+ let args = Arguments :: parse ( ) ;
271+ if args. verbose {
272+ init_subscriber ( tracing:: Level :: DEBUG ) . unwrap ( ) ;
273+ } else {
274+ init_subscriber ( tracing:: Level :: INFO ) . unwrap ( ) ;
277275 }
276+
277+ let dir = & args. out_dir ;
278+ let path = Path :: new ( dir) ;
279+ if !path. exists ( ) {
280+ std:: fs:: create_dir_all ( path) . unwrap ( ) ;
281+ }
282+
283+ match args. task {
284+ Task :: Build ( ref build_args) => {
285+ let _ = build ( build_args. input . clone ( ) , & args) . await ;
286+ }
287+ Task :: Watch ( ref watch_args) => watch ( watch_args. input . clone ( ) , & args) . await ,
288+ } ;
278289}
0 commit comments