-
-
Notifications
You must be signed in to change notification settings - Fork 255
NetGear_Async
NetGear_Async is NetGear API on steroids. 🔥 Upto 1.5~2x times performance boost as compared to NetGear API at about 1/3rd of memory consumption only.
NetGear_Async is an asynchronous videoframe messaging framework built on AsyncIO ZmQ and powered by high-performance asyncio event loop called uvloop
to achieve unmatchable high-speed and lag-free video streaming over the network with minimal resource constraint. Basically, this API is able to transfer thousands of frames in just a few seconds without causing any significant load on your system.
-
Uninterrupted network streaming with excellent system-resources handling and insignificant latency.
-
Complete server-client handling and options to use variable protocols/patterns similar to NetGear API
-
NO support for any NetGear Exclusive modes yet.
-
Supports all four ZeroMQ messaging patterns:
-
zmq.PAIR
(ZMQ Pair Pattern) -
zmq.REQ/zmq.REP
(ZMQ Request/Reply Pattern) -
zmq.PUB/zmq.SUB
(ZMQ Publish/Subscribe Pattern) -
zmq.PUSH/zmq.PULL
(ZMQ Push/Pull Pattern)
-
-
Supported protocol are:
tcp
andipc
. -
In addition to all this, NetGear_Async also provides a special internal wrapper around VideoGear API, which itself provides internal access to both CamGear and PiGear APIs thereby granting it exclusive power for streaming frames incoming from any connected device/source to the network.
-
NetGear_Async API is available for Python 3.6 and above versions only.
-
NetGear_Async API as of now only available with the Testing Branch only.
-
It is advised to enable logging (
logging = True
) on the first run, to easily identify any runtime errors. -
It is advised to comprehend NetGear API before using this API.
You can import NetGear_Async from async
as follows:
from vidgear.gears.asyncio import NetGear_Async
-
Python 3.6+ already installed.
-
Clone and install the testing branch as follows:
git clone https://github.com/abhiTronix/vidgear.git cd vidgear git checkout testing sudo pip3 install .[asyncio] #install all necessary asyncio requirements cd
Open your favorite terminal and execute the following python code:
Tip::bulb: You can end streaming anytime by pressing [Ctrl+C]
/[⌘+C]
on your keyboard!
# import libraries
from vidgear.gears.asyncio import NetGear_Async
import asyncio
#initialize Server with suitable source
server = NetGear_Async(source='/home/foo/foo1.mp4').launch()
if __name__ == '__main__':
#set event loop
asyncio.set_event_loop(server.loop)
try:
#run your main function task until it is complete
server.loop.run_until_complete(server.task)
except KeyboardInterrupt:
#wait for keyboard interrupt
pass
finally:
# finally close the server
server.close()
Then open another terminal on the same system and execute the following python code and see the output:
Tip::bulb: You can end client anytime by pressing [Ctrl+C]
/[⌘+C]
on your keyboard!
# import libraries
from vidgear.gears.asyncio import NetGear_Async
import cv2, asyncio
#define and launch Client with `receive_mode = True`
client = NetGear_Async(receive_mode = True).launch()
#Create a async function where you want to show/manipulate your received frames
async def main():
# loop over Client's Asynchronous Frame Generator
async for frame in client.recv_generator():
# do something with received frames here
# Show output window
cv2.imshow("Output Frame", frame)
key = cv2.waitKey(1) & 0xFF
#await before continuing
await asyncio.sleep(0.00001)
if __name__ == '__main__':
#Set event loop to client's
asyncio.set_event_loop(client.loop)
try:
#run your main function task until it is complete
client.loop.run_until_complete(main())
except KeyboardInterrupt:
#wait for keyboard interrupt
pass
# close all output window
cv2.destroyAllWindows()
# safely close client
client.close()
Open a terminal on the System(a Client, where you want to display the input frames received from the Server) and execute the following python code: Also, Remember the IP-address of this system(required at Server's end) by executing the command: hostname -I
and also replace it in the following code.
# import libraries
from vidgear.gears.asyncio import NetGear_Async
import cv2, asyncio
#define and launch Client with `receive_mode = True`. #change following IP address '192.168.x.xxx' with yours
client = NetGear_Async(address = '192.168.x.xxx', port = '5454', protocol = 'tcp', pattern = 3, receive_mode = True, logging = True).launch()
#Create a async function where you want to show/manipulate your received frames
async def main():
# loop over Client's Asynchronous Frame Generator
async for frame in client.recv_generator():
# do something with received frames here
# Show output window
cv2.imshow("Output Frame", frame)
key = cv2.waitKey(1) & 0xFF
#await before continuing
await asyncio.sleep(0.00001)
if __name__ == '__main__':
#Set event loop to client's
asyncio.set_event_loop(client.loop)
try:
#run your main function task until it is complete
client.loop.run_until_complete(main())
except KeyboardInterrupt:
#wait for keyboard interrupt
pass
# close all output window
cv2.destroyAllWindows()
# safely close client
client.close()
Now, Open the terminal on another System(a Server, with a webcam connected to it at index 0
) and execute the following python code: Also, remember to replace the IP address in the following code with Client's IP address copied earlier
Tip::bulb: You can end streaming anytime by pressing [Ctrl+C] on your keyboard!
# import libraries
from vidgear.gears.asyncio import NetGear_Async
import asyncio
#initialize Server with suitable source
server = NetGear_Async(source=0, address = '192.168.x.xxx', port = '5454', protocol = 'tcp', pattern = 3, logging = True).launch()
if __name__ == '__main__':
#set event loop
asyncio.set_event_loop(server.loop)
try:
#run your main function task until it is complete
server.loop.run_until_complete(server.task)
except KeyboardInterrupt:
#wait for keyboard interrupt
pass
finally:
# finally close the server
server.close()
NetGear_Async allows you to easily define your own custom Source at Server-end that you want to use to manipulate your frames before sending them onto the network. Let us implement a bare-minimum example with a custom source with NetGear_Async and OpenCV:
Open your favorite terminal and execute the following python code:
Tip::bulb: You can end streaming anytime by pressing [Ctrl+C] on your keyboard!
# import library
from vidgear.gears.asyncio import NetGear_Async
import cv2, asyncio
#initialize Server
server = NetGear_Async(logging = True)
#Create a async frame generator as custom source
async def my_frame_generator(self):
#Open any video stream such as live webcam video stream on first index(i.e. 0) device
stream = cv2.VideoCapture(0)
# loop over stream until its terminated
while True:
# read frames
(grabbed, frame) = stream.read()
# check if frame empty
if not grabbed:
#if True break the infinite loop
break
# do something with the frame to be sent here
# yield frame
yield frame
# sleep for sometime
await asyncio.sleep(0.00001)
if __name__ == '__main__':
#set event loop
asyncio.set_event_loop(server.loop)
#Add your custom source generator to Server configuration
server.config["generator"] = my_frame_generator()
#Launch the Server
server.launch()
try:
#run your main function task until it is complete
server.loop.run_until_complete(server.task)
except KeyboardInterrupt:
#wait for keyboard interrupt
pass
finally:
# finally close the server
server.close()
Then open another terminal on the same system and execute the following python code and see the output:
Tip::bulb: You can end client anytime by pressing [Ctrl+C] on your keyboard!
# import libraries
from vidgear.gears.asyncio import NetGear_Async
import cv2, asyncio
#define and launch Client with `receive_mode = True`
client = NetGear_Async(receive_mode = True, logging = True).launch()
#Create a async function where you want to show/manipulate your received frames
async def main():
# loop over Client's Asynchronous Frame Generator
async for frame in client.recv_generator():
# do something with received frames here
# Show output window
cv2.imshow("Output Frame", frame)
key = cv2.waitKey(1) & 0xFF
#await before continuing
await asyncio.sleep(0.01)
if __name__ == '__main__':
#Set event loop to client's
asyncio.set_event_loop(client.loop)
try:
#run your main function task until it is complete
client.loop.run_until_complete(main())
except KeyboardInterrupt:
#wait for keyboard interrupt
pass
# close all output window
cv2.destroyAllWindows()
# safely close client
client.close()
NetGear_Async can be used with any other Gear directly without any compatibility issues. Let's implement a bare-minimum example where we are sending stabilized frames from Server-end and saving them at Client's end with WriteGear as follows:
Open your favorite terminal and execute the following python code:
Tip::bulb: You can end streaming anytime by pressing [Ctrl+C]
/[⌘+C]
on your keyboard!
# import libraries
from vidgear.gears.asyncio import NetGear_Async
import asyncio
#initialize Server with suitable source
server = NetGear_Async(source='/home/foo/foo1.mp4').launch()
if __name__ == '__main__':
#set event loop
asyncio.set_event_loop(server.loop)
try:
#run your main function task until it is complete
server.loop.run_until_complete(server.task)
except KeyboardInterrupt:
#wait for keyboard interrupt
pass
finally:
# finally close the server
server.close()
Then open another terminal on the same system and execute the following python code and see the output:
Tip::bulb: You can end client anytime by pressing [Ctrl+C]
/[⌘+C]
on your keyboard!
# import libraries
from vidgear.gears.asyncio import NetGear_Async
import cv2, asyncio
#define and launch Client with `receive_mode = True`
client = NetGear_Async(receive_mode = True).launch()
#Define writer with output filename 'Output.mp4'
writer = WriteGear(output_filename = 'Output.mp4', compression_mode = True, logging = True, **output_params)
#Create a async function where you want to show/manipulate your received frames
async def main():
# loop over Client's Asynchronous Frame Generator
async for frame in client.recv_generator():
# do something with received frames here
# write a modified frame to writer
writer.write(gray)
# Show output window
cv2.imshow("Output Frame", frame)
key = cv2.waitKey(1) & 0xFF
#await before continuing
await asyncio.sleep(0.00001)
if __name__ == '__main__':
#Set event loop to client's
asyncio.set_event_loop(client.loop)
try:
#run your main function task until it is complete
client.loop.run_until_complete(main())
except KeyboardInterrupt:
#wait for keyboard interrupt
pass
# close all output window
cv2.destroyAllWindows()
# safely close client
client.close()
# safely close writer
writer.close()
NetGear_Async provides a special internal wrapper around VideoGear API and its attributes, which itself provides internal access to all parameters available with PiGear API and CamGear API based on which API is currently accessed.
-
address
(string): sets the valid network address of the server/client. Network addresses unique identifiers across the network. Its default value is based on current primary mode, i.e'localhost'
for Send Mode and'*'
for Receive Mode. -
port
(string): sets the valid Network Port of the Server/Client. A network port is a number that identifies one side of a connection between two devices on the network and is used determine to which process or application a message should be delivered. Its default value is'5555'
. -
protocol
(string): sets the valid messaging protocol between server and client. A network protocol is a set of established rules that dictates how to format, transmit and receive data so computer network devices - from servers and routers to endpoints - can communicate regardless of the differences in their underlying infrastructures, designs or standards. Supported protocol are:'tcp'
and'ipc'
. Its default value is'tcp'
. -
pattern
(int): sets the supported messaging pattern(flow of communication) between server and client. Messaging patterns are the network-oriented architectural pattern that describes the flow of communication between interconnecting systems. NetGear provides access to ZeroMQ's pre-optimized sockets which enables you to take advantage of these patterns. Its default value is0
(i.ezmq.PAIR
). All supported ZMQ patterns are:-
0
(.i.e. zmq.PAIR): (PAIR) In this pattern, the communication is bidirectional. There is no specific state stored within the socket. There can only be one connected peer. The server listens on a certain port and a client connects to it. -
1
(.i.e. zmq.REQ/zmq.REP): (Request/Reply) In this pattern, it employsZMQ REQ
sockets that can connect to many servers. The requests will be interleaved or distributed to both the servers. socketzmq.REQ
will block send unless it has successfully received a reply back and socketzmq.REP
will block on recv() unless it has received a request. -
2
(.i.e. zmq.PUB/zmq.SUB): (Publish/Subscribe) is another classic pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers. Messages are published without the knowledge of what or if any subscriber of that knowledge exists. AZMQ.SUB
can connect to multipleZMQ.PUB
(publishers). No single publisher overwhelms the subscriber. The messages from both publishers are interleaved. -
3
(.i.e. zmq.PUSH/zmq.PULL):(Push/Pull) sockets let you distribute messages to multiple workers, arranged in a pipeline. A Push socket will distribute sent messages to its Pull clients evenly. This is equivalent to the producer/consumer model but the results computed by the consumer are not sent upstream but downstream to another pull/consumer socket.
-
-
receive_mode
(boolean): set this flag to select the Netgear's Mode of operation. This basically activatesReceive Mode
(ifTrue
) andSend Mode
(ifFalse
). Furthermore,recv()
function will only work when this flag is enabled(i.e.Receive Mode
) andsend()
function will only work when this flag is disabled(i.e.Send Mode
). Its default value isFalse
(i.e. Send Mode is activated by default). -
timeout
(float/int): In NetGear_Async, the Receiver-end keeps tracks if frames are received from Server-end within this specified timeout value (in seconds), OtherwiseTimeoutError
will be raised. It Helps to close the Receiver-end safely if the Server has lost connection prematurely. Its default value is10.0
.