Kek Lmao
Kek Lmao

Reputation: 53

Downloading an MJPEG stream frame by frame

I've got an IP camera set up and I can browse to its IP and get an MJPEG stream, I'm trying to download it frame by frame so I can analyse the images on another server. However I'm having troubles reading the stream. My code is:

import cv2
import urllib.request
import numpy as np
import ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE       

stream = urllib.request.urlopen('https://x.x.x.x:8602/Interface/Cameras/GetJPEGStream?Camera=Bosch%20NBE6502AL%20Bullet&ResponseFormat=XML&AuthUser=username&AuthPass=password',context=ctx)
bytes = ''
while True:
    bytes += stream.read(1024)
    a = bytes.find('\xff\xd8')
    b = bytes.find('\xff\xd9')
    if a != -1 and b != -1:
        jpg = bytes[a:b+2]
        bytes = bytes[b+2:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.CV_LOAD_IMAGE_COLOR)
        cv2.imshow('i', i)
        if cv2.waitKey(1) == 27:
            exit(0)  

It gives me the following error:

Traceback (most recent call last):
File "mjpeg.py", line 15, in <module>
bytes += stream.read(1024)
TypeError: can only concatenate str (not "bytes") to str

I think the stream outputs strings, but how do I go about converting the stream to bytes and saving the file?

Kind regards,

Ellens

Upvotes: 2

Views: 2057

Answers (3)

Alif Jahan
Alif Jahan

Reputation: 795

concatenation works only on same type of value like

string with a string str += str
bytes with a bytes bytes += bytes 

so set your bytes variable as bytes = b''. Hope that will work fine.

import cv2
import urllib.request
import numpy as np
import ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE       

stream = urllib.request.urlopen('https://x.x.x.x:8602/Interface/Cameras/GetJPEGStream?Camera=Bosch%20NBE6502AL%20Bullet&ResponseFormat=XML&AuthUser=username&AuthPass=password',context=ctx)
bytes = b''# MAKE IT BYTES
while True:
    bytes += stream.read(1024)
    a = bytes.find('\xff\xd8')
    b = bytes.find('\xff\xd9')
    if a != -1 and b != -1:
        jpg = bytes[a:b+2]
        bytes = bytes[b+2:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.CV_LOAD_IMAGE_COLOR)
        cv2.imshow('i', i)
        if cv2.waitKey(1) == 27:
            exit(0)

Upvotes: 1

user10417531
user10417531

Reputation:

Your bytes variable is str when initialized (bytes = '') and not (bytes= b''), change this

stream = urllib.request.urlopen('https://x.x.x.x:8602/Interface/Cameras/GetJPEGStream?Camera=Bosch%20NBE6502AL%20Bullet&ResponseFormat=XML&AuthUser=username&AuthPass=password',context=ctx)
bytes = ''
while True:

to this

stream = urllib.request.urlopen('https://x.x.x.x:8602/Interface/Cameras/GetJPEGStream?Camera=Bosch%20NBE6502AL%20Bullet&ResponseFormat=XML&AuthUser=username&AuthPass=password',context=ctx)
bytes = b''
while True:

you can check for yourself like this

>>> type('') == type(b'')
False
>>> type(''),type(b'')
(<class 'str'>, <class 'bytes'>)

Upvotes: 0

AKX
AKX

Reputation: 169194

You'll need to be bytesy throughout, so initialize bytes (which, btw, isn't the best of names as that's the builtin type's name too) as a bytestring, and use bytes literals to find the start/end markers:

bytes = b''
while True:
    bytes += stream.read(1024)
    a = bytes.find(b'\xff\xd8')
    b = bytes.find(b'\xff\xd9')
    if a != -1 and b != -1:
        # ...

Upvotes: 0

Related Questions