Can't play video created with OpenCV VideoWriter - python

MWE
import cv2
FPS = 30
KEY_ESC = 27
OUTPUT_FILE = "vid.mp4"
cam = cv2.VideoCapture(0)
codec = cv2.VideoWriter.fourcc(*"mp4v") # MPEG-4 http://mp4ra.org/#/codecs
frame_size = cam.read()[1].shape[:2]
video_writer = cv2.VideoWriter(OUTPUT_FILE, codec, FPS, frame_size)
# record until user exits with ESC
while True:
success, image = cam.read()
cv2.imshow("window", image)
video_writer.write(image)
if cv2.waitKey(5) == KEY_ESC:
break
cam.release()
video_writer.release()
Problem
Video does not play.
Firefox reports "No video with supported format and MIME type found.".
VLC reports "cannot find any /moov/trak" "No steams found".

The problem is that np.ndarray.shape, although not properly documented, returns (rows, columns) for a 2d array, which corresponds to (height, width). VideoWriter(frameSize) although not properly documented, seems to expect (width, height).
You can correct this with:
frame_size = tuple(reversed(cam.read()[1].shape[:2]))
But, I recommend creating the VideoWriter using the VideoCapture properties as follows:
output_file = "vid.mp4"
codec = cv2.VideoWriter.fourcc(*"mp4v")
fps = cam.get(cv2.CAP_PROP_FPS)
frame_width = cam.get(cv2.CAP_PROP_FRAME_WIDTH)
frame_height = cam.get(cv2.CAP_PROP_FRAME_HEIGHT)
frame_size = (int(frame_width), int(frame_height))
video_writer = cv2.VideoWriter(output_file, codec, fps, frame_size)
Sources:
VideoWriter()
VideoCapture.get()
https://answers.opencv.org/question/66545/problems-with-the-video-writer-in-opencv-300/
Related:
OpenCV - Video doesn't play after saving in Python
OpenCV VideoWriter: Issues with playing video

Related

How to change mp4 file FPS value 30 to 5 using OpenCV

I want to change the framerate of an mp4 file from 30 to 5.I tried set(cv2.CAP_PROP_FPS, 10).But it did not work. I can't find a way to do this with ffmpeg. Please help me to do this.Thank you.
import cv2
cap = cv2.VideoCapture('./data/video/7e2.mp4')
fps = int(cap.get(cv2.CAP_PROP_FPS))
print('fps :'+str(fps))
if (cap.isOpened()== False):
print("Error opening video stream or file")
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
cv2.imshow('Frame',frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
If you are reading a file then file will not be modified and FPS of the original file will be unchanged. cv2.VideoCapture( ) opens file in read mode. To save a video file you need to use VideoWriter and then open the output file using
video.open(out_filename,VideoWriter::fourcc('M','P','4','V'),FPS, Size(FRAME_WIDTH,FRAME_HEIGHT),true)
And then finally use write function to enter each frame.
So your code will look like this:
cv::VideoWriter video;
video.open(out_filename,VideoWriter::fourcc('M','P','4','V'),FPS, Size(FRAME_WIDTH,FRAME_HEIGHT),true)
In loop {
... Read Each Frame
video.write(frame);
(I have given C++ code, Python code will be similar)
I am providing you the complete code. It should work.
import cv2
cap = cv2.VideoCapture('./data/video/7e2.mp4')
fps = int(cap.get(cv2.CAP_PROP_FPS))
print('fps :'+str(fps))
# Change the FPS whatever you want
FPS=5;
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
writer = cv2.VideoWriter('outpy.avi',cv2.VideoWriter_fourcc('M','J','P','G'), FPS, (frame_width,frame_height) )
if (cap.isOpened()== False):
print("Error opening video stream or file")
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
cv2.imshow('Frame',frame)
writer.write( frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
writer.release()
cap.release()
cv2.destroyAllWindows()

Gstreamer warning: Gstreamer: pipeline has not been created

Trying to run object detection algorithms in jetson nano (ubuntu 18.4) and Gstreamer cannot open the video files because of this warning in the Gstreamer. I have Gstreamer 1.14.5 version. (I tried .avi, .mp4 and .MOV).
It also appeared these warnings:
"Gstreamer warning:unable to start pipeline" and
"Gstreamer warning: Embedded video playback halted; module avidemux0 reported: Internal data stream error."
The code:
if __name__ == '__main__':
args = arg_parse()
confidence = float(args.confidence)
start = 0
CUDA = torch.cuda.is_available()
num_classes = 80
CUDA = torch.cuda.is_available()
videofile = args.video
# start the file video stream thread and allow the buffer to
# start to fill
print("[INFO] starting video file thread...")
fvs = FileVideoStream(videofile).start()
time.sleep(1.0)
# start the FPS timer
fps = FPS().start()
# loop over frames from the video file stream
while fvs.more():
try:
# grab the frame from the threaded video file stream, resize
# it, and convert it to grayscale (while still retaining 3
# channels)
frame = fvs.read()
frame = imutils.resize(frame, width=800)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame = np.dstack([frame, frame, frame])
fps.update()
# stop the timer and display FPS information
fps.stop()
print()
print("[INFO] elasped time: {:.2f}".format(fps.elapsed()))
print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))
print("[INFO] Accuracy: {:.2f}%".format(np.clip((accuracy/(frames+1))*100,1,100)))
PIL_image = Image.fromarray(np.uint8(frame)).convert('RGB')
original_image = PIL_image
# original_image = original_image.convert('RGB')
ret = detect(original_image, min_score=confidence, max_overlap=0.1, top_k=200)
ret = np.asarray(ret)
cv2.imshow("frame", ret)
frames+=1
key = cv2.waitKey(1)
if key & 0xFF == ord('q'):
break
continue
except:
pass
How will i fix it?
Thanks.

OpenCV video not getting saved

I am trying to save a video in OpenCV but i keep getting the error "could not demultiplex stream". I then checked size and found out that it was in kB. I primarily want to save grayscale videos how do i make it possible?
Is there any specific codec i need to use?
mplayer gives the following output
MPlayer 1.1-4.8 (C) 2000-2012 MPlayer Team
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.
Playing output.avi.
libavformat version 54.20.4 (external)
Mismatching header version 54.20.3
AVI file format detected.
[aviheader] Video stream found, -vid 0
AVI: Missing video stream!? Contact the author, it may be a bug :(
libavformat file format detected.
[lavf] stream 0: video (mpeg4), -vid 0
VIDEO: [MP4V] 1280x720 24bpp -nan fps 0.0 kbps ( 0.0 kbyte/s)
Clip info:
encoder: Lavf54.20.4
Load subtitles in ./
Failed to open VDPAU backend libvdpau_nouveau.so: cannot open shared object file: No such file or directory
[vdpau] Error when calling vdp_device_create_x11: 1
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
libavcodec version 54.35.1 (external)
Mismatching header version 54.35.0
Unsupported AVPixelFormat 53
Selected video codec: [ffodivx] vfm: ffmpeg (FFmpeg MPEG-4)
==========================================================================
Audio: no sound
Starting playback...
V: 0.0 0/ 0 ??% ??% ??,?% 0 0
Exiting... (End of file)
Right now i tried with multiple codec formats
import imutils
import cv2
import numpy as np
interval = 30
outfilename = 'output.avi'
threshold=100.
fps = 10
cap = cv2.VideoCapture("video.mp4")
ret, frame = cap.read()
height, width, nchannels = frame.shape
fourcc = cv2.cv.CV_FOURCC(*'DIVX')
out = cv2.VideoWriter( outfilename,fourcc, fps, (width,height))
ret, frame = cap.read()
frame = imutils.resize(frame, width=500)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
while(True):
frame0 = frame
ret, frame = cap.read()
frame = imutils.resize(frame, width=500)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
if not ret:
deletedcount +=1
break
if np.sum( np.absolute(frame-frame0) )/np.size(frame) > threshold:
out.write(frame)
else:
print "Deleted"
cv2.imshow('Feed - Press "q" to exit',frame)
key = cv2.waitKey(interval) & 0xFF
if key == ord('q'):
print('received key q' )
break
cap.release()
out.release()
print('Successfully completed')
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
out = cv2.VideoWriter('output.avi',-1, 20.0, (640,480))
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
gray = cv2.cvtColor(src=frame, code=cv2.COLOR_BGR2GRAY)
out.write(gray)
cv2.imshow('frame', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
Try this one
Select Intel iyuv codec.
The out.avi is non working file.
The output.avi is new working file.
If video is not getting saved, possibly the reason may be its capture size which is hardcoded as (640,480).
You can try the below code:
cap = cv2.VideoCapture(0)
fourcc_codec = cv2.VideoWriter_fourcc(*'XVID')
fps = 20.0
capture_size = (int(cap.get(3)), int(cap.get(4)))
out = cv2.VideoWriter("output.avi", fourcc_codec, fps, capture_size)
You can also check if you are passing the correct shape, do it like this:
h, w, _ = frame.shape
size = (w, h)
out = cv2.VideoWriter('video.avi', cv2.VideoWriter_fourcc(*'XVID'), 30, size)

Getting very high fps for video stream captured and stored using opencv

I've written a small python code, which captures video stream from the webcam, and writes it into an output file.
I've put a sleep of 50 ms, and specified a fps of 20.0 in the VideoWriter as following:
#!/usr/bin/python
import cv2
from PIL import Image
import threading
from http.server import BaseHTTPRequestHandler,HTTPServer
from socketserver import ThreadingMixIn
from io import StringIO,BytesIO
import time
import datetime
capture=None
out=None
class CamHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path.endswith('.mjpg'):
self.send_response(200)
self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
self.end_headers()
while True:
try:
rc,img = capture.read()
if not rc:
continue
#Get the timestamp on the frame
timestamp = datetime.datetime.now()
ts = timestamp.strftime("%A %d %B %Y %I:%M:%S%p")
cv2.putText(img, ts, (10, img.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)
#Store the frame into the output file
out.write(img)
#Some processing before sending the frame to webserver
imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
jpg = Image.fromarray(imgRGB)
tmpFile = BytesIO()
jpg.save(tmpFile,'JPEG')
self.wfile.write("--jpgboundary".encode())
self.send_header('Content-type','image/jpeg')
self.send_header('Content-length',str(tmpFile.getbuffer().nbytes))
self.end_headers()
jpg.save(self.wfile,'JPEG')
time.sleep(0.05)
except KeyboardInterrupt:
break
return
if self.path.endswith('.html'):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write('<html><head></head><body>'.encode())
self.wfile.write('<img src="http://127.0.0.1:8080/cam.mjpg"/>'.encode())
self.wfile.write('</body></html>'.encode())
return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""Handle requests in a separate thread."""
def main():
global capture
global out
capture = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
global img
try:
server = ThreadedHTTPServer(('0.0.0.0', 8080), CamHandler)
print( "server started")
server.serve_forever()
except KeyboardInterrupt:
capture.release()
server.socket.close()
out.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
It works fine, and I'm able to get the video saved. However, the fps as seen in property of the video is 600.0 (30X what I set!!)
$ mediainfo output.avi
General
Complete name : output.avi
Format : AVI
Format/Info : Audio Video Interleave
File size : 4.95 MiB
Duration : 17s 252ms
Overall bit rate : 2 408 Kbps
Writing application : Lavf58.3.100
Video
ID : 0
Format : MPEG-4 Visual
Format profile : Simple#L1
Format settings, BVOP : No
Format settings, QPel : No
Format settings, GMC : No warppoints
Format settings, Matrix : Default (H.263)
Codec ID : XVID
Codec ID/Hint : XviD
Duration : 17s 252ms
Bit rate : 2 290 Kbps
Width : 640 pixels
Height : 480 pixels
Display aspect ratio : 4:3
Frame rate : 600.000 fps
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Compression mode : Lossy
Bits/(Pixel*Frame) : 0.012
Stream size : 4.71 MiB (95%)
Writing library : Lavc58.6.103
I'm pretty sure my code looks alright, do let me know if there are any obvious mistakes. In case it matters, I'm using an ubuntu OS, Asus X553M laptop with inbuilt webcam to run the above.
EDIT 1:
I'm using python3, if that matters
EDIT 2:
Using MJPG codec did solve the problem, (thanks #api55) so can someone tell me why XVID would give the incorrect fps?
Is it possible that XVID codec incorrectly writes the fps property, while the video is actually correctly coded in 20 fps?
You getting frames every 50 ms + processing time, but writing them to video with delay 50ms, so they will be played with higher speed with ratio=(50+processing time)/ 50ms.
I have this recipe, it's pretty similar to what Andrey answered. The fps gets pretty close to what's expected.
cap = cv2.VideoCapture(capture) # 0 | filepath
fps = cap.get(cv2.CAP_PROP_FPS)
period = 1000 / fps
while cap.isOpened():
start = time.time()
success, frame = cap.read()
if not success:
if capture:
break # video
continue # cam
# processing steps
cv2.imshow('video (ESC to quit)', frame)
processing_time = (time.time() - start) * 1000
wait_ms = period - processing_time if period > processing_time else period
if cv2.waitKey(int(wait_ms)) & 0xFF == 27:
break
end = (time.time() - start)
print(f'FPS: {1.0 / end:.2f} (expected {fps:.2f})\r', end='')

OpenCv - cv2.VideoWriter object has no attribute release

I am using OpenCV with python 2.7.3 on Linux 64-bit machine. I wanted to fetch frames from my Logitech C270 and store it as an AVI video. The code is working fine, it also shows me the video getting captured and the output file is also created. But when i try to play the file it is not playing at all as well as i am getting 'cv2.VideoWriter object has no attribute release' error on terminal. So, if someone can tell me how to release the cv2.VideoWriter after completion.
import numpy as np
import cv2
cap = cv2.VideoCapture(1)
fourcc = cv2.cv.CV_FOURCC('X','V','I','D')
out = cv2.VideoWriter('output.avi', fourcc, 20.0,(640,480))
while(True):
ret, frame = cap.read()
if cap.isOpened() == 0:
cap.open(1)
if ret==True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
out.write(gray)
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
Instead of using the lines below:
fourcc = cv2.cv.CV_FOURCC('X','V','I','D')
out = cv2.VideoWriter('output.avi', fourcc, 20.0,(640,480))
Use those one:
fourcc = cv2.VideoWriter_fourcc(*'DIVX')
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (int(cap.get(3)),int(cap.get(4))))
I think, this will help you.
Instead of using this line
fourcc = cv2.cv.CV_FOURCC('X','V','I','D')
Use this one
fourcc = cv2.VideoWriter_fourcc(*'XVID')

Categories