This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 3.6 kB View raw
1mod scenes; 2 3use anyhow::anyhow; 4use schedule_hell::State; 5use shapemaker::{ui::Log, *}; 6use std::{fs, path::PathBuf, time::Duration}; 7 8#[tokio::main] 9pub async fn main() { 10 let canvas = Canvas::new(16, 9); 11 12 let mut video = Video::<State>::new(canvas); 13 let mut args = pico_args::Arguments::from_env(); 14 15 video = video 16 // Sync inputs // 17 .sync_audio_with("schedule-hell.midi") 18 .expect("Failed to sync from MIDI file") 19 .sync_audio_with("schedule-hell.wav") 20 .expect("Failed to sync from WAV file"); 21 22 if let Ok(marker) = args.value_from_str::<_, String>("--marker") { 23 let range = video 24 .syncdata 25 .marker_ms_range(marker) 26 .expect("Cannot find marker {marker:?} in sync data"); 27 28 video.start_rendering_at = Timestamp::from_ms(range.start); 29 video.duration_override = Some(Duration::from_millis(range.len() as _)); 30 } 31 32 if let Ok(duration) = args.value_from_str("--duration") { 33 video.duration_override = Some(Duration::from_secs(duration)); 34 } 35 36 if let Ok(start) = args.value_from_str("--start") { 37 video.start_rendering_at = Timestamp::from_seconds(start); 38 } 39 40 video.resolution = args.value_from_str("--resolution").ok().unwrap_or(480); 41 video.fps = args.value_from_str("--fps").ok().unwrap_or(30); 42 43 video.audiofile = PathBuf::from("schedule-hell.wav"); 44 video = video 45 // Scenes // 46 .with_scene(scenes::starry_sky()) 47 .with_init_scene(scenes::intro()) 48 .with_marked_scene(scenes::first_break()) 49 .with_scene(scenes::backbone()) 50 .with_scene(scenes::dices()) 51 .assign_scene_to("end of first break", "intro") 52 .assign_scene_to("second break", "starry sky") 53 // "end first break" means "end of second break" lol 54 .assign_scene_to("end first break", "dices") 55 // Credits // 56 .when_remaining(10, &|canvas, _| { 57 let world = canvas.world_region; 58 canvas.root().set( 59 "credits text", 60 Shape::Text( 61 world.start, 62 "Postamble / Schedule Hell".into(), 63 12.0, 64 ) 65 .colored(Color::White), 66 ); 67 Ok(()) 68 }); 69 70 let destination: String = args 71 .free_from_str() 72 .unwrap_or(String::from("schedule-hell.mp4")); 73 74 if destination.starts_with("localhost:") { 75 video.serve(&destination).await; 76 } else { 77 let result = if destination.ends_with(".svg") { 78 let render_ahead = 1_000; 79 80 let frame_no = destination 81 .trim_end_matches(".svg") 82 .parse::<usize>() 83 .expect("Provide a integer when rendering a frame"); 84 85 video.progress_bars.loading.log( 86 "Constrained", 87 &format!( 88 "to frame #{frame_no}, with {render_ahead}-frame context" 89 ), 90 ); 91 92 video 93 .render_frame(frame_no, render_ahead) 94 .and_then(|svg| { 95 fs::write(destination, svg.to_string()) 96 .map_err(|e| anyhow!("{e:?}")) 97 }) 98 .map(|_| Duration::default()) 99 } else { 100 video.encode(destination) 101 }; 102 103 match result { 104 Ok(_) => (), 105 Err(e) => { 106 let _ = video.progress.clear(); 107 ().log_error("Failed", &format!("{e:?}")); 108 } 109 }; 110 } 111}