├── README.md ├── client.py ├── main.py ├── requirements.txt ├── stream.py └── templates └── index.html /README.md: -------------------------------------------------------------------------------- 1 | ## Distributed Live Streaming with ZeroMQ and Flask Socket Connection 2 | 3 | ```python 4 | pip install requirements.txt 5 | 6 | ``` 7 | ### Run Server 8 | ```python 9 | python main.py 10 | ``` 11 | ```python 12 | python client.py 13 | ``` 14 | ### Now Browse 15 | - [http://127.0.0.1:5000/](http://127.0.0.1:5000/) 16 | 17 | #### Use Built-in Webcam of Laptop 18 | ##### Put Zero (O) in cv2.VideoCapture(0) 19 | ```python 20 | cv2.VideoCapture(0) 21 | 22 | ``` 23 | #### Use Ip Camera/CCTV/RTSP Link 24 | ```python 25 | cv2.VideoCapture('rtsp://username:password@camera_ip_address:554/user=username_password='password'_channel=channel_number_stream=0.sdp') 26 | 27 | ``` 28 | #### Example RTSP Link 29 | ```python 30 | cv2.VideoCapture('rtsp://mamun:123456@101.134.16.117:554/user=mamun_password=123456_channel=0_stream=0.sdp') 31 | 32 | ``` 33 | #### Change Channel Number to Change the Camera 34 | ```python 35 | cv2.VideoCapture('rtsp://mamun:123456@101.134.16.117:554/user=mamun_password=123456_channel=1_stream=0.sdp') 36 | 37 | ``` 38 | #### Display the resulting frame in browser 39 | ```python 40 | cv2.imencode('.jpg', frame)[1].tobytes() 41 | 42 | ``` 43 | -------------------------------------------------------------------------------- /client.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import cv2 3 | import zmq 4 | 5 | context = zmq.Context() 6 | footage_socket = context.socket(zmq.PUB) 7 | footage_socket.bind('tcp://*:5555') 8 | 9 | camera = cv2.VideoCapture(0) # init the camera 10 | 11 | while True: 12 | grabbed, frame = camera.read() # grab the current frame 13 | frame = cv2.resize(frame, (640, 480)) # resize the frame 14 | encoded, buffer = cv2.imencode('.jpg', frame) 15 | jpg_as_text = base64.b64encode(buffer) 16 | footage_socket.send(jpg_as_text) 17 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, Response 2 | from stream import streamer 3 | 4 | app = Flask(__name__) 5 | 6 | def gen(): 7 | 8 | while True: 9 | stream = streamer() 10 | yield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + stream + b'\r\n\r\n') 11 | 12 | @app.route('/') 13 | def index(): 14 | return render_template('index.html') 15 | 16 | @app.route('/camera') 17 | def camera(): 18 | return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame') 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | opencv-python 3 | zmq -------------------------------------------------------------------------------- /stream.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import zmq 3 | import base64 4 | import numpy as np 5 | 6 | context = zmq.Context() 7 | footage_socket = context.socket(zmq.SUB) 8 | footage_socket.connect('tcp://localhost:5555') 9 | 10 | footage_socket.setsockopt_string(zmq.SUBSCRIBE, np.unicode('')) 11 | 12 | 13 | def streamer(): 14 | while True: 15 | frame = footage_socket.recv_string() 16 | img = base64.b64decode(frame) 17 | npimg = np.fromstring(img, dtype=np.uint8) 18 | source = cv2.imdecode(npimg, 1) 19 | return cv2.imencode('.jpg', source)[1].tobytes() 20 | 21 | # source.tobytes() 22 | 23 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | Live Streaming Demonstration 13 | 14 | 15 |
16 |
17 |
18 |

Live Streaming

19 | 20 |
21 |
22 |
23 | 24 | --------------------------------------------------------------------------------