OpenCV VideoWriter Not Writing to Output.avi

12,996

Solution 1

The reason of error is the differences between the dimension of the cropped_frame (640,340) and the dimension declared in the writer (640,360).

So the writer should be:

out = cv2.VideoWriter('output.avi', fourcc, 20.0,(640,340))

Solution 2

I had the same problem with OpenCV C++ in Ubuntu ubuntu 18.04. I was processing a video (converting to grayscale and then generating a "paint" effect).

I solved the problem successfully doing the following steps:

  1. Use the VideoWriter with the following line:
    VideoWriter videoWriter("effect.avi", VideoWriter::fourcc('m','p','4','v'), 15.0, Size(ancho, alto), true);
  1. Convert the image (in my case was in grayscale) to BGR (do the same in case that your image is in RGB color space):
    Mat finalImage;
    cvtColor(imgEffect,finalImage,COLOR_GRAY2BGR);
    videoWriter.write(finalImage);

After the execution, the code generates the video without problems.

You can found my code in the following link: Example Code in C++

Share:
12,996
R.Zane
Author by

R.Zane

Updated on June 11, 2022

Comments

  • R.Zane
    R.Zane about 2 years

    I'm attempting to write a simple bit of code that takes a video, crops it, and writes to an output file.

    System Setup:

    OS: Windows 10
    Conda Environment Python Version: 3.7
    OpenCV Version: 3.4.2
    ffmpeg Version: 2.7.0
    

    File Input Specs:

    Codec: H264 - MPEG-4 AVC (part 10)(avc1)
    Type: Video
    Video resolution: 640x360
    Frame rate: 5.056860
    

    Code failing to produce output (it creates the file but doesn't write to it):

    import numpy as np
    import cv2
    
    cap = cv2.VideoCapture('croptest1.mp4')
    
    # Define the codec and create VideoWriter object
    fourcc = cv2.VideoWriter_fourcc('F', 'M', 'P', '4')
    out = cv2.VideoWriter('output.avi', fourcc, 20.0,
                          (int(cap.get(3)), int(cap.get(4))))
    
    # Verify input shape
    width = cap.get(3)
    height = cap.get(4)
    fps = cap.get(5)
    print(width, height, fps)
    
    while(cap.isOpened()):
        ret, frame = cap.read()
        if ret == True:
            # from top left =frame[y0:y1, x0:x1]
            cropped_frame = frame[20:360, 0:640]
    
            # write the clipped frames
            out.write(cropped_frame)
    
            # show the clipped video
            cv2.imshow('cropped_frame', cropped_frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        else:
            break
    
    # Release everything if job is finished
    cap.release()
    out.release()
    cv2.destroyAllWindows()
    

    Variations to fourcc and out variables tried to get codec to work:

    fourcc = cv2.cv.CV_FOURCC(*'DIVX')
    fourcc = cv2.VideoWriter_fourcc(*'DIVX')
    
    out = cv2.VideoWriter('ditch_effort.avi', -1, 20.0, (640, 360))
    

    Based on this link I should be able to refer to this fourcc reference list to determine the appropriate fourcc compression code to use. I have tried a bunch of variations, but cannot get the output file to be written. When I run the code, the #verify input shape variables print the corresponding 640, 360 and correct Frame Rate.

    Can any one tell me what my issue is...would be much appreciated.

  • R.Zane
    R.Zane over 5 years
    I have a question concerning the details. So my out variable must always have the corresponding dimensions such that Y=y1-y0 and X-x1-x0. Is this correct? And lastly, why is the time off by a margin of a few seconds. I tried matching the fps (5.056859927954619) (the 20 I had above was an error), but the time is still off from the original by an added 7 seconds
  • Ha Bom
    Ha Bom over 5 years
    Yes, the writer out must have the corresponding dimensions with the frame you write.
  • Ha Bom
    Ha Bom over 5 years
    What do you mean by time off? The fps you set and the actual fps are different?
  • R.Zane
    R.Zane over 5 years
    To your first answer. Awesome...thanks again very much. To your second, I had a fps of 20 in my 'out' variable in the code above because I pulled it from the website, however, my actual input file has a fps of 5.056860 (as in my above File Input Specs). I tried matching the decimal place the cap.get method gives me (5.056859927954619) and I still get an added 7 seconds (11:02-->11:09) Any idea why?
  • Ha Bom
    Ha Bom over 5 years
    I guess that cv2.waitKey(1) makes a delay of 1 ms every frame so your video is a little bit longer than the original. Also, I've never tried to set fps in that such decimal number.
  • R.Zane
    R.Zane over 5 years
    I wonder if it has to do with the codec I used (FMP4), I will try some others now like (*'DIVX) now that you informed me on the problem of syncing the net value of the dimensions. The cv2.waitKey(1) likely has no effect, as I tested with out that section of code. Anyways, I really appreciate all the help. Thanks very much for you time, patience and effort.