Skip to content

Instantly share code, notes, and snippets.

@pgorczak
Last active March 7, 2019 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pgorczak/f1a6326fdf51ac886e2ce54399fbd6a4 to your computer and use it in GitHub Desktop.
Save pgorczak/f1a6326fdf51ac886e2ce54399fbd6a4 to your computer and use it in GitHub Desktop.
Helper class for exporting video from openFrameworks.

Video export for openFrameworks

This is a small helper that uses ffmpeg to record h264 video from openFrameworks.

It starts ffmpeg in a subprocess, so ffmpeg should be available on your system. Tested on Linux but probably works on macOS too.

How to use

  • Add the videxport.h file to your project and include it.
  • VidRecorder::start to start ffmpeg and configure output filename and framerate.
  • VidRecorder::recordViewport adds a frame to the video file.
  • VidRecorder::finish stops ffmpeg.
  • Watch the console output for errors and messages from the ffmpeg process.
  • All functions return false if something goes wrong (see the example file draw function).
#include "ofApp.h"
#include "ofMain.h"
#include "videxport.h"
class VidRecorderExample : public ofBaseApp {
public:
void setup() {
ofBackground(ofColor::gray);
ofSetBackgroundAuto(false);
recorder.start("example.mp4", 60);
position.x = 0;
position.y = ofGetViewportHeight() / 2;
}
void update() {
position.x =
ofGetViewportWidth() * static_cast<float>(ofGetFrameNum()) / 300;
}
void draw() {
ofSetColor(ofColor::white, 16);
ofFill();
ofDrawRectangle(0, 0, ofGetViewportWidth(), ofGetViewportHeight());
ofSetColor(ofColor::black);
ofDrawCircle(position, 100);
bool recording = recorder.recordViewport();
if (!recording) {
ofExit();
}
if (ofGetFrameNum() > 300) {
recorder.finish();
ofExit();
}
}
ofPoint position;
VidRecorder recorder;
};
int main() {
ofSetupOpenGL(1000, 1000, OF_WINDOW);
ofSetFrameRate(60);
ofSetVerticalSync(true);
ofRunApp(new VidRecorderExample());
}
#ifndef VIDEXPORT_H
#define VIDEXPORT_H
#include <stdio.h>
#include "ofMain.h"
extern template class ofPixels_<unsigned char>;
struct VidRecorder {
FILE *f = nullptr;
ofPixels p;
ofBuffer b;
void logError(std::string m) { ofLogError("VidRecorder", m); }
bool start(std::string filename, unsigned int fps = 60) {
// If we don't call this and ffmpeg crashes, the whole app stops.
signal(SIGPIPE, SIG_IGN);
std::stringstream cmd;
cmd << "ffmpeg "
<< "-f image2pipe "
<< "-framerate " << fps << " -i - -c:v libx264 -pix_fmt yuv420p "
<< filename;
f = popen(cmd.str().c_str(), "w");
if (!f) {
logError(std::string(strerror(errno)));
return false;
}
return true;
}
bool recordViewport() {
if (!f) {
logError("File handle is null.");
return false;
}
ofGetGLRenderer()->saveFullViewport(p);
ofSaveImage(p, b, OF_IMAGE_FORMAT_BMP);
auto written = fwrite(b.getData(), sizeof(char), b.size(), f);
if (written != b.size()) {
logError(std::string(strerror(errno)));
return false;
}
return true;
}
bool finish() {
if (!f) {
logError("File handle is null.");
return false;
}
auto r = pclose(f);
if (r == -1) {
logError(std::string(strerror(errno)));
f = nullptr;
return false;
}
f = nullptr;
return true;
}
};
#endif // VIDEXPORT_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment