In Multi-Clients Mode, NetGear robustly handles Multiple Clients at once thereby able to broadcast frames and data across multiple Clients/Consumers in the network at same time. This mode works contrary to Multi-Servers Mode such that every new Client that connects to single Server can be identified by its unique port address on the network.
The supported patterns for this mode are Publish/Subscribe (zmq.PUB/zmq.SUB) and Request/Reply(zmq.REQ/zmq.REP) and can be easily activated in NetGear API through multiclient_mode attribute of its options dictionary parameter during initialization.
Multi-Clients Mode is best for broadcasting Meta-Data with Video-frames to specific limited number of clients in real time. But if you're looking to scale broadcast to a very large pool of clients, then see our WebGear or WebGear_RTC APIs.
Important Information regarding Multi-Clients Mode
A unique PORT address MUST be assigned to each Client on the network using its port parameter.
A list/tuple of PORT addresses of all unique Clients MUST be assigned at Server's end using its port parameter for a successful connection.
Patterns 1(i.e. Request/Reply zmq.REQ/zmq.REP) and 2(i.e. Publish/Subscribe zmq.PUB/zmq.SUB) are the only supported pattern values for this Mode. Therefore, calling any other pattern value with is mode will result in ValueError.
Multi-Clients and Multi-Servers exclusive modes CANNOT be enabled simultaneously, Otherwise NetGear API will throw ValueError.
The address parameter value of each Client MUST exactly match the Server.
Frame/Data transmission will NOT START until all given Client(s) are connected to the Server.
For sake of simplicity, in these examples we will use only two unique Clients, but the number of these Clients can be extended to SEVERAL numbers depending upon your Network bandwidth and System Capabilities.
In this example, we will capturing live video-frames from a source (a.k.a Server) with a webcam connected to it. Afterwards, those captured frame will be sent over the network to two independent system (a.k.a Clients) using this Multi-Clients Mode in NetGear API. Finally, both Clients will be displaying received frames in Output Windows in real time.
This example is useful for building applications like Real-Time Video Broadcasting to multiple clients in local network.
Now, Open the terminal on a Server System (with a webcam connected to it at index 0). Now execute the following python code:
Important Notes
Note down the local IP-address of this system(required at all Client(s) end) and also replace it in the following code. You can follow this FAQ for this purpose.
Also, assign the tuple/list of port address of all Client you are going to connect to this system.
Frame/Data transmission will NOT START untill all given Client(s) are connected to this Server.
You can terminate streaming anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearfromvidgear.gearsimportCamGear# Open suitable video stream (webcam on first index in our case)stream=CamGear(source=0).start()# activate multiclient_mode modeoptions={"multiclient_mode":True}# Define NetGear Client at given IP address and assign list/tuple of# all unique Server((5577,5578) in our case) and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!server=NetGear(address="192.168.x.x",port=(5567,5577),protocol="tcp",pattern=1,logging=True,**options)# Define received data dictionarydata_dict={}# loop over until KeyBoard InterruptedwhileTrue:try:# read frames from streamframe=stream.read()# check for frame if not None-typeifframeisNone:break# {do something with the frame here}# send frame and also receive data from Client(s)recv_data=server.send(frame)# check if valid data receivedifnot(recv_dataisNone):# extract unique port address and its respective dataunique_address,data=recv_data# update the extracted data in the data dictionarydata_dict[unique_address]=dataifdata_dict:# print data just received from Client(s)forkey,valueindata_dict.items():print("Client at port {} said: {}".format(key,value))exceptKeyboardInterrupt:break# safely close video streamstream.stop()# safely close serverserver.close()
Now, Open a terminal on another Client System (where you want to display the input frames received from Server), let's name it Client-1. Execute the following python code:
Replace the IP address in the following code with Server's IP address you noted earlier and also assign a unique port address (required by Server to identify this system).
You can terminate client anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearimportcv2# activate Multi-Clients modeoptions={"multiclient_mode":True}# Define NetGear Client at Server's IP address and assign a unique port address and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!client=NetGear(address="192.168.x.x",port="5567",protocol="tcp",pattern=1,receive_mode=True,logging=True,**options)# loop overwhileTrue:# receive data from serverframe=client.recv()# check for frame if NoneifframeisNone:break# {do something with frame here}# Show output windowcv2.imshow("Client 5567 Output",frame)# check for 'q' key if pressedkey=cv2.waitKey(1)&0xFFifkey==ord("q"):break# close output windowcv2.destroyAllWindows()# safely close clientclient.close()
Finally, Open a terminal on another Client System (where you want to display the input frames received from Server), let's name it Client-2. Execute the following python code:
Replace the IP address in the following code with Server's IP address you noted earlier and also assign a unique port address (required by Server to identify this system).
You can terminate client anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearimportcv2# activate Multi-Clients modeoptions={"multiclient_mode":True}# Define NetGear Client at Server's IP address and assign a unique port address and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!client=NetGear(address="192.168.x.x",port="5577",protocol="tcp",pattern=1,receive_mode=True,logging=True,**options)# loop overwhileTrue:# receive data from serverframe=client.recv()# check for frame if NoneifframeisNone:break# {do something with frame here}# Show output windowcv2.imshow("Client 5577 Output",frame)# check for 'q' key if pressedkey=cv2.waitKey(1)&0xFFifkey==ord("q"):break# close output windowcv2.destroyAllWindows()# safely close clientclient.close()
Now, Open the terminal on a Server System (with a webcam connected to it at index 0). Now execute the following python code:
Important Notes
Note down the local IP-address of this system(required at all Client(s) end) and also replace it in the following code. You can follow this FAQ for this purpose.
Also, assign the tuple/list of port address of all Client you are going to connect to this system.
Frame/Data transmission will NOT START untill all given Client(s) are connected to this Server.
You can terminate streaming anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearimportcv2# Open suitable video stream (webcam on first index in our case)stream=cv2.VideoCapture(0)# activate multiclient_mode modeoptions={"multiclient_mode":True}# Define NetGear Client at given IP address and assign list/tuple of all unique Server((5577,5578) in our case) and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!server=NetGear(address="192.168.x.x",port=(5567,5577),protocol="tcp",pattern=2,logging=True,**options)# Define received data dictionarydata_dict={}# loop over until KeyBoard InterruptedwhileTrue:try:# read frames from stream(grabbed,frame)=stream.read()# check for frame if not grabbedifnotgrabbed:break# {do something with the frame here}# send frame and also receive data from Client(s)recv_data=server.send(frame)# check if valid data receivedifnot(recv_dataisNone):# extract unique port address and its respective dataunique_address,data=recv_data# update the extracted data in the data dictionarydata_dict[unique_address]=dataifdata_dict:# print data just received from Client(s)forkey,valueindata_dict.items():print("Client at port {} said: {}".format(key,value))exceptKeyboardInterrupt:break# safely close video streamstream.release()# safely close serverserver.close()
Now, Open a terminal on another Client System (where you want to display the input frames received from Server), let's name it Client-1. Execute the following python code:
Replace the IP address in the following code with Server's IP address you noted earlier and also assign a unique port address (required by Server to identify this system).
You can terminate client anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearimportcv2# activate Multi-Clients modeoptions={"multiclient_mode":True}# Define NetGear Client at Server's IP address and assign a unique port address and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!client=NetGear(address="192.168.x.x",port="5567",protocol="tcp",pattern=2,receive_mode=True,logging=True,**options)# loop overwhileTrue:# receive data from serverframe=client.recv()# check for frame if NoneifframeisNone:break# {do something with frame here}# Show output windowcv2.imshow("Client 5567 Output",frame)# check for 'q' key if pressedkey=cv2.waitKey(1)&0xFFifkey==ord("q"):break# close output windowcv2.destroyAllWindows()# safely close clientclient.close()
Finally, Open a terminal on another Client System (also, where you want to display the input frames received from Server), let's name it Client-2. Execute the following python code:
Replace the IP address in the following code with Server's IP address you noted earlier and also assign a unique port address (required by Server to identify this system).
You can terminate client anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearimportcv2# activate Multi-Clients modeoptions={"multiclient_mode":True}# Define NetGear Client at Server's IP address and assign a unique port address and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!client=NetGear(address="192.168.x.x",port="5577",protocol="tcp",pattern=2,receive_mode=True,logging=True,**options)# loop overwhileTrue:# receive data from serverframe=client.recv()# check for frame if NoneifframeisNone:break# {do something with frame here}# Show output windowcv2.imshow("Client 5577 Output",frame)# check for 'q' key if pressedkey=cv2.waitKey(1)&0xFFifkey==ord("q"):break# close output windowcv2.destroyAllWindows()# safely close clientclient.close()
Using Multi-Clients Mode for Unidirectional Custom Data Transfer¶
Abstract
With Multi-Clients Mode, you can also send additional data of any data-type (such as list, tuple, string, int, ndarray etc.) along with frame, from all connected Clients(s) back to a Server unidirectionally.
In Multi-Clients Mode, unidirectional data transfer ONLY works with pattern 1(i.e. Request/Reply zmq.REQ/zmq.REP), and NOT with pattern 2(i.e. Publish/Subscribe zmq.PUB/zmq.SUB)!
In this example, We will be transferring video-frames from a single Server (consisting of Raspberry Pi with Camera Module) over the network to two independent Client for displaying them in real-time. At the same time, we will be sending data (a Text String, for the sake of simplicity) from both the Client(s) back to our Server, which will be printed onto the terminal.
Now, Open the terminal on a Server System (with a webcam connected to it at index 0). Now execute the following python code:
Important Notes
Note down the local IP-address of this system(required at all Client(s) end) and also replace it in the following code. You can follow this FAQ for this purpose.
Also, assign the tuple/list of port address of all Client you are going to connect to this system.
Frame/Data transmission will NOT START untill all given Client(s) are connected to this Server.
You can terminate streaming anytime by pressing Ctrl+C on your keyboard!
Backend PiGear API now fully supports the newer picamera2 python library under the hood for Raspberry Pi camera modules. Follow this guide ➶ for its installation.
# import required librariesfromvidgear.gearsimportPiGearfromvidgear.gearsimportNetGear# add various Picamera2 tweak parametersoptions={"queue":True,"buffer_count":4,"controls":{"Brightness":0.5,"ExposureValue":2.0},"transform":Transform(hflip=1),"auto_align_output_config":True,# auto-align camera configuration}# open pi video stream with defined parametersstream=PiGear(resolution=(640,480),framerate=60,logging=True,**options).start()# activate multiclient_mode modeoptions={"multiclient_mode":True}# Define NetGear Client at given IP address and assign list/tuple of all unique Server((5577,5578) in our case) and other parametersserver=NetGear(address="192.168.x.x",port=(5577,5578),protocol="tcp",pattern=1,logging=True,**options)# !!! change following IP address '192.168.x.xxx' with yours !!!# Define received data dictionarydata_dict={}# loop over until KeyBoard InterruptedwhileTrue:try:# read frames from streamframe=stream.read()# check for frame if NonetypeifframeisNone:break# {do something with the frame here}# send frame and also receive data from Client(s)recv_data=server.send(frame)# check if valid data receivedifnot(recv_dataisNone):# extract unique port address and its respective dataunique_address,data=recv_data# update the extracted data in the data dictionarydata_dict[unique_address]=dataifdata_dict:# print data just received from Client(s)forkey,valueindata_dict.items():print("Client at port {} said: {}".format(key,value))exceptKeyboardInterrupt:break# safely close video streamstream.stop()# safely close serverserver.close()
Under the hood, Backend PiGear API (version 0.3.3 onwards) prioritizes the new picamera2 API backend.
However, the API seamlessly switches to the legacy picamera backend, if the picamera2 library is unavailable or not installed.
It is advised to enable logging(logging=True) to see which backend is being used.
The picamera library is built on the legacy camera stack that is NOT (and never has been) supported on 64-bit OS builds.
You could also enforce the legacy picamera API backend in PiGear by using the enforce_legacy_picamera user-defined optional parameter boolean attribute.
# import required librariesfromvidgear.gearsimportPiGearfromvidgear.gearsimportNetGear# add various Picamera tweak parameters to dictionaryoptions={"hflip":True,"exposure_mode":"auto","iso":800,"exposure_compensation":15,"awb_mode":"horizon","sensor_mode":0,}# open pi video stream with defined parametersstream=PiGear(resolution=(640,480),framerate=60,logging=True,**options).start()# activate multiclient_mode modeoptions={"multiclient_mode":True}# Define NetGear Client at given IP address and assign list/tuple of all unique Server((5577,5578) in our case) and other parametersserver=NetGear(address="192.168.x.x",port=(5577,5578),protocol="tcp",pattern=1,logging=True,**options)# !!! change following IP address '192.168.x.xxx' with yours !!!# Define received data dictionarydata_dict={}# loop over until KeyBoard InterruptedwhileTrue:try:# read frames from streamframe=stream.read()# check for frame if NonetypeifframeisNone:break# {do something with the frame here}# send frame and also receive data from Client(s)recv_data=server.send(frame)# check if valid data receivedifnot(recv_dataisNone):# extract unique port address and its respective dataunique_address,data=recv_data# update the extracted data in the data dictionarydata_dict[unique_address]=dataifdata_dict:# print data just received from Client(s)forkey,valueindata_dict.items():print("Client at port {} said: {}".format(key,value))exceptKeyboardInterrupt:break# safely close video streamstream.stop()# safely close serverserver.close()
Now, Open a terminal on another Client System (where you want to display the input frames received from Server), let's name it Client-1. Execute the following python code:
Replace the IP address in the following code with Server's IP address you noted earlier and also assign a unique port address (required by Server to identify this system).
You can terminate client anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearimportcv2# activate Multi-Clients modeoptions={"multiclient_mode":True}# Define NetGear Client at Server's IP address and assign a unique port address and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!client=NetGear(address="192.168.x.x",port="5577",protocol="tcp",pattern=1,receive_mode=True,logging=True,**options)# loop overwhileTrue:# prepare data to be senttarget_data="Hi, I am 5577 Client here."# receive data from server and also send our dataframe=client.recv(return_data=target_data)# check for frame if NoneifframeisNone:break# {do something with frame here}# Show output windowcv2.imshow("Client 5577 Output",frame)# check for 'q' key if pressedkey=cv2.waitKey(1)&0xFFifkey==ord("q"):break# close output windowcv2.destroyAllWindows()# safely close clientclient.close()
Finally, Open a terminal on another Client System (also, where you want to display the input frames received from Server), let's name it Client-2. Execute the following python code:
Replace the IP address in the following code with Server's IP address you noted earlier and also assign a unique port address (required by Server to identify this system).
You can terminate client anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearimportcv2# activate Multi-Clients modeoptions={"multiclient_mode":True}# Define NetGear Client at Server's IP address and assign a unique port address and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!client=NetGear(address="192.168.x.x",port="5578",protocol="tcp",pattern=1,receive_mode=True,logging=True,**options)# loop overwhileTrue:# prepare data to be senttarget_data="Hi, I am 5578 Client here."# receive data from server and also send our dataframe=client.recv(return_data=target_data)# check for frame if NoneifframeisNone:break# {do something with frame here}# Show output windowcv2.imshow("Client 5578 Output",frame)# check for 'q' key if pressedkey=cv2.waitKey(1)&0xFFifkey==ord("q"):break# close output windowcv2.destroyAllWindows()# safely close clientclient.close()
Multi-Clients Mode now also compatible with Bidirectional Mode, which lets you send additional data of any datatype1 along with frame in real-time bidirectionally between a single Server and all connected Client(s).
Important Information
Bidirectional data transfer ONLY works with pattern 1(i.e. Request/Reply zmq.REQ/zmq.REP), and NOT with pattern 2(i.e. Publish/Subscribe zmq.PUB/zmq.SUB)
Additional data of numpy.ndarray data-type is NOT SUPPORTED at Server's end with its message parameter.
Bidirectional Mode may lead to additional LATENCY depending upon the size of data being transfer bidirectionally. User discretion is advised!
New in v0.2.5
This example was added in v0.2.5.
In this example, We will be transferring video-frames and data (a Text String, for the sake of simplicity) from a single Server (In this case, Raspberry Pi with Camera Module) over the network to two independent Clients for displaying them both in real-time. At the same time, we will be sending data (a Text String, for the sake of simplicity) back from both the Client(s) to our Server, which will be printed onto the terminal.
Now, Open the terminal on a Server System (with a webcam connected to it at index 0). Now execute the following python code:
Important Notes
Note down the local IP-address of this system(required at all Client(s) end) and also replace it in the following code. You can follow this FAQ for this purpose.
Also, assign the tuple/list of port address of all Client you are going to connect to this system.
Frame/Data transmission will NOT START untill all given Client(s) are connected to this Server.
You can terminate streaming anytime by pressing Ctrl+C on your keyboard!
Backend PiGear API now fully supports the newer picamera2 python library under the hood for Raspberry Pi camera modules. Follow this guide ➶ for its installation.
# import required librariesfromvidgear.gearsimportPiGearfromvidgear.gearsimportNetGearfromlibcameraimportTransform# add various Picamera2 tweak parametersoptions={"queue":True,"buffer_count":4,"controls":{"Brightness":0.5,"ExposureValue":2.0},"transform":Transform(hflip=1),"auto_align_output_config":True,# auto-align camera configuration}# open pi video stream with defined parametersstream=PiGear(resolution=(640,480),framerate=60,logging=True,**options).start()# activate both multiclient and bidirectional modesoptions={"multiclient_mode":True,"bidirectional_mode":True}# Define NetGear Client at given IP address and assign list/tuple of # all unique Server((5577,5578) in our case) and other parametersserver=NetGear(address="192.168.x.x",port=(5577,5578),protocol="tcp",pattern=1,logging=True,**options)# !!! change following IP address '192.168.x.xxx' with yours !!!# Define received data dictionarydata_dict={}# loop over until KeyBoard InterruptedwhileTrue:try:# read frames from streamframe=stream.read()# check for frame if NonetypeifframeisNone:break# {do something with the frame here}# prepare data to be sent(a simple text in our case)target_data="Hello, I am a Server."# send frame & data and also receive data from Client(s)recv_data=server.send(frame,message=target_data)# (1)# check if valid data receivedifnot(recv_dataisNone):# extract unique port address and its respective dataunique_address,data=recv_data# update the extracted data in the data dictionarydata_dict[unique_address]=dataifdata_dict:# print data just received from Client(s)forkey,valueindata_dict.items():print("Client at port {} said: {}".format(key,value))exceptKeyboardInterrupt:break# safely close video streamstream.stop()# safely close serverserver.close()
Everything except numpy.ndarray datatype data is accepted as target_data in message parameter.
Under the hood, Backend PiGear API (version 0.3.3 onwards) prioritizes the new picamera2 API backend.
However, the API seamlessly switches to the legacy picamera backend, if the picamera2 library is unavailable or not installed.
It is advised to enable logging(logging=True) to see which backend is being used.
The picamera library is built on the legacy camera stack that is NOT (and never has been) supported on 64-bit OS builds.
You could also enforce the legacy picamera API backend in PiGear by using the enforce_legacy_picamera user-defined optional parameter boolean attribute.
# import required librariesfromvidgear.gearsimportPiGearfromvidgear.gearsimportNetGear# add various Picamera tweak parameters to dictionaryoptions={"hflip":True,"exposure_mode":"auto","iso":800,"exposure_compensation":15,"awb_mode":"horizon","sensor_mode":0,}# open pi video stream with defined parametersstream=PiGear(resolution=(640,480),framerate=60,logging=True,**options).start()# activate both multiclient and bidirectional modesoptions={"multiclient_mode":True,"bidirectional_mode":True}# Define NetGear Client at given IP address and assign list/tuple of # all unique Server((5577,5578) in our case) and other parametersserver=NetGear(address="192.168.x.x",port=(5577,5578),protocol="tcp",pattern=1,logging=True,**options)# !!! change following IP address '192.168.x.xxx' with yours !!!# Define received data dictionarydata_dict={}# loop over until KeyBoard InterruptedwhileTrue:try:# read frames from streamframe=stream.read()# check for frame if NonetypeifframeisNone:break# {do something with the frame here}# prepare data to be sent(a simple text in our case)target_data="Hello, I am a Server."# send frame & data and also receive data from Client(s)recv_data=server.send(frame,message=target_data)# (1)# check if valid data receivedifnot(recv_dataisNone):# extract unique port address and its respective dataunique_address,data=recv_data# update the extracted data in the data dictionarydata_dict[unique_address]=dataifdata_dict:# print data just received from Client(s)forkey,valueindata_dict.items():print("Client at port {} said: {}".format(key,value))exceptKeyboardInterrupt:break# safely close video streamstream.stop()# safely close serverserver.close()
Everything except numpy.ndarray datatype data is accepted as target_data in message parameter.
Now, Open a terminal on another Client System (where you want to display the input frames received from Server), let's name it Client-1. Execute the following python code:
Replace the IP address in the following code with Server's IP address you noted earlier and also assign a unique port address (required by Server to identify this system).
You can terminate client anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearimportcv2# activate both multiclient and bidirectional modesoptions={"multiclient_mode":True,"bidirectional_mode":True}# Define NetGear Client at Server's IP address and assign a unique port address and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!client=NetGear(address="192.168.x.x",port="5577",protocol="tcp",pattern=1,receive_mode=True,logging=True,**options)# loop overwhileTrue:# prepare data to be senttarget_data="Hi, I am 5577 Client here."# receive data from server and also send our datadata=client.recv(return_data=target_data)# check for data if NoneifdataisNone:break# extract server_data & frame from dataserver_data,frame=data# again check for frame if NoneifframeisNone:break# {do something with the extracted frame and data here}# lets print extracted server dataifnot(server_dataisNone):print(server_data)# Show output windowcv2.imshow("Client 5577 Output",frame)# check for 'q' key if pressedkey=cv2.waitKey(1)&0xFFifkey==ord("q"):break# close output windowcv2.destroyAllWindows()# safely close clientclient.close()
Finally, Open a terminal on another Client System (also, where you want to display the input frames received from Server), let's name it Client-2. Execute the following python code:
Replace the IP address in the following code with Server's IP address you noted earlier and also assign a unique port address (required by Server to identify this system).
You can terminate client anytime by pressing Ctrl+C on your keyboard!
# import required librariesfromvidgear.gearsimportNetGearimportcv2# activate both multiclient and bidirectional modesoptions={"multiclient_mode":True,"bidirectional_mode":True}# Define NetGear Client at Server's IP address and assign a unique port address and other parameters# !!! change following IP address '192.168.x.xxx' with yours !!!client=NetGear(address="192.168.x.x",port="5578",protocol="tcp",pattern=1,receive_mode=True,logging=True,**options)# loop overwhileTrue:# prepare data to be senttarget_data="Hi, I am 5578 Client here."# receive data from server and also send our datadata=client.recv(return_data=target_data)# check for data if NoneifdataisNone:break# extract server_data & frame from dataserver_data,frame=data# again check for frame if NoneifframeisNone:break# {do something with the extracted frame and data here}# lets print extracted server dataifnot(server_dataisNone):print(server_data)# Show output windowcv2.imshow("Client 5578 Output",frame)# check for 'q' key if pressedkey=cv2.waitKey(1)&0xFFifkey==ord("q"):break# close output windowcv2.destroyAllWindows()# safely close clientclient.close()
Additional data of numpy.ndarray data-type is NOT SUPPORTED at Server's end with its message parameter.