Сервер потокового видео WebRTC (Python) застрял при получении кадровPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Сервер потокового видео WebRTC (Python) застрял при получении кадров

Сообщение Anonymous »

Справочная информация:
Я работаю над сервером потокового видео WebRTC, используя aiortc и aiohttp. > на питоне. Цель состоит в том, чтобы сервер захватывал кадры с IP-камеры, обрабатывал их и затем передавал их клиенту. Для целей тестирования это упрощенная версия кода, в которой кадры захватываются с IP-камеры и напрямую передаются клиенту без дополнительной обработки (в оригинальной версии кадры проходят обработку перед отправкой клиенту).
Проблема:
Несмотря на успешное согласование ICE и прием трека на стороне клиента, клиент зависает при попытке получить видеокадры, и кажется, что серверный метод Recv() (который захватывает и отправляет кадры) никогда не запускается.
Я объясню настройку и поделюсь соответствующим кодом как для сервера (stream.py), так и для клиента. (client.py).
Сервер: stream.py

Код: Выделить всё

import cv2
import asyncio
import logging
import time
import numpy as np
from aiortc import VideoStreamTrack, RTCPeerConnection, RTCSessionDescription
from aiortc.mediastreams import VideoFrame
from aiohttp import web

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("WebRTC")

# WebRTC track for video streaming
class VideoProcessorTrack(VideoStreamTrack):
def __init__(self, camera_url, desired_fps=15):
super().__init__()
self.camera_url = camera_url
self.cap = cv2.VideoCapture(self.camera_url)
self.desired_fps = desired_fps
self.frame_interval = 1.0 / self.desired_fps  # Time interval between frames

if not self.cap.isOpened():
logger.error(f"Failed to open camera stream: {self.camera_url}")
else:
logger.info(f"Camera stream opened successfully: {self.camera_url}")

async def recv(self):
"""Capture and process frames from the camera."""
logger.info("Entering recv() method to capture frame")
await asyncio.sleep(self.frame_interval)

# Capture frame
ret, frame = self.cap.read()
if not ret:
logger.warning("Failed to read frame, sending empty frame...")
frame = np.zeros((480, 640, 3), dtype=np.uint8)  # Dummy black frame
else:
logger.info("Successfully captured a frame from the camera")

# Convert frame for WebRTC
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
video_frame = VideoFrame.from_ndarray(frame_rgb, format="rgb24")
video_frame.pts = time.time()
video_frame.time_base = 1 / self.desired_fps
logger.info("Frame is ready to be sent")
return video_frame

async def offer(request):
"""Handle incoming WebRTC offer and send the answer."""
try:
logger.info("Received offer request from the client")
params = await request.json()
logger.info(f"Parsed offer: {params}")

offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])
pc = RTCPeerConnection()

async def on_iceconnectionstatechange():
logger.info(f"ICE connection state is {pc.iceConnectionState}")
if pc.iceConnectionState == "completed":
logger.info("ICE connection completed successfully!")
elif pc.iceConnectionState == "failed":
logger.error("ICE connection failed.")

pc.on("iceconnectionstatechange", on_iceconnectionstatechange)

# Add video track to peer connection
player = VideoProcessorTrack(camera_url="http://129.125.136.20/axis-cgi/mjpg/video.cgi?camera=1", desired_fps=15)
logger.info("Adding video track to peer connection")
pc.addTrack(player)

# Log every time we receive a frame request
@pc.on("track")
async def on_track(track):
logger.info(f"Track {track.kind} received on the server")

# Handle the WebRTC offer/answer exchange
await pc.setRemoteDescription(offer)
answer = await pc.createAnswer()
await pc.setLocalDescription(answer)

logger.info("Local description set with the answer")
return web.json_response({"sdp": pc.localDescription.sdp, "type": pc.localDescription.type})

except Exception as e:
logger.error(f"Error in offer handling: {e}")
return web.Response(text="Internal Server Error", status=500)

app = web.Application()
app.router.add_post("/offer", offer)

if __name__ == "__main__":
logger.info("Starting WebRTC streaming server...")
web.run_app(app, port=8081)
Клиент: client.py

Код: Выделить всё

import asyncio
import cv2
from aiortc import RTCPeerConnection, RTCSessionDescription, MediaStreamTrack
import aiohttp
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("WebRTC Client")

class DummyVideoTrack(MediaStreamTrack):
kind = "video"

async def recv(self):
return None

async def run_client():
pc = RTCPeerConnection()

dummy_track = DummyVideoTrack()
pc.addTrack(dummy_track)

@pc.on("track")
async def on_track(track):
logger.info(f"Receiving track: {track.kind}")

if track.kind == "video":
cv2.namedWindow("WebRTC Stream", cv2.WINDOW_NORMAL)

while True:
try:
frame = await track.recv()  # Receive frame from track
img = frame.to_ndarray(format="bgr24")  # Convert frame to numpy array
logger.info(f"Frame received: {img.shape}")

# Display the frame using OpenCV
cv2.imshow("WebRTC Stream", img)

if cv2.waitKey(1) & 0xFF == ord('q'):
break  # Exit on 'q'
except Exception as e:
logger.error(f"Error processing frame: {e}")
break  # Break loop in case of errors

cv2.destroyAllWindows()  # Close the window when done
track.stop()

# Create WebRTC offer
offer = await pc.createOffer()
await pc.setLocalDescription(offer)

# Send offer to server
offer_payload = {
"sdp": pc.localDescription.sdp,
"type": pc.localDescription.type,
}
logger.info("Sending offer to server")

async with aiohttp.ClientSession() as session:
async with session.post("http://localhost:8081/offer", json=offer_payload) as response:
if response.status != 200:
logger.error(f"Server error: {response.status}")
return
answer = await response.json()
logger.info("Received answer from server")

await pc.setRemoteDescription(RTCSessionDescription(sdp=answer["sdp"], type=answer["type"]))
logger.info("Remote description set on client")

# Keep connection open
await asyncio.Future()

if __name__ == "__main__":
asyncio.run(run_client())
Что работает:
  • Клиент успешно отправляет предложение на сервер, и сервер
    отвечает с ответом.
  • Согласование ICE завершается успешно, и найдена допустимая пара-кандидат.
  • Клиент регистрирует дорожку приема: видео с указанием сервера отправляет видеодорожку.
Проблема:
Несмотря на успешное соединение ICE и обмен медиа-дорожками, клиент застревает на:

Код: Выделить всё

frame = await track.recv()
Похоже, что метод Recv() в VideoProcessorTrack сервера (который захватывает и отправляет кадры) никогда не срабатывает. Это означает, что клиент ожидает кадров, которые никогда не отправляются.
В чем мне нужна помощь:
  • Почему не запускается ли метод Recv() на сервере?
  • Что-то не так с согласованием отслеживания WebRTC между клиентом и сервером, что не позволяет серверу отправлять кадры?
    Как правильно заставить сервер начать отправку кадров клиенту?
Будем очень признательны за любую помощь или рекомендации. !

Подробнее здесь: https://stackoverflow.com/questions/790 ... ing-frames
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»