Timeout context manager should be used inside a task
Opened this issue · 2 comments
TheNha commented
Hello,
I used Livekit Egress API, when I called start_track_composite_egress function. I got the following error :
[ERROR] File "/usr/local/lib/python3.9/site-packages/livekit/api/egress_service.py", line 51, in start_track_composite_egress
[ERROR] return await self._client.request(
[ERROR]
[ERROR] File "/usr/local/lib/python3.9/site-packages/livekit/api/twirp_client.py", line 93, in request
[ERROR] async with self._session.post(
[ERROR]
[ERROR] File "/usr/local/lib/python3.9/site-packages/aiohttp/client.py", line 1194, in __aenter__
[ERROR] self._resp = await self._coro
[ERROR]
[ERROR] File "/usr/local/lib/python3.9/site-packages/aiohttp/client.py", line 504, in _request
[ERROR] with timer:
[ERROR]
[ERROR] File "/usr/local/lib/python3.9/site-packages/aiohttp/helpers.py", line 715, in __enter__
[ERROR] raise RuntimeError(
[ERROR]
[ERROR] RuntimeError: Timeout context manager should be used inside a task
I used async_to_sync function of asgiref library from django.
async def start_track_composite_egress(start):
return await self.lvk_api.egress.start_track_composite_egress(start)
from asgiref.sync import async_to_sync
res_track_composite = async_to_sync(start_track_composite_egress)(start)
Please help me. Thank you.
xiaokang00010 commented
the same error occured to me.
here's my code:
@app.route("/api/v1/rtvc/establish", methods=["POST"])
async def establishRealTimeVoiceChat():
if not authenticateSession():
return {'data': 'not authenticated', 'status': False}
if not dProvider.checkIfInitialized():
return {'data': 'not initialized', 'status': False}
charName = ''
try:
data = flask.request.get_json()
charName = data['charName']
except:
return {'data': 'invalid form', 'status': False}
sessionName = uuid.uuid4().hex
session = webFrontend.chatbotManager.VoiceChatSession(sessionName, charName, dProvider)
userName = dProvider.getUserName()
userToken = livekit.api.AccessToken(
webFrontend.config.LIVEKIT_API_KEY, webFrontend.config.LIVEKIT_API_SECRET).with_identity(
'user').with_name(userName).with_grants(livekit.api.VideoGrants(room_join=True, room=sessionName)).to_jwt()
botToken = livekit.api.AccessToken(
webFrontend.config.LIVEKIT_API_KEY, webFrontend.config.LIVEKIT_API_SECRET).with_identity(
'model').with_name(charName).with_grants(livekit.api.VideoGrants(room_join=True, room=sessionName)).to_jwt()
# livekit api is in this file, so we can't put this logic into createRtSession
await livekitApi.room.create_room(create=livekit.api.CreateRoomRequest(name=sessionName, empty_timeout=10*60, max_participants=2))
Update:
I came up with a solution. Define a event loop by asyncio.new_event_loop()
and use it like
# livekit api is in this file, so we can't put this logic into createRtSession
async def f():
await livekitApi.room.create_room(create=livekit.api.CreateRoomRequest(name=sessionName, empty_timeout=10*60, max_participants=2))
session.start(botToken)
asyncio.run_coroutine_threadsafe(f(), asyncEventLoop)
It took me at least 1 hour to solve it.
Update:
Fk it. I didn't solve it. However, it just stuck there and refused to create room. I gonna to sleep now.
Update:
My final solution is to use
async def getLiveKitAPI():
return livekit.api.LiveKitAPI(webFrontend.config.LIVEKIT_API_URL, webFrontend.config.LIVEKIT_API_KEY, webFrontend.config.LIVEKIT_API_SECRET)
Which livekitApi should be initialized in an async def
function and can't be initialized globally.
This explained.
theomonnom commented
maybe you can use an asyncio event_loop and using run_until_complete?