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
+17.1k Golang : Get future or past hours, minutes or seconds
+22.6k Golang : Calculate time different
+25.4k Golang : Convert IP address string to long ( unsigned 32-bit integer )
+7.2k Golang : Dealing with struct's private part
+5.1k Golang : Qt update UI elements with core.QCoreApplication_ProcessEvents
+8.5k Golang : Random integer with rand.Seed() within a given range
+5.5k Golang : Fix opencv.LoadHaarClassifierCascade The node does not represent a user object error
+30.1k Golang : How to redirect to new page with net/http?
+4.5k Linux/MacOSX : How to symlink a file?
+14.2k Golang : Find network of an IP address
+7.2k Android Studio : AlertDialog to get user attention example
+6.8k Golang : Squaring elements in array