Task 3 server client video calling program

Abhinav Shreyash
5 min readJun 16, 2021

Today i’ll be telling you all on how to make a video calling application using python.

So without any further ado lets start

Starting from the client .

in python import the following

import cv2
import socket
import struct
import pickle
import zlib
import threading

cv2 for doing image related operation ,access camera and click the photo

socket for doing socket operation and setting up server client or connecting to a server

struct — i’ll tell later about it

pickle converts and encodes any datatype into bytes format and we can retrieve it without any loss.

zlib is used for data compression

threading module is used to setup both server client instance on the same computer parallely.

— — — — — — — — — — — xxxx — — — — — — — — — — — — — — — —

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((‘127.0.0.1’, 8485))
connection = client_socket.makefile(‘wb’)

— — — — — — — — — — — xxxx — — — — — — — — — — — — — — — —

setting up a TCP connection on the client side where in the ip and port 127.0.0.1 and 8485 is for the local computer

and socket.makefile() is a very special function which tells when a piece of file has ended, it echoes to the server and the server recieves it , w means write b means in binary

— — — — — — — — — — — xxxx — — — — — — — — — — — — — — — —

cam = cv2.VideoCapture(‘rtsp://192.168.137.37:9999/h264_pcm.sdp’)
cam.set(3, 320);
cam.set(4, 240);
img_counter = 0

— — — — — — — — — — — xxxx — — — — — — — — — — — — — — — —

firstline is for the camera input , replace it with you webcam ip , its just to demonstrate the input for ip webcam, and the second and third line sets the resolution of the camera object to 340x240

and initialize the image counter to count number of images sent to the server

— — — — — — — — — — — xxxx — — — — — — — — — — — — — — — —

encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90]

while True:

\n\n\n\n ret, frame = cam.read()

\n\n\n\n result, frame = cv2.imencode(‘.jpg’, frame)

# data = zlib.compress(pickle.dumps(frame),9)

\n\n\n\n data = pickle.dumps(frame)

# data = zlib.compress(zlib.compress(data,9),9)

\n\n\n\n size = len(data)

\n\n\n\n print(f”{img_counter}: {size}”)

\n\n\n\nclient_socket.sendall(struct.pack(“>L”, size) + data)

\n\n\n\n img_counter += 1

\n\n\n\nif cv2.waitKey() == 8:

\n\n\n\n\n\n\n\n break

cam.release()

— — — — — — — — — — — xxxx — — — — — — — — — — — — — — — —

starting from the first line we define , what is the format of image to be written into bytes , and the quality that must be maintained,

the loop ,

imencode encode the image into bytes

the we pickle the imencode

and then we compress the pickled two times,

the we calcute lenght of the end image and encode the length using struct.pack, what it does is it encode the integer into bytes which can easily concatened with the end image, and its size is always going to be 4 bytes ,

The server side :

import socket
import cv2
import pickle
import numpy as np
import struct
import zlib
import threading as t
from time import sleep

usual import

— — — — — — — — — — — — -xx — — — — — — — — — — — —

HOST=’’
PORT=8485

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print(‘Socket created’)

s.bind((HOST,PORT))
print(‘Socket bind complete’)
s.listen(10)
print(‘Socket now listening’)

conn,addr=s.accept()

— — — — — — — — — — — — — — — — xx — — — — — — — — — — — — —

setup TCP server at port 8485

— — — — — — — — — — — — — — — CODE — — — — — — — — — — — — -

data = b””
payload_size = struct.calcsize(“>L”)
print(“payload_size: {}”.format(payload_size))

— — — — — — — — — — — — — — -CODE — — — — — — — — — — — — —

define empty byte string

define payload size of length 4

— — — — — — — — — — — — — — -CODE — — — — — — — — — — — — —

while True:
while len(data) < payload_size:
#print(“Recv: {}”.format(len(data)))
data += conn.recv(9999999999)

# print(“Done Recv: {len(data)}”)
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack(“>L”, packed_msg_size)[0]
print(f”msg_size: {msg_size}”)
while len(data) < msg_size:
data += conn.recv(9999999999)
frame_data = data[:msg_size]
data = data[msg_size:]
#frame_data = zlib.decompress(zlib.decompress(frame_data))
# frame=pickle.loads(frame_data, fix_imports=True, encoding=”bytes”)
frame=pickle.loads(frame_data)
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
cv2.imshow(‘ImageWindow’,frame)
if cv2.waitKey(10) == 8:
close()
exit(0)

— — — — — — — — — — — — — — -CODE — — — — — — — — — — — — —

then i run a loop (infinite) while loop

the secondary loop iterated and recieves the data till the data size is equal to the payload size and when loop fails it collects the 4 length byte data into different variable and remaining into the data variable .

the it decode the 4 length byte data using struct.unpack and the it give and integer output which is the length of the data i.e. image and the it runs the while loop till the data size is less than the new found message length and then it reverse decode the data as it was encode in the client side .

and then we display the data decoded , and about the data which is more than the message length, it is the part of the new message length.

the using python multi threading we run the client program in the server side and the server program in the client side, and put the client program on the server side , and sleep it for 10 seconds , till then the server on the client side sets up , and then we run both side video calling simultaneously .

voila a video calling program.

thanks for reading this.

heres the github link and change the server and client address and also the camera link

https://github.com/abhinavisgood/task3.git

--

--