Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Communicate blocks the asyncio loop briefly at the start #223

Closed
lanzz opened this issue May 18, 2024 · 3 comments
Closed

Communicate blocks the asyncio loop briefly at the start #223

lanzz opened this issue May 18, 2024 · 3 comments

Comments

@lanzz
Copy link

lanzz commented May 18, 2024

Test case:

import asyncio
import edge_tts


TEXT = (
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt '
    'ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco '
    'laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in '
    'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat '
    'cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
)

async def edge_request():
    req = edge_tts.Communicate(TEXT)
    return b''.join([chunk['data'] async for chunk in req.stream() if chunk['type'] == 'audio'])


async def dummy_sleep():
    await asyncio.sleep(2)


async def test(fn) -> None:
    print(f'testing {fn!r}')
    edge_task = asyncio.create_task(fn())
    while not edge_task.done():
        await asyncio.wait({edge_task}, timeout=.1)
        print('tick')
    print('done')


asyncio.run(test(edge_request))
asyncio.run(test(dummy_sleep))

It runs the test twice, once executing an edge-tts request, and a second time executing just a regular asyncio.sleep(). You can see that with the sleep there's no pauses between the printed "tick"-s, but with the edge-tts request there is a brief, but noticeable pause before the first tick (so that's when await asyncio.wait yields the execution to the loop and the edge_request task starts to run, before the first asyncio.wait timeout), then it seems that after the stream is started the rest of the ticks get printed without blocks.

I can work around this by running the edge-tts request in an asyncio.to_thread executor, but it seems to indicate something not really async happening in edge-tts.

@rany2
Copy link
Owner

rany2 commented May 18, 2024

I modified your script slightly and can't repro. I don't notice any blocks either. This is what I used to confirm this:

import asyncio
import edge_tts
import timeit


TEXT = (
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt '
    'ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco '
    'laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in '
    'voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat '
    'cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
)

async def edge_request():
    req = edge_tts.Communicate(TEXT)
    return b''.join([chunk['data'] async for chunk in req.stream() if chunk['type'] == 'audio'])


async def dummy_sleep():
    await asyncio.sleep(2)


async def test(fn) -> None:
    print(f'testing {fn!r}')
    x = 0
    y = timeit.default_timer()
    i = 0
    edge_task = asyncio.create_task(fn())
    while not edge_task.done():
        await asyncio.wait({edge_task}, timeout=.1)
        x = y
        y = timeit.default_timer()
        i += 1
        print(f'elapsed time: {y - x:.2f} seconds ({i} iterations)')



asyncio.run(test(edge_request))
asyncio.run(test(dummy_sleep))

@rany2
Copy link
Owner

rany2 commented May 18, 2024

I know that async on Windows is pretty buggy, so maybe you're using that platform?

@lanzz
Copy link
Author

lanzz commented May 20, 2024

Yeah, I can confirm that this only occurs on Windows, tested on macOS and Linux and there's no block there. Oh well.

@lanzz lanzz closed this as completed May 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants