Video Streaming using Python

In this article, I am going to explain how we can create a video chat app using Python OpenCV and Socket Programming.

For this practical, I am going to use Python OpenCV and Socket Programming so let’s first understand Python OpenCV and Socket Programming.

Python OpenCV

OpenCV-Python makes use of Numpy, which is a highly optimized library for numerical operations with a MATLAB-style syntax. All the OpenCV array structures are converted to and from Numpy arrays. This also makes it easier to integrate with other libraries that use Numpy such as SciPy and Matplotlib.

Socket Programming in Python

Socket programming is started by importing the socket library and making a simple socket.

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Here we have created a socket with two parameters. The first parameter is AF_INET and the second one is SOCK_STREAM. AF_INET refers to the address-family ipv4 and SOCK_STREAM means connection-oriented TCP protocol.

What is a Network Socket?

A socket address is the combination of protocol type, IP address, and Port number for data communication. A remote process establishes a socket in its connection to its protocol stack and then uses network API to connect to the application. It presents its own socket address for use.

In standard internet protocols like TCP and UDP socket address is the combination of socket address = (IP address, port number)

Types of Internet Sockets:

  • Datagram sockets: Datagram sockets allow processes to use UDP to communicate. A datagram socket supports a bidirectional flow of messages. A process on a datagram socket can receive messages in a different order from the sending sequence and can receive duplicate messages.
  • Raw sockets: Raw sockets provide access to ICMP. These sockets are normally datagram-oriented, although their exact characteristics are dependent on the interface provided by the protocol. Raw sockets are not for most applications.

Client-Server Model in Network Programming

At first, the server will create the socket and will go to the listening mode. Initially, the server will not require the IP address of the client but the client will know the IP address and port number of the server to connect.

Video Chat App using Python

For creating Video Chat App using Python I am going to create two files in python one is for the client-side and the other is for the server-side. I will use the stream socket where the server code with extracting the video from the server webcam and then it will send that video to the client using socket programming.

Server-side Python Code:

server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

Then I am going to bind the socket with the Host Ip address and with some port number. The port should be an integer value between 1000 to 6265535.

server_socket.bind(socket_address)

Then I am going to use listen to function to accept the connection. Here I am giving backlog as 5 which means five connections the system will allow. Also, I am using accept function the accept the connection and getting the client socket and the address.

server_socket.listen(5)
client_socket,addr = server_socket.accept()

After that, it can handle the client socket to accept and send the message using send function, and finally, we can close the socket with the close function.

client_socket.recv()

client_socket.sendall()

client_socket.close()

At the server-side I am using OpenCV to get the frames of the webcam then each frame data will be serialized to bytes data using the pickle module and then it will be packed using the struck module.

Here is the complete code for chat-server.py

# This code is for the server 
# Lets import the libraries
import socket, cv2, pickle,struct,imutils

# Socket Create
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_name = socket.gethostname()
host_ip = socket.gethostbyname(host_name)
print('HOST IP:',host_ip)
port = 9999
socket_address = (host_ip,port)

# Socket Bind
server_socket.bind(socket_address)

# Socket Listen
server_socket.listen(5)
print("LISTENING AT:",socket_address)

# Socket Accept
while True:
client_socket,addr = server_socket.accept()
print('GOT CONNECTION FROM:',addr)
if client_socket:
vid = cv2.VideoCapture(0)

while(vid.isOpened()):
img,frame = vid.read()
frame = imutils.resize(frame,width=320)
a = pickle.dumps(frame)
message = struct.pack("Q",len(a))+a
client_socket.sendall(message)

cv2.imshow('TRANSMITTING VIDEO',frame)
if cv2.waitKey(1) == '13':
client_socket.close()

Client-side Python Code:

server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

Now I will use the connect function to connect to the server socket. The host IP address and the port number will be the same as the server.

client_socket.connect((host_ip,port))

Now we can send and receive the information using send() and recv() function. Here we will use 1024 as buffer size as TCP is a streaming protocol which means there are no message boundaries it is just the stream of message bytes. It is like FIFO and when the server will send 1024 bytes then 1024 bytes will be received by the client.

packet = client_socket.recv(1024)

client_socket.send(packet)

The socket can be close the socket with the close function.

client_socket.close()

Here at the client-side first, we will unpack the received packet data using struct module and then will load the frame using pickle, and finally, we will display the received video.

Here is the complete code for client-server.py

import socket,cv2, pickle,struct

# create socket
client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_ip = '192.168.1.20' # paste your server ip address here
port = 9999
client_socket.connect((host_ip,port)) # a tuple
data = b""
payload_size = struct.calcsize("Q")
while True:
while len(data) < payload_size:
packet = client_socket.recv(4*1024) # 4K
if not packet: break
data+=packet
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("Q",packed_msg_size)[0]

while len(data) < msg_size:
data += client_socket.recv(4*1024)
frame_data = data[:msg_size]
data = data[msg_size:]
frame = pickle.loads(frame_data)
cv2.imshow("RECEIVING VIDEO",frame)
if cv2.waitKey(1) == '13':
break
client_socket.close()

Thank You for reading!! 😇😇

I'm passionate learner diving into the concepts of computing 💻