0

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!

Jamiu S.
  • 5,257
  • 5
  • 12
  • 34
Amirez
  • 1
  • 2
  • See https://superuser.com/a/1429266/1669011 and convert it to OpenCV call. If it doesn't support it, use ffmpeg – kesh Mar 21 '22 at 14:27
  • What is the source of the video you intend to record? Are you planning to record a video stream that is already encoded (e.g. video from camera), or is it raw video frames (stored in NumPy arrays)? "Without any loss in data or bitrate" - what is the resolution and what is the bitrate? – Rotem Mar 21 '22 at 15:10
  • @kesh I tried ffmpeg but I lost 2/3 of my bitrate in the process – Amirez Mar 21 '22 at 21:53
  • @Rotem the source is an .avi video loaded locally (recorded from a webcam). final goal is to convert the video format from BGR to RGB for mediapipe purposes. The video meta data are as follows: Format : AVI File size : 220 MiB Duration : 10 s 0 ms Overall bit rate : 184 Mb/s Format : RGB Duration : 10 s 0 ms Bit rate : 184 Mb/s Width : 640 pixels Height : 480 pixels Display aspect ratio : 4:3 Frame rate : 25.000 FPS Bit depth : 8 bits Bits/(Pixel*Frame) : 24.000 Stream size : 220 MiB (100%) – Amirez Mar 21 '22 at 21:57
  • @kesh ffmpeg results: Format : MPEG-4 File size : 37.8 MiB Duration : 10 s 0 ms Overall bit rate : 31.7 Mb/s Format : AVC Format settings, ReFrames : 16 frames Duration : 10 s 0 ms Bit rate : 31.7 Mb/s Width : 640 pixels Height : 480 pixels Display aspect ratio : 4:3 Frame rate mode : Constant Frame rate : 25.000 FPS Bit depth : 8 bits Bits/(Pixel*Frame) : 4.126 Stream size : 37.8 MiB (100%) Writing library : x264 core 164 – Amirez Mar 21 '22 at 22:04
  • @rookie - you do realize the bitrate would be lower for losslessly compressed bitstream, right? You need to compare the decoded pixels to confirm if the stream is indeed lossless. (just making sure) – kesh Mar 21 '22 at 22:09
  • @kesh yes, that is considered but when comparing the Bits/(pixel*frame) value, for FFmpeg I have so far managed to get 7.728 but the original video is 24 – Amirez Mar 21 '22 at 22:43
  • @rookie - What you are saying is analogous to concerning a zip file containing a text file does not match its filesize/#characters compared to that of the unzipped text file. – kesh Mar 21 '22 at 23:26
  • @kesh a quick question? given that fps and video dimension remain constant, is there any metric that guarantees bit rate fluctuation doesn't result in data written /s in every frame? how can I be sure that the amount of pixels/frame remains unchanged when writing the video? since the final video will be converted to an np array and signals will be extracted from that array, every bit of data counts. I am not decompressing anything, I am basically looking for a way to keep everything as intact as possible for the sake of my experiment – Amirez Mar 21 '22 at 23:46

1 Answers1

0

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
kesh
  • 4,515
  • 2
  • 12
  • 20