Skip to content

Commit

Permalink
fix: Guess the content type of remote files as well
Browse files Browse the repository at this point in the history
* Move get_mime from cli to util

* StreamInfo: Add the guessed_content_type property

* Use the guessed content-type of the stream to initialize the call of play_media_url

This is more sensible than the default of video/mp4, not suitable for all media
files (like images).

* Rename get_mime into guess_mime

This better reflects the fact that is might be wrong sometimes.

* Rename is_video to is_remote_file

* Remove use of guess_mime from cli.py

* Make guess_mime return None if it can't make a guess

* Fix content_type fallback in play_media_url
  • Loading branch information
Konubinix authored and skorokithakis committed May 13, 2018
1 parent 0bbb6f0 commit e003fe7
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 31 deletions.
33 changes: 8 additions & 25 deletions catt/cli.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -181,25 +181,6 @@ def process_subtitle(ctx, param, value):
return value


def get_mime(path):
# source: https://developers.google.com/cast/docs/media
extension = Path(path).suffix.lower()
extensions = {
".mp4": "video/mp4",
".m4a": "audio/mp4",
".mp3": "audio/mp3",
".mpa": "audio/mpeg",
".webm": "video/webm",
".mkv": "video/x-matroska",
".bmp": "image/bmp",
".jpg": "image/jpeg",
".gif": "image/gif",
".png": "image/png",
".webp": "image/web",
}
return extensions.get(extension, "video/mp4")


@cli.command(short_help="Send a video to a Chromecast for playing.")
@click.argument("video_url", callback=process_url)
@click.option("-s", "--subtitle",
Expand All @@ -224,13 +205,13 @@ def cast(settings, video_url, subtitle, force_default, random_play, no_subs):
else:
subtitle_url = load_subtitle_if_exists(subtitle, video_url, stream.local_ip, stream.port + 1)

content_type = get_mime(video_url)
thr = Thread(target=serve_file,
args=(video_url, stream.local_ip, stream.port, content_type))
args=(video_url, stream.local_ip, stream.port, stream.guessed_content_type))

thr.setDaemon(True)
thr.start()
cst.play_media_url(stream.video_url, content_type=content_type, title=stream.video_title, subtitles=subtitle_url)
cst.play_media_url(stream.video_url, content_type=stream.guessed_content_type,
title=stream.video_title, subtitles=subtitle_url)
click.echo("Serving local file, press Ctrl+C when done.")
while thr.is_alive():
time.sleep(1)
Expand All @@ -255,7 +236,8 @@ def cast(settings, video_url, subtitle, force_default, random_play, no_subs):
if cst.info_type == "url":
cst.play_media_url(stream.playlist_entry_url,
title=stream.playlist_entry_title,
thumb=stream.playlist_entry_thumbnail)
thumb=stream.playlist_entry_thumbnail,
content_type=stream.guessed_content_type)
elif cst.info_type == "id":
cst.play_media_id(stream.playlist_entry_id)

Expand All @@ -264,7 +246,8 @@ def cast(settings, video_url, subtitle, force_default, random_play, no_subs):
click.echo("Playing %s on \"%s\"..." % (stream.video_title, cst.cc_name))
if cst.info_type == "url":
cst.play_media_url(stream.video_url, title=stream.video_title,
thumb=stream.video_thumbnail)
thumb=stream.video_thumbnail,
content_type=stream.guessed_content_type)
elif cst.info_type == "id":
cst.play_media_id(stream.video_id)

Expand All @@ -274,7 +257,7 @@ def cast(settings, video_url, subtitle, force_default, random_play, no_subs):
@click.pass_obj
def add(settings, video_url):
cst, stream = setup_cast(settings["device"], video_url=video_url, prep="control")
if (cst.name != "default" and cst.name != stream.extractor) or not stream.is_video:
if (cst.name != "default" and cst.name != stream.extractor) or not stream.is_remote_file:
raise CattCliError("This url cannot be added to the queue.")
cst.add(stream.video_id)

Expand Down
2 changes: 1 addition & 1 deletion catt/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ def __init__(self, cast, name, app_id, prep=None):
self._cast.app_id == DEFAULT_APP["app_id"]) else None

def play_media_url(self, video_url, **kwargs):
content_type = kwargs.get("content_type", "video/mp4")
content_type = kwargs.get("content_type") or "video/mp4"
self._controller.play_media(video_url, content_type,
current_time=kwargs.get("current_time"),
title=kwargs.get("title"), thumb=kwargs.get("thumb"),
Expand Down
17 changes: 14 additions & 3 deletions catt/stream_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import click
import youtube_dl

from .util import guess_mime


AUDIO_MODELS = [("Google Inc.", "Chromecast Audio")]
ULTRA_MODELS = [("Xiaomi", "MIBOX3"), ("Google Inc.", "Chromecast Ultra")]
Expand Down Expand Up @@ -56,7 +58,7 @@ def __init__(self, video_url, model=None, host=None):
self._info = self._get_stream_info(self._preinfo)

@property
def is_video(self):
def is_remote_file(self):
return not self.is_local_file and not self.is_playlist

@property
Expand Down Expand Up @@ -92,11 +94,20 @@ def video_url(self):

@property
def video_id(self):
return self._preinfo["id"] if self.is_video else None
return self._preinfo["id"] if self.is_remote_file else None

@property
def video_thumbnail(self):
return self._preinfo.get("thumbnail") if self.is_video else None
return self._preinfo.get("thumbnail") if self.is_remote_file else None

@property
def guessed_content_type(self):
if self.is_local_file:
return guess_mime(self.video_title)
elif self.is_remote_file and self._info.get("direct"):
return guess_mime(self._info["webpage_url_basename"])
else:
return None

@property
def playlist_length(self):
Expand Down
21 changes: 21 additions & 0 deletions catt/util.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
from pathlib import Path

import click


def warning(msg):
click.secho("Warning: ", fg="red", nl=False, err=True)
click.echo(msg, err=True)


def guess_mime(path):
# source: https://developers.google.com/cast/docs/media
extension = Path(path).suffix.lower()
extensions = {
".mp4": "video/mp4",
".m4a": "audio/mp4",
".mp3": "audio/mp3",
".mpa": "audio/mpeg",
".webm": "video/webm",
".mkv": "video/x-matroska",
".bmp": "image/bmp",
".jpg": "image/jpeg",
".gif": "image/gif",
".png": "image/png",
".webp": "image/web",
}
return extensions.get(extension, "video/mp4")
4 changes: 2 additions & 2 deletions tests/test_catt.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def test_stream_info_youtube_video(self):
stream = StreamInfo("https://www.youtube.com/watch?v=VZMfhtKa-wo")
self.assertIn("https://", stream.video_url)
self.assertEqual(stream.video_id, "VZMfhtKa-wo")
self.assertTrue(stream.is_video)
self.assertTrue(stream.is_remote_file)
self.assertEqual(stream.extractor, "youtube")

def test_stream_info_youtube_playlist(self):
Expand All @@ -26,7 +26,7 @@ def test_stream_info_other_video(self):
stream = StreamInfo("http://www.dailymotion.com/video/x6fotne")
self.assertIn("https://", stream.video_url)
self.assertEqual(stream.video_id, "x6fotne")
self.assertTrue(stream.is_video)
self.assertTrue(stream.is_remote_file)
self.assertEqual(stream.extractor, "dailymotion")

def test_cache(self):
Expand Down

0 comments on commit e003fe7

Please sign in to comment.