Skip to main content

Python module to talk to Google Chromecast.

Project description

Library for Python 3.11+ to communicate with the Google Chromecast. It currently supports:

  • Auto discovering connected Chromecasts on the network

  • Start the default media receiver and play any online media

  • Control playback of current playing media

  • Implement Google Chromecast api v2

  • Communicate with apps via channels

  • Easily extendable to add support for unsupported namespaces

  • Multi-room setups with Audio cast devices

Check out Home Assistant for a ready-made solution using PyChromecast for controlling and automating your Chromecast or Cast-enabled device like Google Home.

Dependencies

PyChromecast depends on the Python packages requests, protobuf and zeroconf. Make sure you have these dependencies installed using pip install -r requirements.txt

How to use

>> import time
>> import pychromecast
>> import zeroconf

>> # Create a browser which prints the friendly name of found chromecast devices
>> zconf = zeroconf.Zeroconf()
>> browser = pychromecast.CastBrowser(pychromecast.SimpleCastListener(lambda uuid, service: print(browser.devices[uuid].friendly_name)), zconf)
>> browser.start_discovery()
>> # Shut down discovery
>> pychromecast.discovery.stop_discovery(browser)

>> # Discover and connect to chromecasts named Living Room
>> chromecasts, browser = pychromecast.get_listed_chromecasts(friendly_names=["Living Room"])
>> [cc.cast_info.friendly_name for cc in chromecasts]
['Living Room']

>> # Discover and connect to more than one device
>> chromecasts, browser = pychromecast.get_listed_chromecasts(friendly_names=["Living Room","Bed Room","Kitchen"])
>> [cc.device.friendly_name for cc in chromecasts]
["Living Room","Bed Room","Kitchen"]

>> # If you are seeing less devices get discovered than expected add the below parameter. You can lessen or extend the timeout as needed.
>> chromecasts, browser = pychromecast.get_listed_chromecasts(friendly_names=["Living Room","Bed Room","Kitchen"],discovery_timeout=30)
>> [cc.device.friendly_name for cc in chromecasts]
["Living Room","Bed Room","Kitchen"]

>> cast = chromecasts[0]
>> # Start worker thread and wait for cast device to be ready
>> cast.wait()
>> print(cast.cast_info)
CastInfo(services={ServiceInfo(type='mdns', data='Chromecast-Audio-42feced1d94238232fba92623e2682f3._googlecast._tcp.local.')}, uuid=UUID('42feced1-d942-3823-2fba-92623e2682f3'), model_name='Chromecast Audio', friendly_name='Living room', host='192.168.0.189', port=8009, cast_type='audio', manufacturer='Google Inc.')

>> print(cast.status)
CastStatus(is_active_input=True, is_stand_by=False, volume_level=1.0, volume_muted=False, app_id='CC1AD845', display_name='Default Media Receiver', namespaces=['urn:x-cast:com.google.cast.player.message', 'urn:x-cast:com.google.cast.media'], session_id='CCA39713-9A4F-34A6-A8BF-5D97BE7ECA5C', transport_id='web-9', status_text='')

>> mc = cast.media_controller
>> mc.play_media('http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', 'video/mp4')
>> mc.block_until_active()
>> print(mc.status)
MediaStatus(current_time=42.458322, content_id='http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', content_type='video/mp4', duration=596.474195, stream_type='BUFFERED', idle_reason=None, media_session_id=1, playback_rate=1, player_state='PLAYING', supported_media_commands=15, volume_level=1, volume_muted=False)

>> mc.pause()
>> time.sleep(5)
>> mc.play()

>> # Shut down discovery
>> pychromecast.discovery.stop_discovery(browser)

Adding support for extra namespaces

Each app that runs on the Chromecast supports namespaces. They specify a JSON-based mini-protocol. This is used to communicate between the Chromecast and your phone/browser and now Python.

Support for extra namespaces is added by using controllers. To add your own namespace to a current chromecast instance you will first have to define your controller. Example of a minimal controller:

from pychromecast.controllers import BaseController

class MyController(BaseController):
    def __init__(self):
        super(MyController, self).__init__(
            "urn:x-cast:my.super.awesome.namespace")

    def receive_message(self, message, data):
        print("Wow, I received this message: {}".format(data))

        return True  # indicate you handled this message

    def request_beer(self):
        self.send_message({'request': 'beer'})

After you have defined your controller you will have to add an instance to a Chromecast object: cast.register_handler(MyController()). When a message is received with your namespace it will be routed to your controller.

For more options see the BaseController. For an example of a fully implemented controller see the MediaController.

Exploring existing namespaces

So you’ve got PyChromecast running and decided it is time to add support to your favorite app. No worries, the following instructions will have you covered in exploring the possibilities.

The following instructions require the use of the Google Chrome browser and the Google Cast plugin.

  • In Chrome, go to chrome://net-export/

  • Select ‘Include raw bytes (will include cookies and credentials)’

  • Click ‘Start Logging to Disk’

  • Open a new tab, browse to your favorite application on the web that has Chromecast support and start casting.

  • Go back to the tab that is capturing events and click on stop.

  • Open https://netlog-viewer.appspot.com/ and select your event log file.

  • Browse to https://netlog-viewer.appspot.com/#events&q=type:SOCKET, and find the socket that has familiar JSON data. (For me, it’s usually the second or third from the top.)

  • Go through the results and collect the JSON that is exchanged.

  • Now write a controller that is able to mimic this behavior :-)

Ignoring CEC Data

The Chromecast typically reports whether it is the active input on the device to which it is connected. This value is stored inside a cast object in the following property.

cast.status.is_active_input

Some Chromecast users have reported CEC incompatibilities with their media center devices. These incompatibilities may sometimes cause this active input value to be reported improperly.

This active input value is typically used to determine if the Chromecast is idle. PyChromecast is capable of ignoring the active input value when determining if the Chromecast is idle in the instance that the Chromecast is returning erroneous values. To ignore this CEC detection data in PyChromecast, append a Linux style wildcard formatted string to the IGNORE_CEC list in PyChromecast like in the example below.

pychromecast.IGNORE_CEC.append('*')  # Ignore CEC on all devices
pychromecast.IGNORE_CEC.append('Living Room')  # Ignore CEC on Chromecasts named Living Room

Networking requirements

Pychromecast relies on mDNS to discover cast devices. The mDNS protocol relies on multicast UDP on port 5353 which comes with several implications for discovery to work:

  • Multicast UDP must be forwarded by WiFI routers; some WiFi routers are known to drop multicast UDP traffic.

  • The device running pychromecast must allow both inbound and outbound traffic on port 5353.

  • The device running pychromecast must be on the same subnet as the cast devices because mDNS packets are not routed across subnets.

If not all of these conditions are met, discovery will not work. In cases where these conditions are impossible to meet, it’s possible to pass a list of known IP-addresses or host names to the discovery functions.

Thanks

I would like to thank Fred Clift for laying the socket client ground work. Without him it would not have been possible!

PyChromecast - A library from the Open Home Foundation

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pychromecast-14.0.10.tar.gz (61.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pychromecast-14.0.10-py2.py3-none-any.whl (77.5 kB view details)

Uploaded Python 2Python 3

File details

Details for the file pychromecast-14.0.10.tar.gz.

File metadata

  • Download URL: pychromecast-14.0.10.tar.gz
  • Upload date:
  • Size: 61.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for pychromecast-14.0.10.tar.gz
Algorithm Hash digest
SHA256 f05a1c8d727d4f104c8c731688053033e05157f2ab81bc8eef50ec0c62f9373c
MD5 a82386504b46b7e3ee71910ed9dbc5a0
BLAKE2b-256 3a1fd78497441334d24740cce0a92394c33972a9d6a17b607d0ec976f0f48a35

See more details on using hashes here.

File details

Details for the file pychromecast-14.0.10-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for pychromecast-14.0.10-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 f5ea52b1db0edc3019ec72c9f5354c7e77c2564ecd44f809a6d2f4f518a02e67
MD5 b477b8e92d6f40fb1ea08e712c5700eb
BLAKE2b-256 1f61f0f176622e2b4df06318a3abb2a27cc4c2fee8d40d7a0db8d60034785c09

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page