Skip to content

Instantly share code, notes, and snippets.

@carrotflakes
Last active August 25, 2023 09:01
Show Gist options
  • Save carrotflakes/d6960c62d3de5dcbcc2b44562814d5a7 to your computer and use it in GitHub Desktop.
Save carrotflakes/d6960c62d3de5dcbcc2b44562814d5a7 to your computer and use it in GitHub Desktop.
Generate a movie by Rust with FFmpeg.
use std::io::Write;
use std::process::{Command, Stdio};
fn make_frame(width: usize, height: usize, time: usize) -> Vec<u8> {
let mut frame = Vec::with_capacity(4 * width * height);
for y in 0..height {
for x in 0..width {
frame.push((x % 256) as u8);
frame.push((y % 256) as u8);
frame.push((time % 256) as u8);
frame.push(255);
}
}
frame
}
fn main() {
let width: usize = 320;
let height: usize = 240;
let framerate: usize = 30;
let frames: usize = framerate * 5;
let mut child = Command::new("/bin/sh")
.args(&[
"-c",
format!(
"ffmpeg -f rawvideo -pix_fmt bgra -s {width}x{height} -i - -pix_fmt yuv420p -r {framerate} -y {output}",
width = width,
height = height,
framerate = framerate,
output = "out.mp4").as_str()])
.stdin(Stdio::piped())
.spawn()
.expect("failed to execute child");
let child_stdin = child.stdin.as_mut().expect("failed to get stdin");
for f in 0..frames {
child_stdin.write_all(&make_frame(width, height, f)[..]).unwrap();
}
child.wait().expect("child process wasn't running");
}
extern crate cairo;
use std::io::Write;
use std::process::{Command, Stdio};
use cairo::{ImageSurface, Format, Context};
fn make_make_frame(width: usize, height: usize) -> Box<FnMut(&mut [u8], usize)> {
let mut surface = ImageSurface::create(Format::ARgb32, width as i32, height as i32).unwrap();
Box::new(move |buffer: &mut [u8], time: usize| {
{
let ctx = Context::new(&surface);
ctx.set_source_rgb(1.0, 1.0, 1.0);
ctx.paint();
ctx.move_to(width as f64 / 2.0, height as f64 / 2.0);
ctx.line_to(width as f64 / 2.0 + (time as f64 / 30.0).cos() * 40.0,
height as f64 / 2.0 + (time as f64 / 30.0).sin() * 40.0);
ctx.set_source_rgb(1.0, 0.0, 0.0);
ctx.stroke();
}
let data = surface.get_data().unwrap();
for i in 0..height*width*4 {
buffer[i] = data[i];
}
})
}
fn main() {
let width: usize = 320;
let height: usize = 240;
let framerate: usize = 30;
let frames: usize = framerate * 5;
let mut buffer = vec![0; width * height * 4];
let mut child = Command::new("/bin/sh")
.args(&[
"-c",
format!(
"ffmpeg -f rawvideo -pix_fmt bgra -s {width}x{height} -i - -pix_fmt yuv420p -r {framerate} -y {output}",
width = width,
height = height,
framerate = framerate,
output = "out.mp4").as_str()])
.stdin(Stdio::piped())
.spawn()
.expect("failed to execute child");
let child_stdin = child.stdin.as_mut().expect("failed to get stdin");
let mut fun = make_make_frame(width, height);
for f in 0..frames {
fun(buffer.as_mut_slice(), f);
child_stdin.write_all(buffer.as_slice()).unwrap();
}
child.wait().expect("child process wasn't running");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment