5

I'm using the following code to read a video from file, apply the canny edge algorithm and write the modified video to a file. The code compiles and runs perfectly. But, the video is not written! I'm utterly confused. Please tell me what the error is. The file is not created at all! OS: Ubuntu 12.10

Code for writing to the output file

Opening the output file

bool setOutput(const std::string &filename, int codec=0, double framerate=0.0, bool isColor=true) {

    outputFile= filename;
    extension.clear();

    if (framerate==0.0) 
        framerate= getFrameRate(); // same as input

    char c[4];
    // use same codec as input
    if (codec==0) { 
        codec= getCodec(c);
    }

    // Open output video
    return writer.open(outputFile, // filename
    codec, // codec to be used 
    framerate,      // frame rate of the video
    getFrameSize(), // frame size
    isColor);       // color video?
}

Writing the frame

void writeNextFrame (Mat& frame)
{
    writer.write (frame);
}

And there's a separate run method which executes these

karlphillip
  • 92,053
  • 36
  • 243
  • 426
pratnala
  • 3,723
  • 7
  • 35
  • 58

3 Answers3

5

Whenever I encounter strange behaviors in my applications, I write a short, self contained, correct (compilable), example to help me understand what's going on.

I wrote the code below to illustrate what you should be doing. It's worth noting that it works perfectly on my Mac OS X:

#include <cv.h>
#include <highgui.h>

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    // Load input video
    cv::VideoCapture input_cap("Wildlife.avi");
    if (!input_cap.isOpened())
    {
        std::cout << "!!! Input video could not be opened" << std::endl;
        return -1;
    }

    // Setup output video
    cv::VideoWriter output_cap("output.avi",  
                               input_cap.get(CV_CAP_PROP_FOURCC),
                               input_cap.get(CV_CAP_PROP_FPS), 
                               cv::Size(input_cap.get(CV_CAP_PROP_FRAME_WIDTH), input_cap.get(CV_CAP_PROP_FRAME_HEIGHT)));

    if (!output_cap.isOpened())
    {
        std::cout << "!!! Output video could not be opened" << std::endl;
        return -1;
    }

    // Loop to read frames from the input capture and write it to the output capture
    cv::Mat frame;
    while (true)
    {       
        if (!input_cap.read(frame))             
            break;

        output_cap.write(frame);
    }

    // Release capture interfaces   
    input_cap.release();
    output_cap.release();

    return 0;
}

Inspecting the input file with FFmpeg reveals (ffmpeg -i Wildlife.avi):

Input #0, avi, from 'Wildlife.avi':
  Metadata:
    ISFT            : Lavf52.13.0
  Duration: 00:00:07.13, start: 0.000000, bitrate: 2401 kb/s
    Stream #0.0: Video: msmpeg4v2, yuv420p, 1280x720, PAR 1:1 DAR 16:9, 29.97 tbr, 29.97 tbn, 29.97 tbc
    Stream #0.1: Audio: mp3, 44100 Hz, 2 channels, s16, 96 kb/s

and the output:

Input #0, avi, from 'output.avi':
  Metadata:
    ISFT            : Lavf52.61.0
  Duration: 00:00:07.10, start: 0.000000, bitrate: 3896 kb/s
    Stream #0.0: Video: msmpeg4v2, yuv420p, 1280x720, 29.97 tbr, 29.97 tbn, 29.97 tbc

So the only significant change between the two files is that the output generated by OpenCV doesn't have an audio stream, which is the correct behavior since OpenCV doesn't deal with audio.

Make sure your user has the proper permission to read/write/execute in the directory you are running the application. Also, the debugs I added in the code will probably assist you to find problems related to input/output capture.

karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • Something is wrong. I'm getting the error `!!! Output video can't be opened` which you have thankfully inserted. So I guess that's the problem. And, btw I'm the only user and hence the administrator and these files are located in the Documents folder of the Home Directory – pratnala Nov 15 '12 at 17:50
  • Found the issue. I was using an mov file all this file and thats why it didnt write. I used an avi file and it worked. How to make it work with an mov file? All my test videos are in the mov format. EDIT: I tried mp4 and even that doesn't work – pratnala Nov 15 '12 at 17:53
  • 1
    [AVI/MOV/MP4 are just containers](http://opencv.willowgarage.com/wiki/VideoCodecs) and OpenCV knows how to read them. The real problem is the format in which the data is packed inside these containers (codec). Your .mov files might be using a codec that is not supported by OpenCV. Use a 3rd party tool to change the codec of one of your .mov files and try again. – karlphillip Nov 15 '12 at 18:37
  • My .mov files are recorded from the iPod camera and .mp4 files from my laptop's webcam in Windows 8. Do they use some proprietary codecs which OpenCV doesn't know how to read? – pratnala Nov 16 '12 at 02:19
  • Btw, the input file is opened and read (no error there). Only the output file is not being opened (and hence, not written to). – pratnala Nov 16 '12 at 02:20
  • Use a [software to inspect videos](http://www.fourcc.org/identifier/) to figure out what's the codec used inside of them. What you observed seems to indicate that OpenCV can't write a video with the specified codec. Can you do this simple test: in your program, change the extension of the **output** file from .MOV to .AVI. Let me know if that works. – karlphillip Nov 16 '12 at 14:10
  • Alright, so apparently your OpenCV can't write MOV files or just can't write MOV files with the codec you are using. I have OpenCV 2.4.3 and I tried opening a .mov recorded on my Mac, and I got this error: `Could not open codec 'libx264': Unspecified errorWARNING: Could not create empty movie file container.`. This means that I probably don't have the codec necessary to **ENCODE** the output video in the specified format. In my case it seems to be a simple matter of installing **libx264** on the system. By the way, the most recent OpenCV version available is 2.4.3, released this month. – karlphillip Nov 16 '12 at 16:02
  • I'm using the OpenCV version available in the Ubuntu repositories – pratnala Nov 17 '12 at 12:31
  • I have no idea what version they use. But I insist that you make sure you have libx264 properly installed on your system. Also, as a separate test: pick another codec for the output video but keep the .mov extension. – karlphillip Nov 17 '12 at 15:33
2

do you have FFMPEG library installed on your machine? On Linux FFMPEG is used to write videos; on Windows FFMPEG or VFW is used. check by command

 ffmpeg -version

try to install additional libraries sudo apt-get install libavformat-dev libswscale-dev.

And by calling writer.open you only Initializes or reinitializes video writer.You have to call the void VideoWriter::write(const Mat& image) to write the next video frame to file. I hope this will work.

isrish
  • 692
  • 6
  • 12
  • `ffmpeg` wasn't installed. So, I installed it using `sudo apt-get install ffmpeg`. It still doesn't write it to disk. Although the terminal says `Output #0, mp4, to 'videolala.mp4': Stream #0.0: Video: [0][0][0][0] / 0x0000, yuv420p, 720x480, q=2-31, 22118 kb/s, 90k tbn, 42 tbc`. And `ffmpeg -version` gives `ffmpeg version 0.8.4-6:0.8.4-0ubuntu0.12.10.1, Copyright (c) 2000-2012 the Libav developers`. It also says `The program is deprecated` – pratnala Nov 14 '12 at 02:41
  • yeah `VideoWriter::write` is called in another function. Have added that code too – pratnala Nov 15 '12 at 17:58
0

I had the same problem and I changed the codecs to DIVX. Now the video is saved in both .avi and .mp4 formats.

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Pathum
  • 1
  • 3