7

I have a working python script that uses the video writer from opencv.

source https://gist.github.com/stanchiang/b4e4890160a054a9c1d65f9152172600


If i take in a file, and regardless of whether I simply pass the video frame through to the writer (effectively duplicating the file) or if i try to edit the frame, the file is always larger. I would like for it to be no larger than the original (since if you read my script i'm blurring a lot of stuff).

After checking their metadata, with ffprobe -v quiet -print_format json -show_format -show_streams inputFile.mp4 I notice that the bitrate of the new file is over 5.5x higher than before.

source https://www.diffchecker.com/8r2syeln


since bitrate is a big determinant of file size, I'm wondering if

  1. i can hardcode the desired bitrate of the new file through the video writer
  2. whether for some reason the heavily increased bit rate is needed
stanley
  • 1,113
  • 1
  • 12
  • 26
  • You may want to switch to FFmpeg, as control of all video parameters is excellent there, and from my experience, the bitrate of the output won't be changed from the input. – boardrider Aug 01 '16 at 12:22
  • Can't switch all the way over right? The script edits the video frame by frame using an opencv algorithm. Is there a way I can use ffmpeg to write to a new video frame by frame? – stanley Aug 01 '16 at 16:09
  • @stanley No. The only way with your method is to completely write the video using OpenCV by generating all of the frames, then when you're done you use FFMPEG to compress the video by altering the bitrate. However, it's possible to directly send RGB data to FFMPEG using pipes but that does not use OpenCV. – rayryeng Aug 02 '16 at 02:34
  • @rayryeng if I can send rgb data to ffmpeg, then might there be a way to turn my opencv edited frame into rgb data to be used by ffmpeg? How would that code look? – stanley Aug 02 '16 at 02:51
  • Try this post. http://stackoverflow.com/q/32477586/3250829. – rayryeng Aug 02 '16 at 02:54
  • Thanks for the lead! – stanley Aug 02 '16 at 02:57
  • No problem. Remember to read the comment in the comment stream about the mistake you need to correct to make the code work. The nice thing about that post is that it writes numpy arrays to the ffmpeg pipe. OpenCV images are contained within numpy arrays so it will require very little work given that post. All in all, I would avoid using OpenCV VideoWriter if you want to make videos. For ones with a small amount of frames, sure no problem but not for larger ones. Let me know how it goes! – rayryeng Aug 02 '16 at 03:07
  • If it does work, I'd love to write an answer to help the community for the future. – rayryeng Aug 02 '16 at 03:11
  • 1
    Also try this one too: http://stackoverflow.com/q/13294919/3250829 – rayryeng Aug 02 '16 at 04:33

2 Answers2

5

basically this answer https://stackoverflow.com/a/13298538/1079379

# import packages
from PIL import Image
from subprocess import Popen, PIPE
from imutils.video import VideoStream
from imutils.object_detection import non_max_suppression
from imutils import paths
import cv2
import numpy as np
import imutils

# ffmpeg setup
p = Popen(['ffmpeg', '-y', '-f', 'image2pipe', '-vcodec', 'mjpeg', '-r', '24', '-i', '-', '-vcodec', 'h264', '-qscale', '5', '-r', '24', 'video.mp4'], stdin=PIPE)

video = cv2.VideoCapture('videos.mp4')

while True:
    ret, frame = video.read()
    if ret:
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        im = Image.fromarray(frame)
        im.save(p.stdin, 'JPEG')
    else:
        break

p.stdin.close()
p.wait()
video.release()
cv2.destroyAllWindows()
Community
  • 1
  • 1
stanley
  • 1,113
  • 1
  • 12
  • 26
0

My VidGear Python Library's WriteGear API automates the process of pipelining OpenCV frames into FFmpeg on any platform and at the same time provides same opencv-python syntax. Here's a basic python example:

# import libraries
from vidgear.gears import WriteGear
import cv2

output_params = {"-vcodec":"libx264", "-crf": 0, "-preset": "fast"} #define (Codec,CRF,preset) FFmpeg tweak parameters for writer

stream = cv2.VideoCapture(0) #Open live webcam video stream on first index(i.e. 0) device

writer = WriteGear(output_filename = 'Output.mp4', compression_mode = True, logging = True, **output_params) #Define writer with output filename 'Output.mp4' 

# infinite loop
while True:
    
    (grabbed, frame) = stream.read()
    # read frames

    # check if frame empty
    if not is grabbed:
        #if True break the infinite loop
        break
    

    # {do something with frame here}
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)


    # write a modified frame to writer
    writer.write(gray) 
       
        # Show output window
    cv2.imshow("Output Frame", frame)

    key = cv2.waitKey(1) & 0xFF
    # check for 'q' key-press
    if key == ord("q"):
        #if 'q' key-pressed break out
        break

cv2.destroyAllWindows()
# close output window

stream.release()
# safely close video stream
writer.close()
# safely close writer

Source:https://abhitronix.github.io/vidgear/latest/gears/writegear/compression/usage/#using-compression-mode-with-opencv

You can check out VidGear Docs for more advanced applications and features.

abhiTronix
  • 1,248
  • 13
  • 17