andrew-ld / smart-tv-telegram

stream movies from telegram to smart tv
GNU Affero General Public License v3.0
177 stars 54 forks source link

asyncio.exceptions.CancelledError #31

Open johnd0e opened 1 year ago

johnd0e commented 1 year ago

Occurs when sending video to bot, immediately after I choose device from list.

I have tried to update some packages, but still no luck.

Exception in thread Thread-3:
Traceback (most recent call last):
  File "C:\Apps\Python\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "C:\Apps\Python\Lib\site-packages\pychromecast\socket_client.py", line 525, in run
    self.initialize_connection()
  File "C:\Apps\Python\Lib\site-packages\pychromecast\socket_client.py", line 295, in initialize_connection
    host, port, service_info = get_host_from_service(
                               ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Apps\Python\Lib\site-packages\pychromecast\dial.py", line 38, in get_host_from_service
    service_info = zconf.get_service_info("_googlecast._tcp.local.", service.data)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Apps\Python\Lib\site-packages\zeroconf\_core.py", line 540, in get_service_info
    if info.request(self, timeout, question_type):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Apps\Python\Lib\site-packages\zeroconf\_services\info.py", line 473, in request
    return bool(run_coro_with_timeout(self.async_request(zc, timeout, question_type), zc.loop, timeout))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Apps\Python\Lib\site-packages\zeroconf\_utils\asyncio.py", line 82, in run_coro_with_timeout
    return asyncio.run_coroutine_threadsafe(aw, loop).result(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Apps\Python\Lib\concurrent\futures\_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Apps\Python\Lib\concurrent\futures\_base.py", line 401, in __get_result
    raise self._exception
  File "C:\Apps\Python\Lib\site-packages\zeroconf\_services\info.py", line 482, in async_request
    await zc.async_wait_for_start()
  File "C:\Apps\Python\Lib\site-packages\zeroconf\_core.py", line 507, in async_wait_for_start
    raise NotRunningException
zeroconf._exceptions.NotRunningException
ERROR:pyrogram.dispatcher:
Traceback (most recent call last):
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\bot.py", line 199, in _select_device
    await device.play(uri, data.filename, local_token)
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\devices\chromecast_device.py", line 60, in play
    await run_method_in_executor(self._device.wait)
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\tools.py", line 120, in run_method_in_executor
    return await asyncio.get_event_loop().run_in_executor(_EXECUTOR, func, *args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Apps\Python\Lib\site-packages\pyrogram\dispatcher.py", line 240, in handler_worker
    await handler.callback(self.client, *args)
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\bot.py", line 191, in _select_device
    async with async_timeout.timeout(self._config.device_request_timeout) as timeout_context:
  File "C:\Apps\Python\Lib\site-packages\async_timeout\__init__.py", line 129, in __aexit__
    self._do_exit(exc_type)
  File "C:\Apps\Python\Lib\site-packages\async_timeout\__init__.py", line 212, in _do_exit
    raise asyncio.TimeoutError
TimeoutError
andrew-ld commented 1 year ago

increase device_request_timeout on configuration

johnd0e commented 1 year ago

device_request_timeout=100:

Exception in thread Thread-4:
Traceback (most recent call last):
  File "C:\Apps\Python\lib\threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\socket_client.py", line 527, in run
    self.initialize_connection()
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\socket_client.py", line 297, in initialize_connection
    host, port, service_info = get_host_from_service(
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\dial.py", line 38, in get_host_from_service
    service_info = zconf.get_service_info("_googlecast._tcp.local.", service.data)
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\zeroconf\_core.py", line 595, in get_service_info
    if info.request(self, timeout, question_type):
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\zeroconf\_services\info.py", line 647, in request
    run_coro_with_timeout(
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\zeroconf\_utils\asyncio.py", line 86, in run_coro_with_timeout
    return asyncio.run_coroutine_threadsafe(aw, loop).result(
  File "C:\Apps\Python\lib\concurrent\futures\_base.py", line 458, in result
    return self.__get_result()
  File "C:\Apps\Python\lib\concurrent\futures\_base.py", line 403, in __get_result
    raise self._exception
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\zeroconf\_services\info.py", line 671, in async_request
    await zc.async_wait_for_start()
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\zeroconf\_core.py", line 562, in async_wait_for_start
    raise NotRunningException
zeroconf._exceptions.NotRunningException
andrew-ld commented 1 year ago

try pip3 install -U PyChromecast

johnd0e commented 1 year ago

try pip3 install -U PyChromecast

Unfortunately that makes no difference

andrew-ld commented 1 year ago

https://github.com/andrew-ld/smart-tv-telegram/blob/646158e11800dfbb7cf2f306ed0cd403b6c7b2e0/smart_tv_telegram/devices/chromecast_device.py#L60

it seems that device.wait() (pychromecast function) gives this error, there is something wrong with pychromecast itself

maybe this call is optional, try removing this line

johnd0e commented 1 year ago

No luck..

  File "D:\repo\smart-tv-telegram\venv\Lib\site-packages\pychromecast\socket_client.py", line 928, in send_message
    raise NotConnected(f"Chromecast {self.host}:{self.port} is connecting...")
pychromecast.error.NotConnected: Chromecast unknown:8009 is connecting...

And I have checked pychromecast alone, it's ok:

D:\repo\pychromecast\examples (master)>media_example.py
Found chromecast with name "TV", attempting to play "https://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/dash/nonuk/dash_low/ak/bbc_radio_fourfm.mpd"
Player state: UNKNOWN
Player state: IDLE
Player state: BUFFERING
Player state: PLAYING
andrew-ld commented 1 year ago

try remove stop_discovery line instead of wait

johnd0e commented 1 year ago

try remove stop_discovery line instead of wait

This works, partly.

Also in some cases I get this error in console:

INFO:pychromecast.controllers:Receiver:Stopping current app 'CC1AD845'
ERROR:aiohttp.server:Error handling request
Traceback (most recent call last):
  File "C:\Apps\Python\Lib\asyncio\windows_events.py", line 572, in finish_send
    return ov.getresult()
           ^^^^^^^^^^^^^^
OSError: [WinError 64] The specified network name is no longer available
andrew-ld commented 1 year ago

it seems that the pychromecast api has changed over time, the whole file should be rewritten with the new functions

andrew-ld commented 1 year ago

in the examples (by homeassistant) now use get_listed_chromecasts to get the list of chromecasts, quick_play.quick_play to play a url in the chromecast

andrew-ld commented 1 year ago

@johnd0e can try cast_refcounting_broswer branch, i have tried to update pychromecast to latest version and with the quick_play api

johnd0e commented 1 year ago

Supported devices not found in the network.

chromecast_enabled=1
chromecast_scan_timeout=200
andrew-ld commented 1 year ago

now should be fixed in the same branch

johnd0e commented 1 year ago

Chromecast with Google TV:

Exception in thread Thread-5:
Traceback (most recent call last):
  File "C:\Users\anton\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\socket_client.py", line 525, in run
    self.initialize_connection()
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\socket_client.py", line 295, in initialize_connection
    host, port, service_info = get_host_from_service(
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\dial.py", line 38, in get_host_from_service
    service_info = zconf.get_service_info("_googlecast._tcp.local.", service.data)
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\zeroconf\_core.py", line 540, in get_service_info
    if info.request(self, timeout, question_type):
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\zeroconf\_services\info.py", line 470, in request
    assert zc.loop is not None and zc.loop.is_running()
AssertionError

Google Nest Mini:

Traceback (most recent call last):
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\bot.py", line 212, in _select_device
    await device.play(uri, data.filename, local_token)
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\devices\chromecast_device.py", line 90, in play
    await run_method_in_executor(pychromecast.quick_play.quick_play, self._device, ascii_only(title), dict(media_id=url))
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\tools.py", line 122, in run_method_in_executor
    return await asyncio.get_event_loop().run_in_executor(_EXECUTOR, partial_function)
  File "C:\Users\anton\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\quick_play.py", line 73, in quick_play
    raise NotImplementedError()
NotImplementedError
andrew-ld commented 1 year ago

now should be fixed, the problem has the app name, it should be "default_media_receiver" instead of title of media

johnd0e commented 1 year ago
  1. When I cast to "Chromecast with Google TV" - I get same AssertionError
  2. When I cast to "Google nest Mini" then the media begins to play on Chromecast instead (waking it up successfully). But +30s /-30s still broken.
andrew-ld commented 1 year ago

can you start the program with "-v 2" argument and send full log for debug the assertion error

johnd0e commented 1 year ago

Sure https://pastebin.com/1j20A2x3

andrew-ld commented 1 year ago

the pastebin is inacessible

Error, this is a private paste or is pending moderation. If this paste belongs to you, please login to Pastebin to view it.

johnd0e commented 1 year ago

Sorry, fixed

andrew-ld commented 1 year ago

seem that other projects have the same problem

try to manually update zeroconf from PIP

https://github.com/alexdelorenzo/cast_control/issues/15#issuecomment-950948767

andrew-ld commented 1 year ago

maybe could be fixed with the latest commit

johnd0e commented 1 year ago

try to manually update zeroconf from PIP

Well, that changed the things. Sending video to Chromecast succeeded. But then I have tried to send file to Google Mini, and Play/Pause/Stop buttons appeared, but that's all (no playing). And all following attempts to send anything to any (of mine two) devices result to same effect - I see buttons, but no playing. I tried to restart script but no effect either.

maybe could be fixed with the latest commit

Will try later

johnd0e commented 1 year ago

maybe could be fixed with the latest commit

With zeroconf 0.31:

INFO:pychromecast.socket_client:[TV(192.168.0.124):8009] Connection reestablished!
WARNING:pychromecast.controllers:Quick Play failed for http://192.168.0.88:8350/stream/583/9457612367961363624:video/mp4({})
Traceback (most recent call last):
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\bot.py", line 212, in _select_device
    await device.play(uri, data.filename, local_token)
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\devices\chromecast_device.py", line 91, in play
    await run_method_in_executor(pychromecast.quick_play.quick_play, self._device, "default_media_receiver", dict(media_id=url))
  File "D:\repo\smart-tv-telegram\smart_tv_telegram\tools.py", line 122, in run_method_in_executor
    return await asyncio.get_event_loop().run_in_executor(_EXECUTOR, partial_function)
  File "C:\Users\anton\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\quick_play.py", line 77, in quick_play
    controller.quick_play(**data)
  File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\controllers\media.py", line 547, in quick_play
    raise PyChromecastError()
pychromecast.error.PyChromecastError

And what is important: I see exactly the same error when I send audio file, and when I try cast to another device. Maybe current state is somewhat broken in my network, or I do no know...

andrew-ld commented 1 year ago

if you don't see the video maybe the audio/video codec of the video you sent is not supported https://developers.google.com/cast/docs/media

andrew-ld commented 1 year ago

anyway i have reverted quick_play to play_media in the latest commit

johnd0e commented 1 year ago

if you don't see the video maybe the audio/video codec of the video you sent is not supported

I am absolutely sure that it is supported because I use the same video over and over again.

Maybe current state is somewhat broken in my network, or I do no know...

I have rebooted the Chromecast, and thigs changed. zeroconf 0.39.3 + quick_play

Next thing I am going to (re)try - zeroconf 0.31 + quick_play

johnd0e commented 1 year ago

Next thing I am going to (re)try - zeroconf 0.31 + quick_play

Casting to both devices results in playing media on Chromecast. But again - I was able to do this only once, and things get broken again - I see buttons in chat, but media is not playing. No errors in terminal.

It seems that zeroconf 0.31 is not an option.

P.S Next thing I am going to (re)try - play_media with different versions of zeroconf. Will be back in the evening

andrew-ld commented 1 year ago

maybe cannot play multiple times because only a single zeroconf instance should exists, with latest commit always reuse the same instance

johnd0e commented 1 year ago
ERROR:pychromecast.socket_client:[(unknown):8009] Failed to connect. No retries.
ERROR:pychromecast.socket_client:[(unknown):8009] Failed to connect. No retries.

P.S.

seem that other projects have the same problem

They are referencing catt project. I have checked - at the moment they use zeroconf 0.74.0. And casting seems working ok for both of my devices.

andrew-ld commented 1 year ago

since catt seems to work for you and has usable api's for everyone I decided to use catt instead of pychromecast, catt already seems to handle all the cases internally, try the latest commit

johnd0e commented 1 year ago

catt instead of pychromecast

Sounds like overkill, because is catt is so much bigger, and in turn does include same pychromecast. But make sense if you are going to support streaming media for web sites.

Anyway, it begins to work. All except -30 s/ +30s. catt itself handles them without problems

catt -d TV cast http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4

And some other issues.

  1. If while playing video on the Chromecast I press Back (or Home) button on Chromecast's remote - I get this in terminal:
    
    INFO:pychromecast:Starting app CC1AD845
    INFO:pychromecast.controllers:Receiver:Launching app CC1AD845
    ERROR:aiohttp.server:Error handling request
    Traceback (most recent call last):
    File "C:\Users\anton\AppData\Local\Programs\Python\Python310\lib\asyncio\windows_events.py", line 552, in finish_send
    return ov.getresult()
    OSError: [WinError 64] The specified network name is no longer available

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "D:\repo\smart-tv-telegram\venv\lib\site-packages\aiohttp\web_protocol.py", line 433, in _handle_request resp = await request_handler(request) File "D:\repo\smart-tv-telegram\venv\lib\site-packages\aiohttp\web_app.py", line 504, in _handle resp = await handler(request) File "D:\repo\smart-tv-telegram\smart_tv_telegram\http.py", line 254, in _stream_handler await stream.write(block) File "D:\repo\smart-tv-telegram\venv\lib\site-packages\aiohttp\web_response.py", line 514, in write await self._payload_writer.write(data) File "D:\repo\smart-tv-telegram\venv\lib\site-packages\aiohttp\http_writer.py", line 119, in write await self.drain() File "D:\repo\smart-tv-telegram\venv\lib\site-packages\aiohttp\http_writer.py", line 171, in drain await self._protocol._drain_helper() File "D:\repo\smart-tv-telegram\venv\lib\site-packages\aiohttp\base_protocol.py", line 90, in _drain_helper await asyncio.shield(waiter) File "C:\Users\anton\AppData\Local\Programs\Python\Python310\lib\asyncio\proactor_events.py", line 385, in _loop_writing f.result() File "C:\Users\anton\AppData\Local\Programs\Python\Python310\lib\asyncio\windows_events.py", line 826, in _poll value = callback(transferred, key, ov) File "C:\Users\anton\AppData\Local\Programs\Python\Python310\lib\asyncio\windows_events.py", line 556, in finish_send raise ConnectionResetError(*exc.args) ConnectionResetError: [WinError 64] The specified network name is no longer available

If I am trying to send video again - I see buttons in chat, but nothing happens on TV.
So I have to restart bot to continue.

2. As my Chromecast is Android device, usually I can return back to previous activity, via taskswitcher.
But if I try to do so with just interrupted video - I get this in terminal:

ERROR:pychromecast.socket_client:[(192.168.0.124):8009] Error reading from socket. ERROR:pychromecast.socket_client:[TV(192.168.0.124):8009] Error reading from socket. WARNING:pychromecast.socket_client:[(192.168.0.124):8009] Error communicating with socket, resetting connection WARNING:pychromecast.socket_client:[TV(192.168.0.124):8009] Error communicating with socket, resetting connection INFO:pychromecast.controllers:Receiver:channel_disconnected INFO:pychromecast.controllers:Receiver:channel_disconnected ERROR:pychromecast.socket_client:[TV(192.168.0.124):8009] Unhandled exception in worker thread, attempting reconnect Traceback (most recent call last): File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\socket_client.py", line 540, in run if self.run_once(timeout=POLL_TIME_BLOCKING) == 1: File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\socket_client.py", line 563, in run_once if not self._check_connection(): File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\socket_client.py", line 696, in _check_connection self.initialize_connection() File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\socket_client.py", line 297, in initialize_connection host, port, service_info = get_host_from_service( File "D:\repo\smart-tv-telegram\venv\lib\site-packages\pychromecast\dial.py", line 38, in get_host_from_service service_info = zconf.get_service_info("_googlecast._tcp.local.", service.data) File "D:\repo\smart-tv-telegram\venv\lib\site-packages\zeroconf_core.py", line 595, in get_service_info if info.request(self, timeout, question_type): File "D:\repo\smart-tv-telegram\venv\lib\site-packages\zeroconf_services\info.py", line 667, in request assert zc.loop is not None and zc.loop.is_running() AssertionError


And this is not single message - it is repeated over and over again until I break execution by hands.
With `catt` I cannot return to previous activity as well, but it does not breaks in this case.
andrew-ld commented 1 year ago

pychromecast seems really fragile in handling the same device multiple times in the same python process (catt uses pychromecast but it already handles the various more complex cases that I would have to do)

the first problem i.e. ConnectionResetError is expected, nothing special happens if it is shown in console

andrew-ld commented 1 year ago

one thing that comes to mind is to not create multiple instances of pychromecast for the same device but keep it cached to avoid multiple connections which seems really problematic with zeroconf and pychromecas

In the last commit I tried to make a cache by device

johnd0e commented 1 year ago

In the last commit I tried to make a cache by device

Nothing changed in behavior.

ConnectionResetError is expected, nothing special happens if it is shown in console

Note that problem is not console message. Casting stops working after that.

andrew-ld commented 1 year ago

What app do you use to emulate chromecast on android?

johnd0e commented 1 year ago

There is nothing to emulate as it is genuine Chromecast from Google: https://store.google.com/DE/product/chromecast_google_tv There is https://play.google.com/store/apps/details?id=com.google.android.apps.mediashell, but it is built-in in firmware. There is no possibility to install the APK to arbitrary android device.