X-Git-Url: https://code.delx.au/webdl/blobdiff_plain/b6ad3911d2593698d5ed405520aa2cc0e6ce2ea0..8bacc845a0e6e2d1665fd94ec82e50211f928a2c:/brightcove.py diff --git a/brightcove.py b/brightcove.py index 4c4e096..7bb5737 100644 --- a/brightcove.py +++ b/brightcove.py @@ -1,163 +1,151 @@ -#!/usr/bin/env python -# vim:ts=4:sts=4:sw=4:noet - import re import sys -from common import grab_json, download_rtmp, Node, append_to_qs +from common import grab_json, download_hls, Node, append_to_qs CH9_TOKEN = "ogxhPgSphIVa2hhxbi9oqtYwtg032io4B4-ImwddYliFWHqS0UfMEw.." CH10_TOKEN = "lWCaZyhokufjqe7H4TLpXwHSTnNXtqHxyMvoNOsmYA_GRaZ4zcwysw.." BRIGHTCOVE_API = "http://api.brightcove.com/services/library?" -HASH_URL = "http://admin.brightcove.com/viewer/us20130530.1140/connection/ExternalConnection_2.swf" class BrightcoveVideoNode(Node): - def __init__(self, title, parent, token, video_id): - Node.__init__(self, title, parent) - self.can_download = True - self.token = token - self.video_id = video_id - - def download(self): - desc_url = append_to_qs(BRIGHTCOVE_API, { - "token": self.token, - "command": "find_video_by_id", - "video_fields": "renditions", - "video_id": self.video_id, - }) - print "video desc_url", desc_url - - doc = grab_json(desc_url, 3600) - - best_encoding_rate = 0 - best_url = None - for item in doc['renditions']: - encoding_rate = item['encodingRate'] - if encoding_rate > best_encoding_rate: - best_encoding_rate = encoding_rate - best_url = item['url'] - - if best_url is None: - raise Exception("Could not find video URL: " + desc_url) - - vbase, vpath = best_url.split("&") - filename = self.title + ".mp4" - return download_rtmp(filename, vbase, vpath, HASH_URL) - + def __init__(self, title, parent, token, video_id): + Node.__init__(self, title, parent) + self.can_download = True + self.token = token + self.video_id = video_id + + def download(self): + desc_url = append_to_qs(BRIGHTCOVE_API, { + "token": self.token, + "command": "find_video_by_id", + "video_fields": "HLSURL", + "video_id": self.video_id, + }) + doc = grab_json(desc_url, 3600) + video_url = doc["HLSURL"] + if not video_url: + print("No HLS stream available for: " + self.title) + return False + + filename = self.title + ".ts" + return download_hls(filename, video_url) class BrightcoveRootNode(Node): - def __init__(self, title, parent, token): - Node.__init__(self, title, parent) - self.token = token - self.series_nodes = {} - - def get_series_node(self, series_name): - series_name = series_name.split("-")[0].strip() - key = series_name.lower() - node = self.series_nodes.get(key, None) - if node is None: - node = Node(series_name, self) - self.series_nodes[key] = node - return node - - def fill_children(self): - page_number = 0 - while page_number < 100: - sys.stdout.write(".") - sys.stdout.flush() - url = self.get_all_videos_url(page_number) - page_number += 1 - - page = grab_json(url, 3600) - items = page["items"] - if len(items) == 0: - break - - for video_desc in items: - self.process_video(video_desc) - print - - def process_video(self, video_desc): - if not video_desc["customFields"]: - return - - video_id = video_desc["id"] - title = self.get_video_title(video_desc) - series_name = self.get_series_name(video_desc) - - parent_node = self.get_series_node(series_name) - BrightcoveVideoNode(title, parent_node, self.token, video_id) - - def get_video_title(self, video_desc): - raise NotImplementedError() - - def get_series_name(self, video_desc): - raise NotImplementedError() - - def get_all_videos_url(self, page_number): - raise NotImplementedError() + def __init__(self, title, parent, token): + Node.__init__(self, title, parent) + self.token = token + self.series_nodes = {} + + def get_series_node(self, series_name): + series_name = series_name.split("-")[0].strip() + key = series_name.lower() + node = self.series_nodes.get(key, None) + if node is None: + node = Node(series_name, self) + self.series_nodes[key] = node + return node + + def fill_children(self): + page_number = 0 + while page_number < 100: + sys.stdout.write(".") + sys.stdout.flush() + url = self.get_all_videos_url(page_number) + page_number += 1 + + page = grab_json(url, 3600) + items = page["items"] + if len(items) == 0: + break + + for video_desc in items: + self.process_video(video_desc) + print + + def process_video(self, video_desc): + if not video_desc["customFields"]: + return + + video_id = video_desc["id"] + title = self.get_video_title(video_desc) + series_name = self.get_series_name(video_desc) + + parent_node = self.get_series_node(series_name) + BrightcoveVideoNode(title, parent_node, self.token, video_id) + + def get_video_title(self, video_desc): + raise NotImplementedError() + + def get_series_name(self, video_desc): + raise NotImplementedError() + + def get_all_videos_url(self, page_number): + raise NotImplementedError() class Ch9RootNode(BrightcoveRootNode): - def __init__(self, root_node): - BrightcoveRootNode.__init__(self, "Nine", root_node, CH9_TOKEN) - - def get_video_title(self, video_desc): - title = video_desc["name"] - series = video_desc["customFields"]["series"] - season = video_desc["customFields"].get("season", "") - episode = video_desc["customFields"].get("episode", "1").rjust(2, "0") - - if re.match(R"ep(isode)?\s*[0-9]+\s*:", title.lower()): - title = title.split(":", 1)[1].strip() - - title = "%s - %sx%s - %s" % ( - series, - season, - episode, - title - ) - return title - - def get_series_name(self, video_desc): - return video_desc["customFields"]["series"] - - def get_all_videos_url(self, page_number): - return append_to_qs(BRIGHTCOVE_API, { - "token": self.token, - "command": "search_videos", - "video_fields": "id,name,customFields", - "custom_fields": "series,season,episode", - "sort_by": "PUBLISH_DATE", - "page_number": str(page_number), - }) + def __init__(self, root_node): + BrightcoveRootNode.__init__(self, "Nine", root_node, CH9_TOKEN) + + def get_video_title(self, video_desc): + title = video_desc["name"] + season = video_desc["customFields"].get("season", "") + episode = video_desc["customFields"].get("episode", "1").rjust(2, "0") + series = self.get_series_name(video_desc) + + if re.match(R"ep(isode)?\s*[0-9]+\s*:", title.lower()): + title = title.split(":", 1)[1].strip() + + title = "%s - %sx%s - %s" % ( + series, + season, + episode, + title + ) + return title + + def get_series_name(self, video_desc): + series = video_desc["customFields"].get("series", None) + if not series: + series = video_desc["name"] + return series + + def get_all_videos_url(self, page_number): + return append_to_qs(BRIGHTCOVE_API, { + "token": self.token, + "command": "search_videos", + "video_fields": "id,name,customFields", + "custom_fields": "series,season,episode", + "sort_by": "PUBLISH_DATE", + "page_number": str(page_number), + }) class Ch10RootNode(BrightcoveRootNode): - def __init__(self, root_node): - BrightcoveRootNode.__init__(self, "Ten", root_node, CH10_TOKEN) + def __init__(self, root_node): + BrightcoveRootNode.__init__(self, "Ten", root_node, CH10_TOKEN) - def get_video_title(self, video_desc): - return video_desc["name"] + def get_video_title(self, video_desc): + return video_desc["name"] - def get_series_name(self, video_desc): - return video_desc["customFields"]["tv_show"] + def get_series_name(self, video_desc): + return video_desc["customFields"]["tv_show"] - def get_all_videos_url(self, page_number): - return append_to_qs(BRIGHTCOVE_API, { - "token": self.token, - "command": "search_videos", - "video_fields": "id,name,customFields", - "custom_fields": "tv_show", - "sort_by": "PUBLISH_DATE", - "any": "video_type_long_form:Full Episode", - "page_number": str(page_number), - }) + def get_all_videos_url(self, page_number): + return append_to_qs(BRIGHTCOVE_API, { + "token": self.token, + "command": "search_videos", + "video_fields": "id,name,customFields", + "custom_fields": "tv_show", + "sort_by": "PUBLISH_DATE", + "any": "video_type_long_form:Full Episode", + "page_number": str(page_number), + }) def fill_nodes(root_node): - Ch9RootNode(root_node) - Ch10RootNode(root_node) + Ch9RootNode(root_node) + Ch10RootNode(root_node)