WebRTC aiortc - 将视频从 server.py 发送到 client.py 给出 RTCIceTransport 错误

问题描述 投票:0回答:1

我想使用 aiortc 和 TCPSocketHandling 将视频从 server.py 流式传输到 client.py。 我似乎确实按照 aiortc 示例和文档做了所有事情,但仍然收到以下错误:-

异常=InvalidStateError('RTCIceTransport 已关闭')>

附上client.py和server.py代码

服务器.py

import asyncio
import cv2
from aiortc import MediaStreamTrack, RTCPeerConnection, RTCSessionDescription, RTCIceCandidate
from aiortc.contrib.media import MediaBlackhole, MediaPlayer, MediaRelay
from aiortc.contrib.signaling import TcpSocketSignaling
from av import VideoFrame


class VideoStreamTrack(MediaStreamTrack):
    kind = "video"
    def __init__(self, video_path):
        super().__init__()  # Initialize the base class
        # self.track = track
        self.video_path = video_path
        self.cap = cv2.VideoCapture(video_path)

    async def recv(self):
        # Read frames from the video file and convert them to RTCVideoFrames
        ret, img = self.cap.read()
        if ret:
            # pts, time_base = await self.next_timestamp()
            frame = VideoFrame.from_ndarray(img, format="bgr24")
            # frame.pts = pts
            # frame.time_base = time_base
            # await asyncio.sleep(1/30)
            return frame
        else:
            # Video ended, close the connection
            self.cap.release()
            raise ConnectionError("Video stream ended")


async def serve_video(pc, signaling):
    # Create a MediaRelay to relay media tracks between peers
    relay = MediaRelay()
    # track = MediaStreamTrack()
    # Add the video track to the peer connection
    video_path = "test.mp4"
    video_track = VideoStreamTrack(video_path)
    pc.addTrack(relay.subscribe(video_track))

    # Create an offer and set it as the local description
    offer = await pc.createOffer()
    await pc.setLocalDescription(offer)

    # Send the offer to the client
    await signaling.send(pc.localDescription)

    # Wait for the answer from the client
    answer = await signaling.receive()
    if isinstance(answer, RTCSessionDescription):
            await pc.setRemoteDescription(answer)

    elif isinstance(answer, RTCIceCandidate):
            await pc.addIceCandidate(answer)
    # await pc.setRemoteDescription(RTCSessionDescription(answer))

    # Start relaying the media between peers
    # while True:
    #     try:
    #         frame = await video_track.recv()
    #         await pc.sendVideoFrame(frame)
    #     except ConnectionError:
    #         break

    # # Cleanup when done
    await pc.close()


async def main():
    pc = RTCPeerConnection()

    # Create a TCP socket signaling instance
    signaling = TcpSocketSignaling("127.0.0.1", 8080)

    # Connect to the signaling server
    await signaling.connect()

    # Serve the video
    await serve_video(pc, signaling)

    # Close the signaling connection
    await signaling.close()


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Client.py:-

import asyncio
import cv2
from aiortc import MediaStreamTrack, RTCPeerConnection, RTCSessionDescription, RTCIceCandidate
from aiortc.contrib.media import MediaBlackhole, MediaPlayer, MediaRelay
from aiortc.contrib.signaling import TcpSocketSignaling


class VideoStreamTrack(MediaStreamTrack):
    kind = "video"
    def __init__(self, track):
        super().__init__()  # Initialize the base class
        self.track = track

    async def recv(self):
        # Receive RTCVideoFrames and render them
        frame = await self.track.recv()
        if frame:
            img = frame.to_ndarray(format="bgr24")
            cv2.imshow("b", frame)
            print("a")
            cv2.waitKey(1)
        else:
            # Video ended, close the connection
            raise ConnectionError("Video stream ended")
        
        return frame


async def receive_video(pc, signaling):
    # Create a MediaRelay to relay media tracks between peers
    # relay = MediaRelay()

    offer = await signaling.receive()

    @pc.on("iceconnectionstatechange")
    async def on_iceconnectionstatechange():
        print("ICE connection state is %s" % pc.iceConnectionState)
        if pc.iceConnectionState == "failed":
            print("Error!!!")
            await pc.close()
            # pcs.discard(pc)

    @pc.on("track")
    def on_track(track):
        video_track = VideoStreamTrack(track)

    if isinstance(offer, RTCSessionDescription):
            await pc.setRemoteDescription(offer)

    elif isinstance(offer, RTCIceCandidate):
            await pc.addIceCandidate(offer)
    # await pc.setRemoteDescription(RTCSessionDescription(answer))
    # Create a renderer to display the received video
    

    # Add the video track to the peer connection
    # pc.addTrack(video_track)

    # Create an answer and set it as the local description


    await pc.setLocalDescription(await pc.createAnswer())

    # Send the answer back to the server
    await signaling.send(pc.localDescription)

    # Start relaying the media between peers
    # while True:
    #     try:
    #         await video_track.recv()
    #     except ConnectionError:
    #         break

    # Cleanup when done
    await pc.close()


async def main():
    pc = RTCPeerConnection()

    # Create a TCP socket signaling instance
    signaling = TcpSocketSignaling("127.0.0.1", 8080)

    # Connect to the signaling server
    await signaling.connect()

    # Receive the video
    await receive_video(pc, signaling)

    # Close the signaling connection
    await signaling.close()


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
python sockets video webrtc aiortc
1个回答
0
投票

你找到答案了吗?如果是的话可以分享一下吗?

© www.soinside.com 2019 - 2024. All rights reserved.