Golang : Save webcamera frames to video file
This tutorial will show you how to save image frames captured by a web camera and store the images into a video file. The code below is a simple command line program that will activate the web camera with Go-OpenCV, grab the image frame one at a time, store the image into a video file continuously in a for
loop. The loop will only be broken after the ESC key is pressed.
To build the code below, first install the OpenCV library.
On MacOSX, use homebrew to:
>brew install homebrew/science/opencv
and follow by
go get github.com/lazywei/go-opencv
Build the code and execute it with a target file name.
Here you go!
saveWebCam2File.go
package main
/*
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
char getch(){
char ch = 0;
struct termios old = {0};
fflush(stdout);
if( tcgetattr(0, &old) < 0 ) perror("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if( tcsetattr(0, TCSANOW, &old) < 0 ) perror("tcsetattr ICANON");
if( read(0, &ch,1) < 0 ) perror("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if(tcsetattr(0, TCSADRAIN, &old) < 0) perror("tcsetattr ~ICANON");
return ch;
}
*/
import "C"
// stackoverflow.com/questions/14094190/golang-function-similar-to-getchar
import (
"fmt"
"github.com/lazywei/go-opencv/opencv"
"math/rand"
"os"
"time"
)
func main() {
if len(os.Args) != 2 {
fmt.Printf("Usage : %s <save to filename>\n", os.Args[0])
os.Exit(0)
}
videoFileName := os.Args[1]
// activate webCamera
webCamera := opencv.NewCameraCapture(opencv.CV_CAP_ANY) // autodetect
if webCamera == nil {
panic("Unable to open camera")
}
// !! NEED TO CHECK IF YOUR OS HAS THE CODECS INSTALLED BEFORE SELECTING THE CODEC !!
// !! OTHERWISE, YOU WILL GET A VERY SMALL & CORRUPT VIDEO FILE !!
// see http://www.fourcc.org/codecs.php for other possible combinations
// opencv.FOURCC('p', 'i', 'm', '1') // MPEG-1 codec
// opencv.FOURCC('m', 'j', 'p', 'g') // motion-jpeg codec
// opencv.FOURCC('m', 'p', '4', '2') // MPEG-4.2 codec
// opencv.FOURCC('d', 'i', 'v', '3') // MPEG-4.3 codec
// opencv.FOURCC('m', 'p', '4', 'v') // MPEG-4 codec
// opencv.FOURCC('u', '2', '6', '3') // H263 codec
// opencv.FOURCC('i', '2', '6', '3') // H263I codec
// opencv.FOURCC('f', 'l', 'v', '1') // FLV1 codec
// codec := opencv.CV_FOURCC_PROMPT // Windows only. Prompt for codec selection
// codec := int(webCamera.GetProperty(opencv.CV_CAP_PROP_FOURCC)) -- won't work on my Mac
codec := int(opencv.FOURCC('m', 'p', '4', 'v')) // must be lower case, upper case will screw the file...
fps := float32(30) // 30 frames per second
//fps := float32(webCamera.GetProperty(opencv.CV_CAP_PROP_POS_FRAMES))
frameWidth := int(webCamera.GetProperty(opencv.CV_CAP_PROP_FRAME_WIDTH))
frameHeight := int(webCamera.GetProperty(opencv.CV_CAP_PROP_FRAME_HEIGHT))
isColor := 1 // 0 = false(grayscale), 1 = true -- for Windows only I think
// !! IMPORTANT : Remember to set the type to frameWidth and frameHeight for
// for both input(src) and output(destination) as the same
// otherwise, you gonna get this error message -
// [OpenCV Error: Assertion failed (dst.data == dst0.data) in cvCvtColor,]
// Just a note, you still can resize the frames before writing to file if you want
// for more info, read http://docs.opencv.org/trunk/dd/d9e/classcv_1_1VideoWriter.html
videoFileWriter := opencv.NewVideoWriter(videoFileName, codec, fps, frameWidth, frameHeight, isColor)
// uncomment to see your own recording
// win := opencv.NewWindow("Go-OpenCV record webcam to file")
fmt.Println("Press ESC key to to quit")
// go rountine to intercept ESC key
// since opencv.WaitKey does not work on my Mac :(
go func() {
key := C.getch()
fmt.Println()
fmt.Println("Cleaning up ...")
if key == 27 {
//videoFileWriter.Release() -- optional
webCamera.Release()
//win.Destroy() -- uncomment to see your own recording
fmt.Println("Play", videoFileName, "with a video player to see the result. Remember, no audio!")
os.Exit(0)
}
}()
// recording in progress ticker. From good old DOS days.
ticker := []string{
"-",
"\\",
"/",
"|",
}
rand.Seed(time.Now().UnixNano())
for {
if webCamera.GrabFrame() {
imgFrame := webCamera.RetrieveFrame(1)
if imgFrame != nil {
//win.ShowImage(imgFrame) -- uncomment to see your own recording
// save frame to video
frameNum := videoFileWriter.WriteFrame(imgFrame)
if frameNum > 0 {
fmt.Printf("\rRecording is live now. Wave to your webcamera! [%v]", ticker[rand.Intn(len(ticker)-1)])
}
//if opencv.WaitKey(1) >= 0 { -- won't work on Mac! :(
// os.Exit(0)
//}
}
}
}
}
Sample output:
>./saveWebCam2File test.mp4
Press ESC key to to quit
Recording now. Wave to your webcamera! [/]
Cleaning up ...
Cleaned up camera.
Play test.mp4 to see the result. Remember, no audio!
Happy cam whoring!
References:
https://www.socketloop.com/tutorials/golang-overwrite-previous-output-with-count-down-timer
http://www.fourcc.org/codecs.php
https://socketloop.com/tutorials/golang-randomly-pick-an-item-from-a-slice-array-example
http://stackoverflow.com/questions/14094190/golang-function-similar-to-getchar
See also : Golang : Activate web camera and broadcast out base64 encoded images
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+10.8k Golang : Web routing/multiplex example
+8.6k Golang : Take screen shot of browser with JQuery example
+7.2k Golang : How to stop user from directly running an executable file?
+7.9k Golang : Routes multiplexer routing example with regular expression control
+45.6k Golang : Read tab delimited file with encoding/csv package
+7k Golang : Null and nil value
+15.2k Golang : Force download file example
+19.6k Golang : How to run your code only once with sync.Once object
+4.7k Unix/Linux : secure copying between servers with SCP command examples
+7.6k Golang : Ways to recover memory during run time.
+15.4k Golang : Get current time from the Internet time server(ntp) example