]>
code.delx.au - webdl/blob - brightcove.py
2 # vim:ts=4:sts=4:sw=4:noet
7 from common
import grab_json
, download_rtmp
, Node
, append_to_qs
9 CH9_TOKEN
= "ogxhPgSphIVa2hhxbi9oqtYwtg032io4B4-ImwddYliFWHqS0UfMEw.."
10 CH10_TOKEN
= "lWCaZyhokufjqe7H4TLpXwHSTnNXtqHxyMvoNOsmYA_GRaZ4zcwysw.."
12 BRIGHTCOVE_API
= "http://api.brightcove.com/services/library?"
13 HASH_URL
= "http://admin.brightcove.com/viewer/us20130530.1140/connection/ExternalConnection_2.swf"
16 class BrightcoveVideoNode(Node
):
17 def __init__(self
, title
, parent
, token
, video_id
):
18 Node
.__init
__(self
, title
, parent
)
19 self
.can_download
= True
21 self
.video_id
= video_id
24 desc_url
= append_to_qs(BRIGHTCOVE_API
, {
26 "command": "find_video_by_id",
27 "video_fields": "renditions",
28 "video_id": self
.video_id
,
30 print "video desc_url", desc_url
32 doc
= grab_json(desc_url
, 3600)
34 best_encoding_rate
= 0
36 for item
in doc
['renditions']:
37 encoding_rate
= item
['encodingRate']
38 if encoding_rate
> best_encoding_rate
:
39 best_encoding_rate
= encoding_rate
40 best_url
= item
['url']
43 raise Exception("Could not find video URL: " + desc_url
)
45 vbase
, vpath
= best_url
.split("&")
46 filename
= self
.title
+ ".mp4"
47 return download_rtmp(filename
, vbase
, vpath
, HASH_URL
)
50 class BrightcoveRootNode(Node
):
51 def __init__(self
, title
, parent
, token
):
52 Node
.__init
__(self
, title
, parent
)
54 self
.series_nodes
= {}
56 def get_series_node(self
, series_name
):
57 series_name
= series_name
.split("-")[0].strip()
58 key
= series_name
.lower()
59 node
= self
.series_nodes
.get(key
, None)
61 node
= Node(series_name
, self
)
62 self
.series_nodes
[key
] = node
65 def fill_children(self
):
66 print "Notice! Brightcove API (Ch9 & Ch10) support is still experimental."
68 while page_number
< 100:
71 url
= self
.get_all_videos_url(page_number
)
74 page
= grab_json(url
, 3600)
79 for video_desc
in items
:
80 self
.process_video(video_desc
)
83 def process_video(self
, video_desc
):
84 if not video_desc
["customFields"]:
87 video_id
= video_desc
["id"]
88 title
= self
.get_video_title(video_desc
)
89 series_name
= self
.get_series_name(video_desc
)
91 parent_node
= self
.get_series_node(series_name
)
92 BrightcoveVideoNode(title
, parent_node
, self
.token
, video_id
)
94 def get_video_title(self
, video_desc
):
95 raise NotImplementedError()
97 def get_series_name(self
, video_desc
):
98 raise NotImplementedError()
100 def get_all_videos_url(self
, page_number
):
101 raise NotImplementedError()
104 class Ch9RootNode(BrightcoveRootNode
):
105 def __init__(self
, root_node
):
106 BrightcoveRootNode
.__init
__(self
, "Nine", root_node
, CH9_TOKEN
)
108 def get_video_title(self
, video_desc
):
109 title
= video_desc
["name"]
110 series
= video_desc
["customFields"]["series"]
111 season
= video_desc
["customFields"].get("season", "")
112 episode
= video_desc
["customFields"].get("episode", "1").rjust(2, "0")
114 if re
.match(R
"ep(isode)?\s*[0-9]+\s*:", title
.lower()):
115 title
= title
.split(":", 1)[1].strip()
117 title
= "%s - %sx%s - %s" % (
125 def get_series_name(self
, video_desc
):
126 return video_desc
["customFields"]["series"]
128 def get_all_videos_url(self
, page_number
):
129 return append_to_qs(BRIGHTCOVE_API
, {
131 "command": "search_videos",
132 "video_fields": "id,name,customFields",
133 "custom_fields": "series,season,episode",
134 "sort_by": "PUBLISH_DATE",
135 "page_number": str(page_number
),
139 class Ch10RootNode(BrightcoveRootNode
):
140 def __init__(self
, root_node
):
141 BrightcoveRootNode
.__init
__(self
, "Ten", root_node
, CH10_TOKEN
)
143 def get_video_title(self
, video_desc
):
144 return video_desc
["name"]
146 def get_series_name(self
, video_desc
):
147 return video_desc
["customFields"]["tv_show"]
149 def get_all_videos_url(self
, page_number
):
150 return append_to_qs(BRIGHTCOVE_API
, {
152 "command": "search_videos",
153 "video_fields": "id,name,customFields",
154 "custom_fields": "tv_show",
155 "sort_by": "PUBLISH_DATE",
156 "any": "video_type_long_form:Full Episode",
157 "page_number": str(page_number
),
161 def fill_nodes(root_node
):
162 Ch9RootNode(root_node
)
163 Ch10RootNode(root_node
)