Hey guys, in these tough corona times, all of you might have been using various Video Conferencing tools such as Zoom, Google Meet, MS Teams, etc. While these are pretty big and stable, how awesome will it be to create a simple video conferencing app which you can customise to anything and only allow you and your friends to access the call?
We will be creating a simple server client setup where the server would be broadcasting it’s video to a specific channel and all clients connected to the server would receive the video. In the demo below, we are deploying it on the same machine, but the server and client can be on any place on earth, connected to same channel, as explained in the last.
- Python v3.6+ (preferable Python 3.8)
- Broadcasting System / Message Queue – Redis Pub/Sub (you can use Kafka, AWS SQS/ EventBridge, RabbitMQ, etc)
- OpenCV to capture and present video images.
I personally like Redis Pub/Sub as it is too easy to setup and spin up the message queue in just 3 lines of code.It is also very scalable and performant for huge Production Setups, but you are free to use Kafka, RabbitMQ or any managed service like AWS SQS as per your wish.
That’s it..! Just 3 simple ingredients and about 20 lines of code will make you through it..!
- Run the following command to start the Redis server using docker image of Redis.
docker run --name redis -d -p 6379:6379 redis
- Change directory to your desired folder and create a virtual environment. Install the Redis and Open CV library, then create 2 python files, one for server and one for client.
mkdir project cd project virtualenv venv -p python3 source venv/bin/activate pip install redis opencv-python touch server.py client.py
- Now add the following code to server.py which will create a server with Redis Pub/Sub server and an Open CV video capture connection. Line 5 shows we are connecting to source 0 of our computer which is the webcam. You can connect to any source / open any video file.
import cv2 import redis server = redis.Redis() video = cv2.VideoCapture(0) height = int(video.get(4) / 2) width = int(video.get(3) / 2) while video.isOpened(): ret, frame = video.read() if ret: frame = cv2.resize(frame, (width, height)) server.publish("eazy_devflix", frame.tobytes()) video.release()
As seen above, the program is reading every frame recorded from our webcam and resizing it on Line 13 to a specific height/width ratio. It then publishes that frame (converted to bytes) to the eazy_devflix channel of Redis Pub/Sub. All clients listening on this will receive this frame as a message.
- Now add the following code in your client.py which will create a connection to eazy_devflix Redis Pub/Sub channel and listens to each message. When a message is received, it then changes the bytes information to an image frame and resizes it to current ratio as set by server. Once frame is ready, it then outputs the same on your screen, making it see as a video.
import cv2 import redis from datetime import datetime import numpy as np client = redis.Redis() client_channel = client.pubsub() client_channel.subscribe("netflix") for item in client_channel.listen(): if item["type"] != "message": continue frame = np.frombuffer(item["data"], dtype="uint8").reshape(360, 640, 3) cv2.imshow("Frame", frame) if cv2.waitKey(1) & 0xFF == ord("q"): break client_channel.unsubscribe() cv2.destroyAllWindows()
- To close the video, press the “q“ button.
As you can see, the server is recording your video, and broadcasting it to the eazy_devflix channel. The client then picks the broadcasted messages and shows it on the cline’t screen.
The next challenge is to use the same concept in transferring audio content and to make it two sided communication. I am hoping you guys will try it and do share with me on comments if you try..!