Reputation: 32081
This works fine:
import cv2
cv2.VideoCapture('somevideo.mp4').isOpened()
> True
This throws an exception:
import cv2
f = open('somevideo.mp4', 'rb')
cv2.VideoCapture(f)
> TypeError: an integer is required (got type _io.BufferedReader)
I would like the latter example to work because I have a Python file-like object that abstracts the location of the file (not a standard OS filesystem).
Can OpenCV be coaxed into accepting a standard python file-like object? From this exception it looks like it will only support a file descriptor or filename string.
Upvotes: 4
Views: 1737
Reputation: 23032
OpenCV is a C++ library with Python bindings auto-generated. Partly because of that, in general, the Python library is not really extensible or flexible at all. The parameter you send into the function gets sent to C++, and you will get an error on anything it's not expecting. From the latest docs, the available constructors for a VideoCapture
object are:
VideoCapture ()
Default constructor. More...
VideoCapture (const String &filename, int apiPreference=CAP_ANY)
Opens a video file or a capturing device or an IP video stream for video capturing with API Preference. More...
VideoCapture (int index, int apiPreference=CAP_ANY)
Opens a camera for video capturing. More...
So you can see the only valid signatures contain either an integer index for the device number, or a string which is expected to be a filename. The open()
method has the same expectations on signatures.
OpenCV doesn't really provide first class support for video; instead it relies on a number of possible backend libraries. Your best bet if you want swap-ability is just to copy the API and use some other library (perhaps ffmpeg
) to decode the raw binary stream.
Another idea would be to create a webserver and serve the data. OpenCV accepts URLs in addition to filenames. This introduces latency though, even when serving locally, so it's not a great option (but if the video is remote anyways, then maybe it's not a bad idea).
Upvotes: 3