Vidio/README.md
2021-12-28 10:08:41 -08:00

6.3 KiB

Vidio

A simple Video I/O library written in Go. This library relies on FFmpeg, and FFProbe which must be downloaded before usage.

All frames are encoded and decoded in 8-bit RGB format.

Installation

go get github.com/AlexEidt/Vidio

Video

The Video struct stores data about a video file you give it. The code below shows an example of sequentially reading the frames of the given video.

type Video struct {
	filename    string          // Video Filename
	width       int             // Width of Frames
	height      int             // Height of Frames
	depth       int             // Depth of Frames
	bitrate     int             // Bitrate for video encoding
	frames      int             // Total number of frames
	duration    float64         // Duration in seconds
	fps         float64         // Frames per second
	codec       string          // Codec used to encode video
	pix_fmt     string          // Pixel format video is stored in
	framebuffer []byte          // Raw frame data
	pipe        *io.ReadCloser  // Stdout pipe for ffmpeg process
	cmd         *exec.Cmd       // ffmpeg command
}
video := vidio.NewVideo("input.mp4")
for video.Read() {
	// "frame" stores the video frame as a flattened RGB image
	frame := video.framebuffer // stored as: RGBRGBRGBRGB...
	// Video processing here...
}

Camera

The Camera can read from any cameras on the device running Vidio. It takes in the stream index. On most machines the webcam device has index 0.

type Camera struct {
	name        string          // Camera device name
	width       int             // Camera frame width
	height      int             // Camera frame height
	depth       int             // Camera frame depth
	fps         float64         // Camera frames per second
	codec       string          // Camera codec
	framebuffer []byte          // Raw frame data
	pipe        *io.ReadCloser  // Stdout pipe for ffmpeg process streaming webcam
	cmd         *exec.Cmd       // ffmpeg command
}
camera := vidio.NewCamera(0) // Get Webcam
defer camera.Close()

// Stream the webcam
for camera.Read() {
	// "frame" stores the video frame as a flattened RGB image
	frame := camera.framebuffer // stored as: RGBRGBRGBRGB...
	// Video processing here...
}

VideoWriter

The VideoWriter is used to write frames to a video file. The only required parameters are the output file name, the width and height of the frames being written, and an Options struct. This contains all the desired properties of the new video you want to create.

type Options struct {
	bitrate     int             // Bitrate
	loop        int             // For GIFs only. -1=no loop, 0=loop forever, >0=loop n times
	delay       int             // Delay for Final Frame of GIFs. Default -1 (Use same delay as previous frame)
	macro       int             // macro size for determining how to resize frames for codecs. Default 16
	fps         float64         // Frames per second. Default 25
	quality     float64         // If bitrate not given, use quality instead. Must be between 0 and 1. 0:best, 1:worst
	codec       string          // Codec for video. Default libx264
}
type VideoWriter struct {
	filename    string          // Output video filename
	width       int             // Frame width
	height      int             // Frame height
	bitrate     int             // Output video bitrate for encoding
	loop        int             // Number of times for GIF to loop
	delay       int             // Delay of final frame of GIF
	macro       int             // macro size for determining how to resize frames for codecs
	fps         float64         // Frames per second for output video
	quality     float64         // Used if bitrate not given
	codec       string          // Codec to encode video with
	pipe        *io.WriteCloser // Stdout pipe of ffmpeg process
	cmd         *exec.Cmd       // ffmpeg command
}
w, h, c := 1920, 1080, 3
options := vidio.Options{} // Will fill in defaults if empty

writer := vidio.NewVideoWriter("output.mp4", w, h, &options)
defer writer.Close()

frame := make([]byte, w*h*c) // Create Frame as RGB Image and modify
writer.Write(frame) // Write Frame to video

Images

Vidio provides some convenience functions for reading and writing to images using an array of bytes. Currently, only png and jpeg formats are supported.

// Read png image
w, h, img := vidio.Read("input.png")

// w - width of image
// h - height of image
// img - byte array in RGB format. RGBRGBRGBRGB...

vidio.Write("output.jpg", w, h, img)

Examples

Copy input.mp4 to output.mp4.

video := vidio.NewVideo("input.mp4")
options := vidio.Options{
	fps: video.fps,
	bitrate: video.bitrate
}

writer := vidio.NewVideoWriter("output.mp4", video.width, video.height, &options)
defer writer.Close()

for video.Read() {
    writer.Write(video.framebuffer)
}

Grayscale 1000 frames of webcam stream and store in output.mp4.

webcam := vidio.NewCamera(0)
defer webcam.Close()

options := vidio.Options{fps: webcam.fps}

writer := vidio.NewVideoWriter("output.mp4", webcam.width, webcam.height, &options)
defer writer.Close()

count := 0
for webcam.Read() {
	for i := 0; i < len(webcam.framebuffer); i += 3 {
		rgb := webcam.framebuffer[i : i+3]
		r, g, b := int(rgb[0]), int(rgb[1]), int(rgb[2])
		gray := uint8((3*r + 4*g + b) / 8)
		writer.framebuffer[i] = gray
		writer.framebuffer[i+1] = gray
		writer.framebuffer[i+2] = gray
	}
	writer.Write(webcam.framebuffer)
	count++
	if count > 1000 {
		break
	}
}

Create a gif from a series of png files enumerated from 1 to 10 that loops continuously with a final frame delay of 1000 centiseconds.

w, h, _ := vidio.Read("1.png") // Get frame dimensions from first image

options := vidio.Options{fps: 1, loop: -1, delay: 1000}

gif := vidio.NewVideoWriter("output.gif", w, h, &options)
defer gif.Close()

for i := 1; i <= 10; i++ {
	_, _, img := vidio.Read(strconv.Itoa(i)+".png")
	gif.Write(img)
}

Acknowledgements