Reputation: 465
I am new to python (2.7) and opencv (3.0) (and video streaming/writing in general) so forgive this.
I am using the logitech c920 as my webcam and it can stream video compressed in h264 format so I am trying to write a simple app that sets 4 properties of the VideoCapture instance (fourcc to h264; width to 1920; height to 1080; and fps to 30), and then records a video to the directory one level up named test.mp4 and shows the recording on my screen. Here is code:
import sys
import cv2 as cv
cap = cv.VideoCapture(0)
fourcc = cv.VideoWriter_fourcc('H','2','6','4')
cap.set(6, fourcc)
cap.set(3,1920)
cap.set(4,1080)
cap.set(5, 30)
vid = cv.VideoWriter('../test.mp4', fourcc, 20.0, (640,480))
print vid.isOpened() #returns false :(
while (cap.isOpened()):
ret, frame = cap.read()
if (ret == True):
#gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
vid.write(frame)
cv.imshow('window', frame)
if (cv.waitKey(1) & 0xFF == ord('q')):
break
cap.release()
vid.release()
cv.destroyWindow('window')
cv.imshow('window',frame) works just fine, and the properties are all set; however, vid.isOpened() return false so clearly I have done something wrong in the above. If I pass -1 for the fourcc, I am allowed to pick from a list of codecs and i420 is available and says (for logitech cameras) and vid.isOpened() returns true if I change the file extension from mp4 to avi (I guess that means i420 cannot be stored as .avi ?), however, test.avi is always huge and seemingly raw, 100MB for a few second test video and will not open.
Any help with this would be great, thanks a lot
Upvotes: 7
Views: 29499
Reputation: 184
If Someone is still searching for an answer, you can try this.
pip install av
import av
import cv2
capture_device_index = 0
video_width = 1920
video_height = 1080
fps = 30
output_file = "output_video.mp4"
# Initialize OpenCV for capturing video
cap = cv2.VideoCapture(capture_device_index)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, video_width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, video_height)
cap.set(cv2.CAP_PROP_FPS, fps)
# Initialize PyAV for encoding
container = av.open(output_file, mode='w')
stream = container.add_stream("h264", rate=fps)
stream.width = video_width
stream.height = video_height
stream.pix_fmt = "yuv420p"
if not cap.isOpened():
print("Error: Unable to open capture device.")
exit()
try:
print("Recording... Press 'q' to stop.")
while True:
ret, frame = cap.read()
if not ret:
print("Error: Failed to grab frame.")
break
# Convert frame to AVFrame for encoding
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
av_frame = av.VideoFrame.from_ndarray(frame_rgb, format="rgb24")
for packet in stream.encode(av_frame):
container.mux(packet)
# Display the frame (optional)
cv2.imshow("Capture", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Flush remaining packets
for packet in stream.encode():
container.mux(packet)
finally:
cap.release()
container.close()
cv2.destroyAllWindows()
print(f"Video saved as: {output_file}")
Upvotes: 0
Reputation: 1
Another way is to use conda environment Steps:
a) conda --version (should not be found at first)
b1) wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh -O miniconda.sh (Jetson)
OR
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
b2) bash miniconda.sh -b -p /opt/conda
c) rm miniconda.sh
d) export PATH="/opt/conda/bin:${PATH}"
e) conda --version (should show the version)
f) conda install -c conda-forge opencv
g) avc1 should work now/H264 should be supported
Also use '*avc1' instead, it is also outputs in H264 format
Upvotes: 0
Reputation: 637
Upvotes: 7
Reputation: 6622
If you installed this package via pip install opencv-python then there's no encoding support for x264 because it's under GPL license. Upgrading FFmpeg won't help because opencv-python ships with its own FFmpeg.
You'll have to compile OpenCV manually to get support for H264 encoding.
Related issue on Github: https://github.com/skvark/opencv-python/issues/100#issuecomment-394159998
Upvotes: 4
Reputation: 151
So the workaround I found so far is not that efficient but it works for me on Ubuntu 16.04. After writing the video regularly, I convert it again using H264 coder and the final video size is much smaller than the one I got from opencv alone.
Here is the workaround:
import os # We will use it to access the terminal
# Write the video normally using mp4v and make the extension to be '.mp4'
# Note: the output using "mp4v" coder may be efficient for you, if so, you do not need to add the command below
cv2.VideoWriter('Video.mp4',cv2.VideoWriter_fourcc(*"mp4v"), NewFPS, (width,height))
# When your video is ready, just run the following command
# You can actually just write the command below in your terminal
os.system("ffmpeg -i Video.mp4 -vcodec libx264 Video2.mp4")
Upvotes: 14