Closed reza-shahriari closed 1 week ago
i have found this code useful:
import asyncio
import cv2
import numpy as np
from aiortc import RTCPeerConnection, RTCSessionDescription, RTCIceCandidate, VideoStreamTrack
from aiortc.contrib.media import MediaRelay
import websockets
import json
import av
import time
class PixelStreamerVideoTrack(VideoStreamTrack):
def __init__(self, fps):
super().__init__()
self.frame_count = 0
self.fps = fps
self.pts_increment = 1000 // fps # Time increment per frame in milliseconds
async def recv(self):
self.frame_count += 1
# Calculate the pts based on the frame count and FPS
pts = self.frame_count * self.pts_increment
height, width = 1080, 1920
frame = np.zeros((height, width, 3), dtype=np.uint8)
# Convert the frame to an av.VideoFrame
video_frame = av.VideoFrame.from_ndarray(frame, format="bgr24")
video_frame.pts = pts
video_frame.time_base = av.Rational(1, 1000) # time_base in milliseconds
return video_frame
def modify_sdp_with_stream_id(sdp, stream_id):
lines = sdp.splitlines()
inserted = False
for i, line in enumerate(lines):
if line.startswith("m="): # Media section
lines.insert(i + 1, f"a=msid-semantic: WMS {stream_id}")
inserted = True
break
if not inserted:
# Handle error: stream ID not inserted
pass
return "\n".join(lines)
async def connect_to_pixel_streamer(streamer_id,fps):
pc = RTCPeerConnection()
relay = MediaRelay()
@pc.on("track")
def on_track(track):
print(f"Receiving {track.kind} track")
if track.kind == "video":
local_video = relay.subscribe(track)
async def consume_video():
frame_count = 0
t0 = time.time()
while True:
try:
frame_count+=1
frame = await local_video.recv()
# print("video_frame is : ", frame)
# print("Received frame resolution:", frame.width, "x", frame.height)
# print("Avg Frame Rate: ", frame_count/(time.time() - t0))
# img = cv2.cvtColor(np.array(frame.to_ndarray(format="bgr24")), cv2.COLOR_RGB2BGR)
img = np.array(frame.to_ndarray(format="bgr24"))
cv2.imshow('Pixel Streamer Video', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
except Exception as e:
print(f"Error processing video frame: {e}")
break
asyncio.ensure_future(consume_video())
# Add a video sender to create an offer with media
pc.addTrack(PixelStreamerVideoTrack(fps=fps,))
# Connect to the signaling server
async with websockets.connect(f"ws://localhost/") as ws:
# Send offer
offer = await pc.createOffer()
print(offer)
print("****************************************************************")
offer.sdp = modify_sdp_with_stream_id(offer.sdp, streamer_id)
print(offer)
await pc.setLocalDescription(offer)
message = json.dumps({
"type": "offer",
"sdp": pc.localDescription.sdp,
})
await ws.send(message)
print("Offer sent, waiting for answer...")
while True:
response = await ws.recv()
# print(f"Received message: {response}")
data = json.loads(response)
# for k , v in data.items():
# print(f"key: {k}, value: {v}")
if data["type"] == "answer":
print("Received answer")
await pc.setRemoteDescription(RTCSessionDescription(sdp=data["sdp"], type="answer"))
elif data["type"] == "iceCandidate":
print("Received ICE candidate")
candidate = data["candidate"]["candidate"]
try:
await pc.addIceCandidate(candidate)
except Exception as e:
print(f"Error adding ICE candidate: {e}")
elif data["type"] == "config":
print("Received config")
# Handle config if needed
elif data["type"] == "playerCount":
print(f"Player count: {data['count']}")
else:
print(f"Unhandled message type: {data['type']}")
# Check if connection is established
if pc.iceConnectionState == "connected":
print("WebRTC connection established")
break
# Keep the connection alive
while True:
try:
message = await asyncio.wait_for(ws.recv(), timeout=1.0)
print(f"Received message: {message}")
except asyncio.TimeoutError:
pass # No message received, continue
except websockets.exceptions.ConnectionClosed:
print("WebSocket connection closed")
break
if __name__ == "__main__":
# streamer_id = input("Enter the StreamerId: ")
streamer_id = "Camera1"
fps = 60
asyncio.run(connect_to_pixel_streamer(streamer_id,fps))
I'm experiencing low image quality when streaming video at 1920x1080 resolution and reading in the same size. The image quality is lower than expected. This issue only occurs when using a python, as I don't encounter the problem when using Chrome. Additionally, I'm unable to access my different cameras. No matter what streamer_id I input, I only get results from camera2. I've tried changing ws://localhost/
to ws://localhost/?streamerId=Camera1
, but it doesn't solve the problem.
Python is not something we support currently and so cannot really provide any input for this. However it should be reasonably straight forward to provide a video stream by following the UE plugin as a reference.
Additionally I currently have a JavaScript implementation of a streamer that might be helpful for you at my fork. This is something that is being developed to help testing and has very limited functionality but should provide a good reference for the bare minimum.
It sounds like you have several issues.
If you cannot switch streamers using the streamerId parameter then it sounds like your streamers are not identifying themselves correctly. It's also possible you're confusing "stream id" with "streamer id". Each streamer connected to the signalling server has it's own unique streamer id and that is what the streamerId parameter is selecting. We currently do not have a way to select individual streams from the one streamer.
The quality of the video stream will be completely up to the encoder or the quality of the stream provided. The front end will just display whatever video stream it receives.
Hope this helps.
It helped a lot, Thanks for the answer
Component your question relates to
Question
Hello everyone. Nice repo thanks for it 🙏 I found it really useful and it solved my biggest problem 😁 Is there any way I can capture the video from python outside unreal? Everything works good and I can open web browsers and see the streamed results but when I want to read video from the URL (localhost/?streamid=camera_1) there is no data in it. I have tested other URLs as well but I could not figure out how to read images Would you help me please Thanks a lot