writing a video without any loss in data or bitrate - opencv (python)

1.9k Views Asked by At

I am trying to write a video file without any loss in OpenCV, but so far any codec that I have selected from fourcc codec lists somehow results in loss of data.

regarding the recording parameters I am using:

fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

used these codecs so far but they either to compression or upsize video bit rate

fourcc = cv2.VideoWriter_fourcc(*'MP4V') 
fourcc = cv2.VideoWriter_fourcc(*'DIVX') 
fourcc = cv2.VideoWriter_fourcc(*'RGBA') 
fourcc = cv2.VideoWriter_fourcc(*'x265') 
fourcc = cv2.VideoWriter_fourcc('H','2','6','4')

my video writer function is:

writer= cv2.VideoWriter(out_dest, fourcc, fps, (width,height))

Just to be clear, I do not want any sort of compression for the output video.

I also use

vid_format = int(cap.get(cv2.CAP_PROP_FOURCC))

to get the output video bit rate and compare it to the original video.

I also found someone on GitHub using skvideo but wasn't able to perform the same code

https://gist.github.com/docPhil99/a612c355cd31e69a0d3a6d2f87bfde8b

as it kept showing an extension error and couldn't find proper documentation on how to use it!

Thank you in advance

An Update on the topic:

the final output writer codec will be used as the video writer for BGR to RGB conversion in OpenCV, if you have any other ideas or suggestions that can do the job, I'm all ears!

1

There are 1 best solutions below

0
On

If all you need to do is to get RGB data out of raw AVI file and feed the RGB frame data with MediaPipe, there is no need for intermediate file to store RGB data because FFmpeg can convert the pixel format on the fly by specifying output -pix_fmt rgb24 option.

To do this, you can try my ffmpegio package to load the data. My package is designed for your use case to remove the need to set up FFmpeg call. To install:

pip install ffmpegio

You also need FFmpeg in the system.

Then video.read() loads the video data:

import ffmpegio

fs, I = ffmpegio.video.read('datafile.avi',pix_fmt='rgb24')
# fs = framerate
# I = 250x480x640x3 numpy array containing RGB video data

If you don't want to read all 250 frames at once, you can use the stream interface to work on X number of frames at a time:

with ffmpegio.open('datafile.avi','rv', blocksize=25, pix_fmt='rgb24') as f:
    for I in f: # loops 10 times, 25 frames at a time
        # I = 25x480x640x3 numpy array