home-assistant-libs / pychromecast

Library for Python 3 to communicate with the Google Chromecast.
MIT License
2.54k stars 381 forks source link

External subtitles? #74

Open skorokithakis opened 8 years ago

skorokithakis commented 8 years ago

Is it possible to add an external subtitle track, e.g. from a URL containing an .srt file? If so, how?

moiseslodeiro commented 8 years ago

I've trying to modify the media.py including the following code but subtitles dont work.. did you solved your problem skorokithakis?

msg['media']['tracks']['trackId'] = 1 msg['media']['tracks']['trackContentId'] = 'http://192.168.1.10:8000/testsub.vtt' msg['media']['tracks']['language'] = 'en-US' msg['media']['tracks']['subtype'] = 'SUBTITLES' msg['media']['tracks']['type'] = 'TEXT' msg['media']['tracks']['trackContentType'] = 'text/vtt' msg['media']['tracks']['name'] = 'English Subtitle'

And then using mc.enable_subtitles(1) but nothing happens...

skorokithakis commented 8 years ago

No, unfortunately, I never did...

palaviv commented 8 years ago

Your problem might be CORS(Cross-origin resource sharing). You should try adding Access-Control-Allow-Origin: * to the headers of the http servers that provide the media and the subtitle tracks.

fortizc commented 7 years ago

Your problem might be CORS(Cross-origin resource sharing). You should try adding Access-Control-Allow-Origin: * to the headers of the http servers that provide the media and the subtitle tracks.

I trying to do the same using my own http server, something like this:

mc.play_media('http://my_host/video.mkv', 'video/mkv',
         subtitles="http://my_host/subs.srt",
         subtitles_mime="text/srt",
         subtitle_id=1,
         subtitles_lang="es-CL"
)

and then mc.enable_subtitles(1) without luck :-(

palaviv commented 7 years ago

Try to add mc.update_status(blocking=True) between the play_media and the mc.enable_subtitles(1). You can look at https://github.com/palaviv/caster for what I do to make the subtitles work.

fortizc commented 7 years ago

Still unlucky, I try this:

import pychromecast as cast
c = cast.get_chromecast(friendly_name="Cast")
c.wait()
mc = c.media_controller
mc.play_media(
        "http://mi_ip:port/path_to_my_folder/mr.mkv",
        "video/x-matroska",
        title="hola",
        subtitles="http://mi_ip:port/path_to_my_folder/mr.vtt",
        subtitles_lang='es-CL',
        subtitles_mime="text/vtt"
)
mc.update_status(blocking=True)
mc.enable_subtitle(1)

To ensure that my server is OK I use the code from caster to create a server and when run it, in the terminal I see something like this

192.168.3.126 - - [14/Dec/2016 01:40:49] "GET /Users/fortiz/mr.vtt HTTP/1.1" 200 -
192.168.3.126 - - [14/Dec/2016 01:40:49] "GET /Users/fortiz/mr.mkv HTTP/1.1" 206 -

And video begin in my TV, but without subtitles...

There is a code block in caster that maybe can help, is called from here this function (get_internal_ip) receive the chromecast IP but when I execute it I have the follow error OSError: [Errno 49] Can't assign requested address then I try to download and execute caster but fail in the same way... any ideas? what value does get_internal_ip() return?

palaviv commented 7 years ago

@fortizc would you mind opening an issue in caster with the stack trace from the error in get_internal_ip?

Anyway get_internal_ip only return the ip of the interface that should be used to listen for the chromecast HTTP requests. You can just change it to return '0.0.0.0' and everything should work.

I actually did not tried to use any subtitles other then English. Can you try using English subtitles just so we can rule this out. Also can you request the status of the device and post it here after the mc.enable_subtitle(1) in your code?

fortizc commented 7 years ago

@fortizc would you mind opening an issue in caster with the stack trace from the error in get_internal_ip?

Ready!

Anyway get_internal_ip only return the ip of the interface that should be used to listen for the chromecast HTTP requests. You can just change it to return '0.0.0.0' and everything should work.

Ok

I actually did not tried to use any subtitles other then English. Can you try using English subtitles just so we can rule this out.

Now I try to use play_mediain the same way how you di in caster, look my script

import pychromecast as cast
c = cast.get_chromecast(friendly_name="Cast")
c.wait()
print("HOST: ", c.host, type(c.host))
mc = c.media_controller
mc.play_media(
        "http://192.168.3.119:50222/Users/fortiz/mr.mkv",
        "video/x-matroska",
        title="hola",
        subtitles="http://192.168.3.119:50222/Users/fortiz/mr.vtt"
)
mc.update_status(blocking=True)
mc.enable_subtitle(1)

mc.update_status()
print(c.status)
print(mc.status)

Also can you request the status of the device and post it here after the mc.enable_subtitle(1) in your code?

Yes!, and this is the result:

CastStatus(
    is_active_input=False,
    is_stand_by=True,
    volume_level=1.0,
    volume_muted=False,
    app_id='CC1AD845',
    display_name='Default Media Receiver',
    namespaces=['urn:x-cast:com.google.cast.broadcast', 'urn:x-cast:com.google.cast.media'],
    session_id='8303a1a1-355f-4286-8e25-f2b6985e58e0',
    transport_id='8303a1a1-355f-4286-8e25-f2b6985e58e0',
    status_text='Now Casting: hola'
)
<MediaStatus {
    'supports_pause': True,
    'artist': None,
    'track': None,
    'supports_stream_volume': True,
    'series_title': None,
    'metadata_type': None,
    'supports_skip_forward': False,
    'title': 'hola',
    'media_custom_data': {},
    'media_session_id': 7,
    'album_name': None,
    'episode': None,
    'current_time': 0,
    'playback_rate': 1,
    'volume_level': 1,
    'album_artist': None,
    'supports_skip_backward': False,
    'subtitle_tracks': [{
        'subtype': 'SUBTITLES',
        'name': 'en-US - 1 Subtitle',
        'type': 'TEXT',
        'language': 'en-US',
        'trackId': 1,
        'trackContentId': 'http://192.168.3.119:50222/Users/fortiz/mr.vtt',
        'trackContentType': 'text/vtt'
    }],
    'volume_muted': False,
    'images': [],
    'supports_seek': True,
    'supported_media_commands': 15,
    'idle_reason': 'INTERRUPTED',
    'stream_type': 'BUFFERED',
    'content_id': 'http://192.168.3.119:50222/Users/fortiz/mr.mkv',
    'supports_stream_mute': True,
    'player_state': 'BUFFERING',
    'content_type': 'video/x-matroska',
    'media_metadata': {'title': 'hola'},
    'season': None,
    'duration': 3051.136
}>

Any ideas?

palaviv commented 7 years ago

Could you put blocking=True in the second update_status please

muammar commented 7 years ago

I have tried this and it does not work. The blocking=True option seems to be for older pychromecast versions. The piece of code that I use is this:

media_controller.play_media('http://'+localip+':5000/stream', mtype, title = self.title, subtitles='http://0.0.0.0:8000/something.vtt', subtitle_id=1 )

if self.subtitles != None:
       media_controller.enable_subtitle(1)

I can see that the chromecast is accessing the file:

Serving HTTP on 0.0.0.0 port 8000 ...
127.0.0.1 - - [27/Mar/2017 19:18:56] "GET /Homeland.S06E10.720p.HEVC.x265-MeGusta.vtt HTTP/1.1" 200 -
127.0.0.1 - - [27/Mar/2017 19:19:42] "GET /Homeland.S06E10.720p.HEVC.x265-MeGusta.vtt HTTP/1.1" 200 -

But then, nothing happens...

blacklight commented 5 years ago

Same issue here:

  1. blocking=True on update_status() has been removed by the most recent versions of pychromecast. update_status() now comes with an optional callback parameter instead.

  2. Even when I do something like this, things don't work:

mc.play_media('http://192.168.1.2:8008/media.mp4', 'video/mp4',
    subtitles='http://192.168.1.2:8008/media.vtt', subtitle_id=1)

def set_subtitles_async(status):
    def callback():
        mc.enable_subtitle(1)

    if subtitles:
        mc.update_status(callback)

mc.register_status_listener(set_subtitles_async)

The playback doesn't start at all (it starts when I don't pass the subtitles option to play_media), the status handler is never triggered and no errors are returned, so I've got no clue at all of what's going on.

The subtitles file btw is in vtt format and it's served by the same server that hosts the media. I've tried with plenty of media and subtitles content so far so I can definitely confirm that it's a bug on pychromecast side: subtitles don't work at all, unless the devs have a workaround to get them working that I'm missing.

I know that it's been a while since this issue was opened but can someone please investigate?

blacklight commented 5 years ago

Bump - any hints on where to look to debug the problem?

jakobkhansen commented 5 years ago

I also have this issue and would like a fix. As far as I can tell, no srt files work.

narocath commented 4 years ago

I have also have the same problem with vtt, anyone can indicate any workaround or any hint?

blacklight commented 4 years ago

@palaviv blocking=True has been removed from update_status, but I would expect the code snippet that I've previously posted (which registers an asynchronous status listener to set the subtitle track) to work. Is there any reason why it doesn't work? Is it supposed to work and it's a bug, or is there another (undocumented) way to set the subtitle track with the right timing with the new asynchronous API?

narocath commented 4 years ago

Sorry for the late response, when I try the callback method I get errors:

Traceback (most recent call last):
  File "/home/naro/.local/lib/python3.8/site-packages/pychromecast/controllers/media.py", line 481, in _fire_status_changed
    listener.new_media_status(self.status)
AttributeError: 'function' object has no attribute 'new_media_status'

The video file is served by executing python -m http.server in the folder and the server shows that both files video and vtt are served from server:

192.168.2.5 - - [14/Nov/2020 13:03:36] "GET /Apollo%2018.2011.720p.BrRip.x264.YIFY.mp4 HTTP/1.1" 200 -
192.168.2.5 - - [14/Nov/2020 13:03:40] "GET /Apollo%2018.2011.720p.BrRip.x264.YIFY.vtt HTTP/1.1" 200 -

The video though is playing normal on chromecast but without subtitles. Any ideas?

JonasVautherin commented 1 year ago

Same problem here: cannot get subtitles to work... though I seem to remember that mkchromecast (which was using pychromecast) and I'm sure that catt (I believe also using pychromecast) manage to make subtitles work... I'll have a look there.

JonasVautherin commented 1 year ago

It works for me with WebVTT subtitles files. As mentioned in the catt Readme:

Although Chromecast only supports WEBVTT, TTML and Line 21 subtitles, catt conveniently converts SRTs to WEBVTT for you on the fly.

Also I had missed it, but it's documented by Chromecast:

Your subtitle resources must implement [CORS](https://developers.google.com/cast/docs/player#cors).

    [TTML - Timed Text Markup Language](http://www.w3.org/TR/ttaf1-dfxp/)
    [WebVTT - Web Video Text Tracks](http://dev.w3.org/html5/webvtt/)
    [CEA-608/708](https://www.cta.tech/Research-Standards/Standards-Listing/Test-Materials.aspx)