I'm using mss, numpy, and OpenCV to make my own recording software, but when I record, all of my videos end up with a 258 bytes file size (no matter the length of the video), and I can't view the video. No frames seem to be in my videos. What am I doing wrong?
Here's my code, any help would be greatly appreciated:
import datetime
import numpy as np
import cv2
import mss
import mss.tools
time_stamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
fourcc = cv2.VideoWriter_fourcc("m", "p", "4", "v")
captured_video = cv2.VideoWriter(f"{time_stamp}.mp4", fourcc, 20.0, (1080, 720))
with mss.mss() as sct:
monitor = {"top": 0, "left": 0, "width": 1080, "height": 720}
while True:
img = np.array(sct.grab(monitor))
img_final0 = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
img_final = cv2.cvtColor(img_final0, cv2.COLOR_BGR2RGB)
cv2.imshow('LevelRecorder', img_final)
capture = captured_video.write(img_final)
print(capture)
if cv2.waitKey(10) == ord("q"):
break
CodePudding user response:
The "258 bytes" file size is useful information. Since your files are tiny, VideoWriter actually doesn't even write any video data.
- Make sure the frames you
write()
are sized 1080 by 720 and 3-channel (shape(720, 1080, 3)
), as you announced in the constructor of the VideoWriter object. - You are missing a
captured_video.release()
call. MP4 files will be corrupted if they aren't properly finalized, even if video data actually makes it into the file. - Those
cvtColor
operations make no sense. You simply convert back and forth. - Look at the Video I/O section in
print(cv.getBuildInformation())
and confirm that you have ffmpeg support. Without that,mp4v
video and.mp4
container will not be available.
When in doubt, use MJPG
fourcc and .avi
container. Those two are built into OpenCV, always available.
CodePudding user response:
At last, I finally found my answer. Turns out, this problem had a super simple solution that I somehow missed this entire time.
As it turns out, either NumPy or Open Cv (I don't know which of the two), really really hates mss, but really likes Python Pillow, so, all you have to do is convert it to an image like Python Pillow, and there you go! Here's my new code (which works for me)
import datetime
from PIL import Image
import numpy as np
import cv2
from mss import mss
time_stamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
fourcc = cv2.VideoWriter_fourcc("m", "p", "4", "v")
captured_video = cv2.VideoWriter(f"{time_stamp}.mp4", fourcc, 20.0, (2880, 1800), 3)
sct = mss()
while True:
img0 = sct.grab(sct.monitors[1])
img_PIL = Image.frombytes('RGB', img0.size, img0.bgra, 'raw', 'BGRX') #This is where we convert it to a Pillow-like image
img1= np.array(img_PIL) #Sorry about my variables, I was too lazy to change them :P
img = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
cv2.imshow('LevelRecorder', img)
captured_video.write(img)
if cv2.waitKey(1) == ord("q"):
cv2.destroyAllWindows()
break
So there it is! Just use Python Pillow to convert each frame into something NumPy and Open Cv like using Image.frombytes(). Thank you so much Christoph Rackwitz for helping , I can not bring forth into words how much of a great help you have been :)