def delete_video(video_id, cascade=False, delete_shares=False, connection=None): c = connection if not c: c = APIConnection() c.post('delete_video', video_id=video_id, cascade=cascade, delete_shares=delete_shares)
def activate(class_, video_id, connection=None): c = connection if not c: c = APIConnection() data = c.post('update_video', video={ 'id': video_id, 'itemState': ItemStateEnum.ACTIVE}) return class_(data=data)
def __init__(self, name=None, type=None, id=None, reference_id=None, data=None, connection=None): self.id = None self.reference_id = None self.account_id = None self.name = None self.short_description = None self.thumbnail_url = None self.videos = [] self.video_ids = [] self.type = None self.raw_data = None self.connection = connection if not self.connection: self.connection = APIConnection() if name and type in VALID_PLAYLIST_TYPES: self.name = name self.type = type elif id or reference_id: self.id = id self.reference_id = reference_id self._find_playlist() elif data: self._load(data) else: raise PyBrightcoveError('Invalid parameters for Video.')
def get_status(video_id, connection=None): c = connection if not c: c = APIConnection() return c.post('get_upload_status', video_id=video_id)
def __init__(self, filename=None, name=None, short_description=None, id=None, reference_id=None, data=None, connection=None): self._filename = None self.name = None self.short_description = None self.id = None self.reference_id = None self.accountId = None self.long_description = None self.flv_url = None self.renditions = [] self.assets = [] self.metadata = [] self.video_full_length = None self.creation_date = None self.published_date = None self.last_modified_date = None self.item_state = None self.start_date = None self.end_date = None self.link_url = None self.link_text = None self.tags = [] self.video_still_url = None self.thumbnail_url = None self.length = None self.economics = None self.geo_filtered = None self.geo_filtered_countries = None self.geo_filtered_exclude = None self.cue_points = None self.plays_total = None self.plays_trailing_week = None self.image = None self.raw_data = None self.connection = connection if not self.connection: self.connection = APIConnection() if isinstance(self.connection, APIConnection): if filename and name and short_description: self._filename = filename self.name = name self.short_description = short_description elif id or reference_id: self.id = id self.reference_id = reference_id self._find_video() elif data: self._load(data) else: raise PyBrightcoveError('Invalid parameters for Video.') elif isinstance(self.connection, FTPConnection): if reference_id and name and short_description: self.reference_id = reference_id self.name = name self.short_description = short_description else: raise PyBrightcoveError("Invalid parameters for Video.") else: raise PyBrightcoveError("Invalid connection type for Video.")
class Video(object): """ The Video object is an aggregation of metadata and asset information associated with a video. id A number that uniquely identifies this Video, assigned by Brightcove when the Video is created. reference_id A user-specified id that uniquely identifies this Video. The reference_id can be used as a foreign-key to identify this video in another system. name The title of this Video. The name is a required property when you create a video. account_id A number, assigned by Brightcove, that uniquely identifies the account to which this Video belongs. short_description A short description describing this Video, limited to 256 characters. The short_description is a required property when you create a video. long_description A longer description of this Video, limited to 5000 characters. flv_url The URL of the video file for this Video. Note that this property can be accessed with the Media API only with a special read or write token. renditions An array of Renditions that represent the dynamic delivery renditions available for this Video. video_full_length A single Rendition that represents the the video file for this Video. Note that this property can be accessed with the Media API only with a special read or write token. creation_date The date this Video was created. published_date The date this Video was last made active. last_modified_date The date this Video was last modified. item_state An ItemStateEnum. One of ACTIVE, INACTIVE, or DELETED. You can set this property only to ACTIVE or INACTIVE; you cannot delete a video by setting its itemState to DELETED. start_date The first date this Video is available to be played. end_date The last date this Video is available to be played. link_url An optional URL to a related item. link_text The text displayed for the linkURL. tags A list of Strings representing the tags assigned to this Video. video_still_url The URL to the video still image associated with this Video. Video stills are 480x360 pixels. thumbnail_url The URL to the thumbnail image associated with this Video. Thumbnails are 120x90 pixels. length The length of this video in milliseconds. economics Either FREE or AD_SUPPORTED. AD_SUPPORTED means that ad requests are enabled for this Video. geo_filtered True indicates that the video is geo-restricted. geo_filtered_countries A list of the ISO-3166 two-letter codes of the countries to enforce geo-restriction rules on. Use lowercase for the country codes. geo_filtered_exclude If true, the video can be viewed in all countries except those listed in geo_filtered_countries; if false, the video can be viewed only in the countries listed in geo_filtered_countries. cue_points A List of the CuePoints objects assigned to this Video. plays_total How many times this Video has been played since its creation. plays_trailing_week How many times this Video has been played within the past seven days, exclusive of today. """ def __init__(self, filename=None, name=None, short_description=None, id=None, reference_id=None, data=None, connection=None): self._filename = None self.name = None self.short_description = None self.id = None self.reference_id = None self.accountId = None self.long_description = None self.flv_url = None self.renditions = [] self.assets = [] self.metadata = [] self.video_full_length = None self.creation_date = None self.published_date = None self.last_modified_date = None self.item_state = None self.start_date = None self.end_date = None self.link_url = None self.link_text = None self.tags = [] self.video_still_url = None self.thumbnail_url = None self.length = None self.economics = None self.geo_filtered = None self.geo_filtered_countries = None self.geo_filtered_exclude = None self.cue_points = None self.plays_total = None self.plays_trailing_week = None self.image = None self.raw_data = None self.connection = connection if not self.connection: self.connection = APIConnection() if isinstance(self.connection, APIConnection): if filename and name and short_description: self._filename = filename self.name = name self.short_description = short_description elif id or reference_id: self.id = id self.reference_id = reference_id self._find_video() elif data: self._load(data) else: raise PyBrightcoveError('Invalid parameters for Video.') elif isinstance(self.connection, FTPConnection): if reference_id and name and short_description: self.reference_id = reference_id self.name = name self.short_description = short_description else: raise PyBrightcoveError("Invalid parameters for Video.") else: raise PyBrightcoveError("Invalid connection type for Video.") def _find_video(self): data = None if self.id: data = self.connection.get_item( 'find_video_by_id', video_id=self.id) elif self.reference_id: data = self.connection.get_item( 'find_video_by_reference_id', reference_id=self.reference_id) if data: self._load(data) def _to_dict(self): for i, tag in enumerate(self.tags): if tag in ("", None): self.tags.pop(i) data = { 'name': self.name, 'referenceId': self.reference_id, 'shortDescription': self.short_description, 'longDescription': self.long_description, 'itemState': self.item_state, 'linkURL': self.link_url, 'linkText': self.link_text, 'tags': self.tags, 'economics': self.economics, 'id': self.id, 'end_date': _make_tstamp(self.end_date), 'start_date': _make_tstamp(self.start_date)} [data.pop(key) for key in data.keys() if data[key] == None] return data def to_xml(self): xml = '' for asset in self.assets: xml += '<asset filename="%s" ' % \ os.path.basename(asset['filename']) xml += ' refid="%(refid)s"' % asset xml += ' size="%(size)s"' % asset xml += ' hash-code="%s"' % asset['hash-code'] xml += ' type="%(type)s"' % asset if asset.get('encoding-rate', None): xml += ' encoding-rate="%s"' % asset['encoding-rate'] if asset.get('frame-width', None): xml += ' frame-width="%s"' % asset['frame-width'] if asset.get('frame-height', None): xml += ' frame-height="%s"' % asset['frame-height'] if asset.get('display-name', None): xml += ' display-name="%s"' % asset['display-name'] if asset.get('encode-to', None): xml += ' encode-to="%s"' % asset['encode-to'] if asset.get('encode-multiple', None): xml += ' encode-multiple="%s"' % asset['encode-multiple'] if asset.get('h264-preserve-as-rendition', None): xml += ' h264-preserve-as-rendition="%s"' % \ asset['h264-preserve-as-rendition'] if asset.get('h264-no-processing', None): xml += ' h264-no-processing="%s"' % asset['h264-no-processing'] xml += ' />\n' xml += '<title name="%(name)s" refid="%(referenceId)s" active="TRUE" ' if self.start_date: xml += 'start-date="%(start_date)s" ' if self.end_date: xml += 'end-date="%(end_date)s" ' for asset in self.assets: if asset.get('encoding-rate', None) == None: if asset.get('type', None) == AssetTypeEnum.VIDEO_FULL: xml += 'video-full-refid="%s" ' % asset.get('refid') if asset.get('type', None) == AssetTypeEnum.THUMBNAIL: xml += 'thumbnail-refid="%s" ' % asset.get('refid') if asset.get('type', None) == AssetTypeEnum.VIDEO_STILL: xml += 'video-still-refid="%s" ' % asset.get('refid') if asset.get('type', None) == AssetTypeEnum.FLV_BUMPER: xml += 'flash-prebumper-refid="%s" ' % asset.get('refid') xml += '>\n' if self.short_description: xml += '<short-description><![CDATA[%(shortDescription)s]]>' xml += '</short-description>\n' if self.long_description: xml += '<long-description><![CDATA[%(longDescription)s]]>' xml += '</long-description>\n' for tag in self.tags: xml += '<tag><![CDATA[%s]]></tag>\n' % tag for asset in self.assets: if asset.get('encoding-rate', None): xml += '<rendition-refid>%s</rendition-refid>\n' % \ asset['refid'] for meta in self.metadata: # <custom-string-value name="key_one">String Value One</custom-string-value> xml += '<custom-%s-value name="%s">%s</custom-%s-value>' % \ (meta['type'], meta['key'], meta['value'], meta['type']) xml += '</title>' xml = xml % self._to_dict() return xml def _load(self, data): self.raw_data = data self.creation_date = _convert_tstamp(data['creationDate']) self.economics = data['economics'] self.id = data['id'] self.last_modified_date = _convert_tstamp(data['lastModifiedDate']) self.length = data['length'] self.link_text = data['linkText'] self.link_url = data['linkURL'] self.long_description = data['longDescription'] self.name = data['name'] self.plays_total = data['playsTotal'] self.plays_trailing_week = data['playsTrailingWeek'] self.published_date = _convert_tstamp(data['publishedDate']) self.start_date = _convert_tstamp(data.get('startDate', None)) self.end_date = _convert_tstamp(data.get('endDate', None)) self.reference_id = data['referenceId'] self.short_description = data['shortDescription'] self.tags = [] for tag in data['tags']: self.tags.append(tag) self.thumbnail_url = data['thumbnailURL'] self.video_still_url = data['videoStillURL'] def __setattr__(self, name, value): msg = None if value: if name == 'name' and len(value) > 255: # val = value[:60] ## Is this better? msg = "Video.name must be 60 characters or less." elif name == 'reference_id' and len(value) > 150: # val = value[:150] msg = "Video.reference_id must be 150 characters or less." elif name == 'long_description' and len(value) > 5000: # val = value[:5000] msg = "Video.long_description must be 5000 characters or less." elif name == 'short_description' and len(value) > 250: # val = value[:250] msg = "Video.short_description must be 250 characters or less." elif name == 'item_state' and value not in (ItemStateEnum.ACTIVE, ItemStateEnum.INACTIVE): msg = "Video.item_state must be either ItemStateEnum.ACTIVE or" msg += " ItemStateEnum.INACTIVE" elif name == 'video_full_length' and \ not isinstance(value, Rendition): msg = "Video.video_full_length must be of type Rendition" elif name == 'economics' and \ value not in (EconomicsEnum.FREE, EconomicsEnum.AD_SUPPORTED): msg = "Video.economics must be either EconomicsEnum.FREE or " msg += "EconomicsEnum.AD_SUPPORTED" if msg: raise PyBrightcoveError(msg) return super(Video, self).__setattr__(name, value) def add_custom_metadata(self, key, value, meta_type): self.metadata.append({'key': key, 'value': value, 'type': meta_type}) def add_asset(self, filename, asset_type, display_name, encoding_rate=None, frame_width=None, frame_height=None, encode_to=None, encode_multiple=False, h264_preserve_as_rendition=False, h264_no_processing=False): m = hashlib.md5() fp = file(filename, 'rb') bits = fp.read(262144) ## 256KB while bits: m.update(bits) bits = fp.read(262144) fp.close() hash_code = m.hexdigest() refid = "%s-%s" % (os.path.basename(filename), hash_code) asset = { 'filename': filename, 'type': asset_type, 'size': os.path.getsize(filename), 'refid': refid, 'hash-code': hash_code} if encoding_rate: asset.update({'encoding-rate': encoding_rate}) if frame_width: asset.update({'frame-width': frame_width}) if frame_height: asset.update({'frame-height': frame_height}) if display_name: asset.update({'display-name': display_name}) if encode_to: asset.update({'encode-to': encode_to}) asset.update({'encode-multiple': encode_multiple}) if encode_multiple and h264_preserve_as_rendition: asset.update({ 'h264-preserve-as-rendition': h264_preserve_as_rendition}) else: if h264_no_processing: asset.update({'h264-no-processing': h264_no_processing}) self.assets.append(asset) def save(self, create_multiple_renditions=True, preserve_source_rendition=True, encode_to=EncodeToEnum.FLV): """ Creates or updates the video """ if isinstance(self.connection, FTPConnection) and \ len(self.assets) > 0: self.connection.post(self.to_xml(), self.assets) elif not self.id and self._filename: self.id = self.connection.post('create_video', self._filename, create_multiple_renditions=create_multiple_renditions, preserve_source_rendition=preserve_source_rendition, encode_to=encode_to, video=self._to_dict()) elif self.id: data = self.connection.post('update_video', video=self._to_dict()) if data: self._load(data) def delete(self, cascade=False, delete_shares=False): if self.id: self.connection.post('delete_video', video_id=self.id, cascade=cascade, delete_shares=delete_shares) self.id = None ## Prevent more activity on this video id def get_upload_status(self): if self.id: return self.connection.post('get_upload_status', video_id=self.id) def share(self, accounts): if not isinstance(accounts, (list, tuple)): raise PyBrightcoveError("Video.share expects an iterable argument") raise PyBrightcoveError("Not yet implemented") def set_image(self, image, filename=None, resize=True): if self.id: data = self.connection.post('add_image', filename, video_id=self.id, image=image.to_dict(), resize=resize) if data: self.image = Image(data=data) def find_related(self, connection=None, page_size=100, page_number=0): if self.id: return ItemResultSet('find_related_videos', type(self), connection, page_size, page_number, None, None, video_id=self.id) def deactivate(self): self.item_state = ItemStateEnum.INACTIVE self.save() @staticmethod def delete_video(video_id, cascade=False, delete_shares=False, connection=None): c = connection if not c: c = APIConnection() c.post('delete_video', video_id=video_id, cascade=cascade, delete_shares=delete_shares) @staticmethod def get_status(video_id, connection=None): c = connection if not c: c = APIConnection() return c.post('get_upload_status', video_id=video_id) @classmethod def activate(class_, video_id, connection=None): c = connection if not c: c = APIConnection() data = c.post('update_video', video={ 'id': video_id, 'itemState': ItemStateEnum.ACTIVE}) return class_(data=data) @classmethod def find_modified(class_, since, filter_list=[], connection=None, page_size=25, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): if not isinstance(since, datetime): msg = 'The parameter "since" must be a datetime object.' raise PyBrightcoveError(msg) filters = None fdate = int(since.strftime("%s")) / 60 ## Minutes since UNIX time return ItemResultSet('find_modified_videos', class_, connection, page_size, page_number, sort_by, sort_order, from_date=fdate, filter=filters) @classmethod def find_all(class_,connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): return ItemResultSet('find_all_videos', class_, connection, page_size, page_number, sort_by, sort_order) @classmethod def find_by_tags(class_, and_tags=None, or_tags=None, connection=None, page_size=100, page_number=0, sort_by=SortByType.MODIFIED_DATE, sort_order=SortByOrderType.ASC): err = None if not and_tags and not or_tags: err = "You must supply at least one of either and_tags or or_tags." if and_tags and not isinstance(and_tags, (tuple, list)): err = "The and_tags argument for Video.find_by_tags must an " err += "iterable" if or_tags and not isinstance(or_tags, (tuple, list)): err = "The or_tags argument for Video.find_by_tags must an " err += "iterable" if err: raise PyBrightcoveError(err) atags = None otags = None if and_tags: atags = ','.join([str(t) for t in and_tags]) if or_tags: otags = ','.join([str(t) for t in or_tags]) return ItemResultSet('find_videos_by_tags', class_, connection, page_size, page_number, sort_by, sort_order, and_tags=atags, or_tags=otags) @classmethod def find_by_text(class_, text, connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): return ItemResultSet('find_videos_by_text', class_, connection, page_size, page_number, sort_by, sort_order, text=text) @classmethod def find_by_campaign(class_, campaign_id, connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): return ItemResultSet('find_videos_by_campaign_id', class_, connection, page_size, page_number, sort_by, sort_order, campaign_id=campaign_id) @classmethod def find_by_user(class_, user_id, connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): return ItemResultSet('find_videos_by_user_id', class_, connection, page_size, page_number, sort_by, sort_order, user_id=user_id) @classmethod def find_by_reference_ids(class_, reference_ids, connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): if not isinstance(reference_ids, (list, tuple)): err = "Video.find_by_reference_ids expects an iterable argument" raise PyBrightcoveError(err) ids = ','.join(reference_ids) return ItemResultSet('find_videos_by_reference_ids', class_, connection, page_size, page_number, sort_by, sort_order, reference_ids=ids) @classmethod def find_by_ids(class_, ids, connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): if not isinstance(ids, (list, tuple)): err = "Video.find_by_ids expects an iterable argument" raise PyBrightcoveError(err) ids = ','.join([str(i) for i in ids]) return ItemResultSet('find_videos_by_ids', class_, connection, page_size, page_number, sort_by, sort_order, video_ids=ids) @staticmethod def delete_by_id(id, connection=None, cascade=False, delete_shares=False): if connection is None: connection=Connection() connection.post('delete_video', video_id=id, cascade=cascade, delete_shares=delete_shares)
class Playlist(object): """ The Playlist object is a collection of Videos. id A number that uniquely identifies this Playlist. This id is automatically assigned when the Playlist is created. reference_id A user-specified id that uniquely identifies this Playlist. account_id A number that uniquely identifies the account to which this Playlist belongs, assigned by Brightcove. name The title of this Playlist. The name is a required property when you create a playlist. short_description A short description describing this Playlist, limited to 250 characters. video_ids A list of the ids of the Videos that are encapsulated in this Playlist. videos A list of the Video objects that are encapsulated in this Playlist. type Options are OLDEST_TO_NEWEST, NEWEST_TO_OLDEST, ALPHABETICAL, PLAYSTRAILING, and PLAYSTRAILINGWEEK (each of which is a smart playlist, ordered as indicated) or EXPLICIT (a manual playlist). The type is a required property when you create a playlist. thumbnail_url The URL of the thumbnail associated with this Playlist. """ def __init__(self, name=None, type=None, id=None, reference_id=None, data=None, connection=None): self.id = None self.reference_id = None self.account_id = None self.name = None self.short_description = None self.thumbnail_url = None self.videos = [] self.video_ids = [] self.type = None self.raw_data = None self.connection = connection if not self.connection: self.connection = APIConnection() if name and type in VALID_PLAYLIST_TYPES: self.name = name self.type = type elif id or reference_id: self.id = id self.reference_id = reference_id self._find_playlist() elif data: self._load(data) else: raise PyBrightcoveError('Invalid parameters for Video.') def __setattr__(self, name, value): msg = None if value: if name == 'name' and len(value) > 255: # val = value[:60] ## Is this better? msg = "Playlist.name must be 60 characters or less." elif name == 'reference_id' and len(value) > 150: # val = value[:150] msg = "Playlist.reference_id must be 150 characters or less." elif name == 'short_description' and len(value) > 250: # val = value[:250] msg = "Playlist.short_description must be 250 chars or less." elif name == 'type' and value not in VALID_PLAYLIST_TYPES: msg = "Playlist.type must be a valid PlaylistTypeEnum" if msg: raise PyBrightcoveError(msg) return super(Playlist, self).__setattr__(name, value) def _find_playlist(self): data = None if self.id: data = self.connection.get_item( 'find_playlist_by_id', playlist_id=self.id) elif self.reference_id: data = self.connection.get_item( 'find_playlist_by_reference_id', reference_id=self.reference_id) if data: self._load(data) def _to_dict(self): data = { 'name': self.name, 'referenceId': self.reference_id, 'shortDescription': self.short_description, 'playlistType': self.type, 'id': self.id} if self.videos: for video in self.videos: if video.id not in self.video_ids: self.video_ids.append(video.id) if self.video_ids: data['videoIds'] = self.video_ids [data.pop(key) for key in data.keys() if data[key] == None] return data def _load(self, data): self.raw_data = data self.id = data['id'] self.reference_id = data['referenceId'] self.name = data['name'] self.short_description = data['shortDescription'] self.thumbnail_url = data['thumbnailURL'] self.videos = [] self.video_ids = data['videoIds'] self.type = data['playlistType'] for video in data.get('videos', []): self.videos.append(Video(data=video)) def save(self): d = self._to_dict() if len(d.get('videoIds', [])) > 0: if not self.id: self.id = self.connection.post('create_playlist', playlist=d) else: data = self.connection.post('update_playlist', playlist=d) if data: self._load(data) def delete(self, cascade=False): if self.id: self.connection.post('delete_playlist', playlist_id=self.id, cascade=cascade) self.id = None @classmethod def find_all(class_, connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): return ItemResultSet('find_all_playlists', class_, connection, page_size, page_number, sort_by, sort_order) @classmethod def find_by_ids(class_, ids, connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): ids = ','.join([str(i) for i in ids]) return ItemResultSet('find_playlists_by_ids', class_, connection, page_size, page_number, sort_by, sort_order, playlist_ids=ids) @classmethod def find_by_reference_ids(class_, reference_ids, connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): reference_ids = ','.join([str(i) for i in reference_ids]) return ItemResultSet('find_playlists_by_reference_ids', class_, connection, page_size, page_number, sort_by, sort_order, reference_ids=reference_ids) @classmethod def find_for_player_id(class_, player_id, connection=None, page_size=100, page_number=0, sort_by=SortByType.CREATION_DATE, sort_order=SortByOrderType.ASC): return ItemResultSet('find_playlists_for_player_id', class_, connection, page_size, page_number, sort_by, sort_order, player_id=player_id)