Skip to content

NetGear_Async

Abhishek Thakur edited this page Mar 15, 2020 · 48 revisions

VidGear Logo

NetGear_Async API

NetGear_Async is NetGear API on steroids. 🔥 Upto 1.5~2x times performance boost as compared to NetGear API at 1/3rd of memory consumption as compare to NetGear.

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.

Features:

  • 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:

  • Supported protocol are: tcp and ipc.

  • 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.

 


Important ⚠️

  • 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 comprehend NetGear API before using this API.

 

 

Table of content:

 

Importing

You can import NetGear_Async from async as follows:

from vidgear.gears.asyncio import NetGear_Async

 

 

Usage

 

Requirements

  • 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]
    cd

Basic Usage: (Bare-Minimum)

A. Server End:

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()

B. Clients End:

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()

 

 

Advanced Usage

1. Use NetGear_Async with flexible parameter control

A. Client's End:

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()

B. Server End:

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, receive_mode = True, 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()

 

2. Use NetGear_Async with custom Server Source (using OpenCV)

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:

A. Server End:

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()

B. Clients End:

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()

 

3. Use NetGear_Async with Other gears

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:

A. Server End:

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()

B. Clients End:

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()

 

 

Attributes and Parameters: 🔧

Attention:warning:: 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.

NetGear_Async specific parameters:

  1. 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.

  2. 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. It is used determine to which process or application a message should be delivered. Its default value is '5555'.

  3. 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'.

  4. 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 is 0(i.e zmq.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 employs ZMQ REQ sockets that can connect to many servers. The requests will be interleaved or distributed to both the servers. socket zmq.REQ will block send unless it has successfully received a reply back and socket zmq.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. A ZMQ.SUB can connect to multiple ZMQ.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.

  5. receive_mode (boolean): set this flag to select the Netgear's Mode of operation. This basically activates Receive Mode(if True) and Send Mode(if False). Furthermore, recv() function will only work when this flag is enabled(i.e. Receive Mode) and send() function will only work when this flag is disabled(i.e.Send Mode). Its default value is False(i.e. Send Mode is activated by default).

  6. 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), Otherwise Timeout Error will be raised. It Helps to close the Receiver-end safely if the Server has lost connection prematurely. Its default value is 10.0.

 

 

Clone this wiki locally