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