rad apple
- 1 Devlogs
- 2 Total hours
im just building bad apple in the terminal with rust
im just building bad apple in the terminal with rust
I made bad apple run in terminal using the cascii rust crate to convert the video to frames, and then drew those frames while clearing the terminal. This is just a joke project so I’m not gonna ship it or anything.
Here’s the code, but it’s pretty bad. I’m by no means the greatest programmer. There’s also a lot of warnings, but I’m too lazy to fix them.
use cascii::{AsciiConverter, VideoOptions, ConversionOptions};
use std::path: :Path;
use std::fs::{self, File};
use std::io::Read;
use terminal_size::{Width, Height, terminal_size};
use crossterm::{
cursor::{Hide, Show, MoveTo},
execute,
terminal::{Clear, ClearType},
};
use std::io::{self, stdout};
use std::thread;
use std::time::Duration;
fn main() -> std::io::Result<()> {
if !Path::new("output_frames").is_dir() {
get_frames();
}
let mut frames: Vec<String> = read_files()?;
play_animation(frames)?;
// println!("{}", frames[0]);
Ok(())
}
fn get_frames() -> Result<(), Box<dyn std::error: :Error>> {
let converter = AsciiConverter::new();
let size = terminal_size();
let mut width: u32 = 80;
let mut height = 0;
if let Some((Width(w), Height(h))) = size {
width = u32::from(w);
} else {
println!("unable to get terminal size");
}
let video_options = VideoOptions {
fps: 30,
start: Some("0".to_string()),
end: Some("10".to_string()),
columns: width,
extract_audio: false,
preprocess_filter: None,
};
let conversion_options = ConversionOptions::default().with_font_ratio(0.2).with_luminance(20).with_columns(width);
converter.convert_video(Path::new("assets/apple.mp4"), Path::new("output_frames"), &video_options, &conversion_options, false)?;
Ok(())
}
fn read_files() -> std::io::Result<Vec<String>> {
let mut files = Vec::new();
for file in fs::read_dir("output_frames/").unwrap() {
files.push(file.unwrap().path().display().to_string());
}
files.sort();
let mut frames: Vec<String> = Vec::new();
for file in files {
let content = fs::read_to_string(file);
let frame = match content {
Ok(val) => val,
Err(err) => format!("error: {}", err),
};
frames.push(frame);
}
Ok(frames)
}
fn play_animation(frames: Vec<String>) -> io::Result<()> {
let frame = 0;
let mut stdout = stdout();
for frame in &frames {
execute!(stdout, Hide, Clear(ClearType::All))?;
execute!(stdout, MoveTo(0, 0));
println!("{}", frame);
thread::sleep(Duration::from_millis(33));
}
execute!(stdout, Show)?;
Ok(())
}