From f6113c0bbb49c553ecfb80f132f93a912a5deee5 Mon Sep 17 00:00:00 2001 From: fanpt <320622572@qq.com> Date: Fri, 8 Aug 2025 15:15:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0offer=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=B0=83=E8=AF=95=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 153 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 116 insertions(+), 37 deletions(-) diff --git a/app.py b/app.py index 825c223..bea7992 100644 --- a/app.py +++ b/app.py @@ -110,62 +110,141 @@ def build_nerfreal(sessionid:int)->BaseReal: #@app.route('/offer', methods=['POST']) async def offer(request): - params = await request.json() - offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"]) - - # if len(nerfreals) >= opt.max_session: - # logger.info('reach max session') - # return web.Response( - # content_type="application/json", - # text=json.dumps( - # {"code": -1, "msg": "reach max session"} - # ), - # ) - sessionid = randN(6) #len(nerfreals) + logger.info("开始处理offer请求") + + # 接收请求参数 + try: + params = await request.json() + logger.debug("接收到的请求参数: %s", params) + except Exception as e: + logger.error("解析请求参数失败: %s", str(e)) + return web.Response( + content_type="application/json", + text=json.dumps({"code": -2, "msg": "解析参数失败"}) + ) + + # 验证必要参数 + if "sdp" not in params or "type" not in params: + logger.warning("请求参数缺少sdp或type字段: %s", params) + return web.Response( + content_type="application/json", + text=json.dumps({"code": -3, "msg": "缺少必要参数"}) + ) + + # 创建RTCSessionDescription + try: + offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"]) + logger.debug("成功创建RTCSessionDescription,类型: %s", params["type"]) + except Exception as e: + logger.error("创建RTCSessionDescription失败: %s", str(e)) + return web.Response( + content_type="application/json", + text=json.dumps({"code": -4, "msg": "创建offer失败"}) + ) + + # 生成会话ID并记录 + sessionid = randN(6) nerfreals[sessionid] = None - logger.info('sessionid=%d, session num=%d',sessionid,len(nerfreals)) - nerfreal = await asyncio.get_event_loop().run_in_executor(None, build_nerfreal,sessionid) - nerfreals[sessionid] = nerfreal - - #ice_server = RTCIceServer(urls='stun:stun.l.google.com:19302') - ice_server = RTCIceServer(urls='stun:stun.miwifi.com:3478') - pc = RTCPeerConnection(configuration=RTCConfiguration(iceServers=[ice_server])) - pcs.add(pc) + logger.info('生成新会话,sessionid=%d, 当前会话数量=%d', sessionid, len(nerfreals)) + + # 构建nerfreal + try: + logger.debug("开始构建nerfreal,sessionid=%d", sessionid) + nerfreal = await asyncio.get_event_loop().run_in_executor(None, build_nerfreal, sessionid) + nerfreals[sessionid] = nerfreal + logger.info("成功构建nerfreal,sessionid=%d", sessionid) + except Exception as e: + logger.error("构建nerfreal失败,sessionid=%d: %s", sessionid, str(e)) + del nerfreals[sessionid] + return web.Response( + content_type="application/json", + text=json.dumps({"code": -5, "msg": "构建会话失败"}) + ) + + # 配置ICE服务器并创建RTCPeerConnection + try: + ice_server = RTCIceServer(urls='stun:stun.miwifi.com:3478') + logger.debug("使用ICE服务器: %s", ice_server.urls) + + pc = RTCPeerConnection(configuration=RTCConfiguration(iceServers=[ice_server])) + pcs.add(pc) + logger.info("创建RTCPeerConnection成功,sessionid=%d", sessionid) + except Exception as e: + logger.error("创建RTCPeerConnection失败,sessionid=%d: %s", sessionid, str(e)) + del nerfreals[sessionid] + return web.Response( + content_type="application/json", + text=json.dumps({"code": -6, "msg": "创建连接失败"}) + ) + # 连接状态变化处理 @pc.on("connectionstatechange") async def on_connectionstatechange(): - logger.info("Connection state is %s" % pc.connectionState) + logger.info("sessionid=%d, 连接状态变更为: %s", sessionid, pc.connectionState) if pc.connectionState == "failed": + logger.warning("sessionid=%d, 连接失败,关闭连接", sessionid) await pc.close() pcs.discard(pc) del nerfreals[sessionid] if pc.connectionState == "closed": + logger.info("sessionid=%d, 连接已关闭", sessionid) pcs.discard(pc) del nerfreals[sessionid] gc.collect() + logger.debug("sessionid=%d, 已清理资源", sessionid) - player = HumanPlayer(nerfreals[sessionid]) - audio_sender = pc.addTrack(player.audio) - video_sender = pc.addTrack(player.video) - capabilities = RTCRtpSender.getCapabilities("video") - preferences = list(filter(lambda x: x.name == "H264", capabilities.codecs)) - preferences += list(filter(lambda x: x.name == "VP8", capabilities.codecs)) - preferences += list(filter(lambda x: x.name == "rtx", capabilities.codecs)) - transceiver = pc.getTransceivers()[1] - transceiver.setCodecPreferences(preferences) + # 添加媒体轨道 + try: + player = HumanPlayer(nerfreals[sessionid]) + audio_sender = pc.addTrack(player.audio) + video_sender = pc.addTrack(player.video) + logger.debug("sessionid=%d, 已添加音频和视频轨道", sessionid) + except Exception as e: + logger.error("sessionid=%d, 添加媒体轨道失败: %s", sessionid, str(e)) + return web.Response( + content_type="application/json", + text=json.dumps({"code": -7, "msg": "添加媒体轨道失败"}) + ) - await pc.setRemoteDescription(offer) + # 配置编解码器偏好 + try: + capabilities = RTCRtpSender.getCapabilities("video") + preferences = list(filter(lambda x: x.name == "H264", capabilities.codecs)) + preferences += list(filter(lambda x: x.name == "VP8", capabilities.codecs)) + preferences += list(filter(lambda x: x.name == "rtx", capabilities.codecs)) + logger.debug("sessionid=%d, 编解码器偏好: %s", sessionid, [p.name for p in preferences]) + + transceiver = pc.getTransceivers()[1] + transceiver.setCodecPreferences(preferences) + logger.debug("sessionid=%d, 已设置编解码器偏好", sessionid) + except Exception as e: + logger.error("sessionid=%d, 配置编解码器失败: %s", sessionid, str(e)) - answer = await pc.createAnswer() - await pc.setLocalDescription(answer) + # 处理offer并创建answer + try: + await pc.setRemoteDescription(offer) + logger.debug("sessionid=%d, 已设置远程描述", sessionid) - #return jsonify({"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}) + answer = await pc.createAnswer() + await pc.setLocalDescription(answer) + logger.debug("sessionid=%d, 已创建并设置本地answer", sessionid) + except Exception as e: + logger.error("sessionid=%d, 处理offer创建answer失败: %s", sessionid, str(e)) + return web.Response( + content_type="application/json", + text=json.dumps({"code": -8, "msg": "处理offer失败"}) + ) + # 返回结果 + response_data = { + "sdp": pc.localDescription.sdp, + "type": pc.localDescription.type, + "sessionid": sessionid + } + logger.info("sessionid=%d, offer请求处理完成,返回响应", sessionid) return web.Response( content_type="application/json", - text=json.dumps( - {"sdp": pc.localDescription.sdp, "type": pc.localDescription.type, "sessionid":sessionid} - ), + text=json.dumps(response_data) ) async def human(request):