调用my_channel.send致windows-capture与aiortc协同异常问题
解决windows-capture回调中调用aiortc DataChannel.send导致的阻塞与协程未等待问题
问题根源
- windows-capture的
on_frame_arrived是同步阻塞回调,运行在专属的回调线程中。 - aiortc的
DataChannel.send()是异步方法,调用后会返回协程对象。直接在同步回调里调用该方法而不await,会触发RuntimeWarning: coroutine 'RTCSctpTransport._data_channel_flush' was never awaited错误,同时未被调度的协程会阻塞回调线程,导致后续帧回调无法触发(FPS打印停止),仅能发送一次消息。
解决方案
方案一:将异步send操作提交到aiortc的事件循环中
先保存aiortc运行的事件循环对象,在同步回调里通过线程安全的方法将send协程提交到事件循环执行,避免阻塞回调线程。
示例代码:
import asyncio from windows_capture import WindowsCapture, Frame from aiortc import RTCPeerConnection, RTCDataChannel # 保存aiortc依赖的事件循环 main_loop = asyncio.get_event_loop() data_channel: RTCDataChannel = None def on_frame_arrived(frame: Frame): global data_channel # 仅在通道就绪时发送消息 if data_channel and data_channel.readyState == "open": # 线程安全地将协程提交到主事件循环执行 asyncio.run_coroutine_threadsafe( data_channel.send("data sent from on_frame_arrived"), main_loop ) # 原有FPS打印逻辑 ... # 初始化windows-capture捕获 capture = WindowsCapture( on_frame_arrived=on_frame_arrived, capture_target=... # 你的捕获目标配置 ) capture.start() # aiortc连接处理逻辑 async def setup_peer_connection(): global data_channel pc = RTCPeerConnection() data_channel = pc.createDataChannel("frame_data") # 发送初始消息 await data_channel.send("Hello from Python aiortc server!") # 后续ICE协商等逻辑 ... main_loop.run_until_complete(setup_peer_connection()) main_loop.run_forever()
方案二:改用异步回调(若库支持)
如果windows-capture提供异步回调模式,可直接将on_frame_arrived定义为异步函数,在内部await data_channel.send()即可。但需先确认库是否支持该模式,若不支持则优先使用方案一。
注意事项
- 必须确保提交协程的事件循环是aiortc正在使用的主事件循环,不要在回调中新建事件循环。
- 每次发送前检查DataChannel的
readyState,避免在通道未打开/已关闭时发送消息。 - 高帧率场景下可适当控制消息发送频率,避免网络拥塞。
内容的提问来源于stack exchange,提问作者Dzenis Zigo
相关产品推荐
相关产品推荐

