Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ScreenGear and WebGear_RTC not working when using monitor=2 #251

Closed
harshitsinghai77 opened this issue Oct 3, 2021 · 5 comments · Fixed by #262
Closed

ScreenGear and WebGear_RTC not working when using monitor=2 #251

harshitsinghai77 opened this issue Oct 3, 2021 · 5 comments · Fixed by #262
Assignees
Labels
DOCS 📜 Issue/PR is related to vidgear docs. EXTERNAL BUG 👾 Bug caused by external dependent library SOLVED 🏁 This issue/PR is resolved now. Goal Achieved!
Milestone

Comments

@harshitsinghai77
Copy link

ScreenGear and WebGear_RTC does not work when using monitor=2

self.stram = ScreenGear(monitor=2, logging=True).start()

Description

# import necessary libs
import uvicorn
from av import VideoFrame
from aiortc import VideoStreamTrack
from vidgear.gears import ScreenGear
from aiortc.mediastreams import MediaStreamError
from vidgear.gears.asyncio import WebGear_RTC

# various performance tweaks
options = {
    "frame_size_reduction": 50,
    "enable_live_broadcast": True,
}   
# initialize WebGear_RTC app without any source
web = WebGear_RTC(logging=True, **options)

# create your own Bare-Minimum Custom Media Server
class Custom_RTCServer(VideoStreamTrack):
    """
    Custom Media Server using OpenCV, an inherit-class
    to aiortc's VideoStreamTrack.
    """

    def __init__(self, source=None):

        # don't forget this line!
        super().__init__()

        # initialize global params
        self.stream = ScreenGear(monitor=2, logging=True).start()

    async def recv(self):
        """
        A coroutine function that yields `av.frame.Frame`.
        """
        # don't forget this function!!!

        # get next timestamp
        pts, time_base = await self.next_timestamp()

        # read video frame
        frame = self.stream.read()

        # if NoneType
        if frame is None:
            return MediaStreamError

        # reducer frames size if you want more performance otherwise comment this line
        # frame = await reducer(frame, percentage=30)  # reduce frame by 30%

        # contruct `av.frame.Frame` from `numpy.nd.array`
        av_frame = VideoFrame.from_ndarray(frame, format="bgr24")
        av_frame.pts = pts
        av_frame.time_base = time_base

        # return `av.frame.Frame`
        return av_frame

    def terminate(self):
        """
        Gracefully terminates VideoGear stream
        """
        # don't forget this function!!!

        # terminate
        if not (self.stream is None):
            self.stream.stop()
            self.stream = None


# assign your custom media server to config with adequate source (for e.g. foo.mp4)
web.config["server"] = Custom_RTCServer()

# run this app on Uvicorn server at address http://localhost:8000/
uvicorn.run(web(), host="localhost", port=8000)

# close app safely
web.shutdown()

This doesn't work.

But using self.stream = ScreenGear(logging=True).start() works.

The problem is when using
But using self.stream = ScreenGear(monitor=2, logging=True).start()

Acknowledgment

Environment

  • VidGear version: 0.2.2
  • Branch: master
  • Python version: 3.9.5
  • PiP version: 20.3.4
  • Operating System and version: Linux

Expected Behavior

Only monitor 2 screen should be shared.

@abhiTronix
Copy link
Owner

abhiTronix commented Oct 3, 2021

@harshitsinghai77 Is logging stuck at WebGear_RTC :: DEBUG :: ICE connection state is completed ?

@abhiTronix abhiTronix added the MISSING : INFORMATION 🔍 Requested proper information/evidence about the Issue/PR in context. label Oct 3, 2021
@harshitsinghai77
Copy link
Author

harshitsinghai77 commented Oct 3, 2021

Yes.

image

@no-response no-response bot removed the MISSING : INFORMATION 🔍 Requested proper information/evidence about the Issue/PR in context. label Oct 3, 2021
@abhiTronix abhiTronix added BUG CONFIRMED ✅ Bug is confirmed! BUG 🐛 Vidgear api's error, flaw or fault labels Oct 3, 2021
@abhiTronix abhiTronix added this to the 0.2.3 milestone Oct 3, 2021
@abhiTronix
Copy link
Owner

abhiTronix commented Oct 3, 2021

@harshitsinghai77 Ok I've found the bug. And you're right about problem being with av_frame = VideoFrame.from_ndarray(frame, format="bgr24") line.

Bug:

Turned out ScreenGear was outputting BGRA(4 channel frame) format instead of default BGR(3 channel frame), when monitor value is defined (!=None). Hence, VideoFrame.from_ndarray function cannot work with "bgr24" colorspace since it requires 3 channels and not 4-channel frame at its input and this resut in AssertionError:

aiortc.rtcrtpsender :: WARNING :: RTCRtpsender(video) Traceback (most recent call last):
  File "C:\Users\foo\AppData\Roaming\Python\Python38\site-packages\aiortc\rtcrtpsender.py", line 295, in _run_rtp
    payloads, timestamp = await self._next_encoded_frame(codec)
  File "C:\Users\foo\AppData\Roaming\Python\Python38\site-packages\aiortc\rtcrtpsender.py", line 248, in _next_encoded_frame
    frame = await self.__track.recv()
  File "p.py", line 56, in recv
    av_frame = VideoFrame.from_ndarray(frame, format="bgr24")
  File "av\video\frame.pyx", line 337, in av.video.frame.VideoFrame.from_ndarray
AssertionError

Solution:

The solution is just to change colorspace based on number of channel in frame. Hence following code will work for you:

# import necessary libs
import uvicorn, asyncio, cv2
from av import VideoFrame
from aiortc import VideoStreamTrack
from aiortc.mediastreams import MediaStreamError
from vidgear.gears.asyncio import WebGear_RTC
from vidgear.gears import ScreenGear
from vidgear.gears.asyncio.helper import reducer

# various performance tweaks
options = {
    "frame_size_reduction": 25,
}   
# initialize WebGear_RTC app without any source
web = WebGear_RTC(logging=True, **options)

# create your own Bare-Minimum Custom Media Server
class Custom_RTCServer(VideoStreamTrack):
    """
    Custom Media Server using OpenCV, an inherit-class
    to aiortc's VideoStreamTrack.
    """

    def __init__(self):

        # don't forget this line!
        super().__init__()

        # initialize global params
        self.stream = ScreenGear(monitor=2, logging=True).start()
        self.stream.read()

    async def recv(self):
        """
        A coroutine function that yields `av.frame.Frame`.
        """
        # don't forget this function!!!

        # get next timestamp
        pts, time_base = await self.next_timestamp()

        # read video frame
        frame = self.stream.read()

        # if NoneType
        if frame is None:
            return MediaStreamError

        # reducer frames size if you want more performance otherwise comment this line
        frame = await reducer(frame, percentage=10)  # reduce frame by 10%

        # contruct `av.frame.Frame` from `numpy.nd.array`
        if frame.shape[-1] == 4:
            av_frame = VideoFrame.from_ndarray(frame, format="bgra")
        else:
            av_frame = VideoFrame.from_ndarray(frame, format="bgr24")
        av_frame.pts = pts
        av_frame.time_base = time_base

        # return `av.frame.Frame`
        return av_frame

    def terminate(self):
        """
        Gracefully terminates VideoGear stream
        """
        # don't forget this function!!!

        # terminate
        if not (self.stream is None):
            self.stream.stop()
            self.stream = None


# assign your custom media server to config with adequate source (for e.g. foo.mp4)
web.config["server"] = Custom_RTCServer()

# run this app on Uvicorn server at address http://localhost:8000/
uvicorn.run(web(), host="localhost", port=8000)

# close app safely
web.shutdown()

@abhiTronix abhiTronix added DOCS 📜 Issue/PR is related to vidgear docs. WORK IN PROGRESS 🚧 currently been worked on. labels Oct 3, 2021
abhiTronix added a commit that referenced this issue Oct 7, 2021
)

- 📝 Added new ScreenGear with WebGear_RTC API bonus example.
- 🚸 Added warning for ScreenGear outputting RGBA frames instead of default BGR frames with `mss` backend.
- ✏️ Several internal and external webpage links typos fixed.
- ♿️ Updated admonitions.

CI :
- 👷 Added wildcard to skip CI tests for doc(`.md`) files.
- 👷 Added `.md` files to Codecov ignore list.
@abhiTronix abhiTronix removed the BUG CONFIRMED ✅ Bug is confirmed! label Oct 7, 2021
@abhiTronix
Copy link
Owner

Successfully resolved and merged in commit 7cbc1bd

ScreenGear with WebGear_RTC Example is available here: https://abhitronix.github.io/vidgear/v0.2.3-dev/help/screengear_ex/#using-screengear-with-webgear_rtc

@abhiTronix abhiTronix added SOLVED 🏁 This issue/PR is resolved now. Goal Achieved! and removed WORK IN PROGRESS 🚧 currently been worked on. labels Oct 7, 2021
@harshitsinghai77
Copy link
Author

Hey, Thanks for this. I was caught up in some work. This looks good. Thanks again for fixing it so soon. Really great work.. Keep up the good work. I really like the project. 🚀🚀🚀

@abhiTronix abhiTronix linked a pull request Oct 27, 2021 that will close this issue
6 tasks
@abhiTronix abhiTronix added EXTERNAL BUG 👾 Bug caused by external dependent library and removed BUG 🐛 Vidgear api's error, flaw or fault labels Oct 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DOCS 📜 Issue/PR is related to vidgear docs. EXTERNAL BUG 👾 Bug caused by external dependent library SOLVED 🏁 This issue/PR is resolved now. Goal Achieved!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants