]> code.delx.au - webdl/blob - brightcove.py
iview: Use HLS instead of RTMP
[webdl] / brightcove.py
1 import re
2 import sys
3
4 from common import grab_json, download_rtmp, Node, append_to_qs
5
6 CH9_TOKEN = "ogxhPgSphIVa2hhxbi9oqtYwtg032io4B4-ImwddYliFWHqS0UfMEw.."
7 CH10_TOKEN = "lWCaZyhokufjqe7H4TLpXwHSTnNXtqHxyMvoNOsmYA_GRaZ4zcwysw.."
8
9 BRIGHTCOVE_API = "http://api.brightcove.com/services/library?"
10 HASH_URL = "http://admin.brightcove.com/viewer/us20130530.1140/connection/ExternalConnection_2.swf"
11
12
13 class BrightcoveVideoNode(Node):
14 def __init__(self, title, parent, token, video_id):
15 Node.__init__(self, title, parent)
16 self.can_download = True
17 self.token = token
18 self.video_id = video_id
19
20 def download(self):
21 desc_url = append_to_qs(BRIGHTCOVE_API, {
22 "token": self.token,
23 "command": "find_video_by_id",
24 "video_fields": "renditions",
25 "video_id": self.video_id,
26 })
27 print "video desc_url", desc_url
28
29 doc = grab_json(desc_url, 3600)
30
31 best_encoding_rate = 0
32 best_url = None
33 for item in doc['renditions']:
34 encoding_rate = item['encodingRate']
35 if encoding_rate > best_encoding_rate:
36 best_encoding_rate = encoding_rate
37 best_url = item['url']
38
39 if best_url is None:
40 raise Exception("Could not find video URL: " + desc_url)
41
42 vbase, vpath = best_url.split("&")
43 filename = self.title + ".mp4"
44 return download_rtmp(filename, vbase, vpath, HASH_URL)
45
46
47 class BrightcoveRootNode(Node):
48 def __init__(self, title, parent, token):
49 Node.__init__(self, title, parent)
50 self.token = token
51 self.series_nodes = {}
52
53 def get_series_node(self, series_name):
54 series_name = series_name.split("-")[0].strip()
55 key = series_name.lower()
56 node = self.series_nodes.get(key, None)
57 if node is None:
58 node = Node(series_name, self)
59 self.series_nodes[key] = node
60 return node
61
62 def fill_children(self):
63 page_number = 0
64 while page_number < 100:
65 sys.stdout.write(".")
66 sys.stdout.flush()
67 url = self.get_all_videos_url(page_number)
68 page_number += 1
69
70 page = grab_json(url, 3600)
71 items = page["items"]
72 if len(items) == 0:
73 break
74
75 for video_desc in items:
76 self.process_video(video_desc)
77 print
78
79 def process_video(self, video_desc):
80 if not video_desc["customFields"]:
81 return
82
83 video_id = video_desc["id"]
84 title = self.get_video_title(video_desc)
85 series_name = self.get_series_name(video_desc)
86
87 parent_node = self.get_series_node(series_name)
88 BrightcoveVideoNode(title, parent_node, self.token, video_id)
89
90 def get_video_title(self, video_desc):
91 raise NotImplementedError()
92
93 def get_series_name(self, video_desc):
94 raise NotImplementedError()
95
96 def get_all_videos_url(self, page_number):
97 raise NotImplementedError()
98
99
100 class Ch9RootNode(BrightcoveRootNode):
101 def __init__(self, root_node):
102 BrightcoveRootNode.__init__(self, "Nine", root_node, CH9_TOKEN)
103
104 def get_video_title(self, video_desc):
105 title = video_desc["name"]
106 season = video_desc["customFields"].get("season", "")
107 episode = video_desc["customFields"].get("episode", "1").rjust(2, "0")
108 series = self.get_series_name(video_desc)
109
110 if re.match(R"ep(isode)?\s*[0-9]+\s*:", title.lower()):
111 title = title.split(":", 1)[1].strip()
112
113 title = "%s - %sx%s - %s" % (
114 series,
115 season,
116 episode,
117 title
118 )
119 return title
120
121 def get_series_name(self, video_desc):
122 series = video_desc["customFields"].get("series", None)
123 if not series:
124 series = video_desc["name"]
125 return series
126
127 def get_all_videos_url(self, page_number):
128 return append_to_qs(BRIGHTCOVE_API, {
129 "token": self.token,
130 "command": "search_videos",
131 "video_fields": "id,name,customFields",
132 "custom_fields": "series,season,episode",
133 "sort_by": "PUBLISH_DATE",
134 "page_number": str(page_number),
135 })
136
137
138 class Ch10RootNode(BrightcoveRootNode):
139 def __init__(self, root_node):
140 BrightcoveRootNode.__init__(self, "Ten", root_node, CH10_TOKEN)
141
142 def get_video_title(self, video_desc):
143 return video_desc["name"]
144
145 def get_series_name(self, video_desc):
146 return video_desc["customFields"]["tv_show"]
147
148 def get_all_videos_url(self, page_number):
149 return append_to_qs(BRIGHTCOVE_API, {
150 "token": self.token,
151 "command": "search_videos",
152 "video_fields": "id,name,customFields",
153 "custom_fields": "tv_show",
154 "sort_by": "PUBLISH_DATE",
155 "any": "video_type_long_form:Full Episode",
156 "page_number": str(page_number),
157 })
158
159
160 def fill_nodes(root_node):
161 Ch9RootNode(root_node)
162 Ch10RootNode(root_node)
163