ofxVideoRecorder - video bitrate issue

Dear all,

I’m new to OpenFrameworks, and it’s really nice to experiment with this fantastic tools !
I’m currently working on an asciiArt video program, which aim is to do some offline rendering. Actually, since it requires the algorithm to iterate over many pixels for each frame, it seems a bit hard to make it run in realtime. Well, expcept the slow runtime due to my program, it renders well in realtime, slowly, but beautiful.

My current problem is about ofxVideoRecorder. I could make it run easily in simple tests, but as soon as I try to record the Ascii frames, it outputs a video with a completely different bitrate, even if I specify the bitrate in videoRecorder. Last but not least, the output seems to have some sizing issues that are not present when rendering to screen - resulting with a completely different video (not working for my purpose). I kind of tried every combination with sizes, it seems to transform when rendering. I’m not sure why it doesn’t render exactly like screen rendering.
Here is the function I use to render offline (called at the end of setup method).

void ofApp::processOffline()
{

    std::string ascii("");
    int numframe = video.getTotalNumFrames();
    recorder.setVideoCodec("mpeg4"); 
    recorder.setVideoBitrate("1263k") ; // same as input video
    recorder.setup("/home/johann/Documents/video/output.mp4", ofGetWidth(), ofGetHeight(), 25 ); // also tried with video.getWidth and video.getHeight with no more success
    recorder.start();
    
    ofImage out_image;
    ofColor color;
    int max = video.getTotalNumFrames();
    int idx = 0;
   do {
        ofClear(0);
        std::cout  << "process : " << idx  << " total frames : " << numframe<< std::endl;
        video.nextFrame();
        video.update();
        ofImage img(video.getPixels());
        ascii.clear();
        for(int y = 0; y < img.getHeight() ; y+=16) { // downsampling by 16 - y
            for(int x = 0; x < img.getWidth(); x+=16) { //downsampling by 16 - x
                  color = img.getColor(x,y);
                  ascii += asciiAlgo( getGreyLevel(color), 2); // ascii algorithm
            }
            ascii += "\n";
        }
        myFont.drawString(ascii,0,0);

        out_image.clear();
        out_image.grabScreen(0,0, ofGetWidth(), ofGetHeight());

        recorder.addFrame(out_image.getPixels());

        idx = video.getCurrentFrame();


    } while(idx < 100);


    recorder.close();
    OF_EXIT_APP(0);
}

Has anyone an experience with this ?

Thanks in advance
Johann PHILIPPE

ofPixels::getColor is really slow, try instead using pixels iterator as in:

for (auto line: img.getLines()){
    for(auto pixel: img.line.getPixels()){
         color = pixel.getColor();
         ascii += asciiAlgo( getGreyLevel(color), 2);
    }
   ascii += "\n";
}

It seems a bit slower with this. The problem is still there.

        for(auto line : img.getPixels().getLines() ) {
            for(auto pixel : line.getPixels()) {
               color = pixel.getColor();
               ascii += asciiAlgo( getGreyLevel(color), 2);
            }
            ascii += "\n";
        }

Printing the index of current frame is useful, because recorder (or ffmpeg) prints the current recorded frame too. And I can see it’s not synchronized here. In my previous example, recorded frames are superior to current frame I convert. And with the change you said, it’s the opposite, the recorded frame index is inferior to the current frame (the difference is usually between 5-20 frames)

Edit : of course it’s slower, I didn’t do the downsampling here…

Actually it was easier to do with OpenCv since it’s a non realtime project, that doesn’t requires OpenFrameworks facilities.
Thanks !