def find_aspect_ratios(video: dict) -> None: """ This will print out the aspectratio of a video. """ video_id = video.get('id') delivery_type = video.get('delivery_type') source_w, source_h, response = None, None, None if delivery_type == 'static_origin': response = get_cms().GetRenditionList(video_id=video_id) elif delivery_type == 'dynamic_origin': response = get_cms().GetDynamicRenditions(video_id=video_id) else: eprint( f'No video dimensions found for video ID {video_id} (delivery type: {delivery_type}).' ) return if response.status_code in get_cms().success_responses: renditions = response.json() for rendition in renditions: if rendition.get('media_type') == 'video' or rendition.get( 'audio_only') == False: source_w = rendition.get('frame_width') source_h = rendition.get('frame_height') break if source_h and source_w: x, y = aspect_ratio(source_w, source_h) print(video_id, x, y, sep=', ') else: eprint(f'No video renditions found for video ID {video_id}.') else: eprint(f'Could not get renditions for video ID {video_id}.')
def disable_tt(video: dict): """ This will find text tracks with default tracks and disable those defaults. """ # try to get all text tracks if tts := video.get('text_tracks'): # flag to signal we found and changed default tracks got_hit = False # go through all tracks for track in tts: #check if it's a default track if track.get('default'): # change the setting track['default'] = False # set the flag so we know we found one got_hit = True # check if we found and changed at least one if got_hit: # get the video ID video_id = video.get('id') # create the JSON body json_body = { 'text_tracks': tts } # make the PATCH call r = get_cms().UpdateVideo(video_id=video_id, json_body=json_body) # check if all went well if r.status_code in [200,202]: print(f'Disabled default track(s) for video ID {video_id} with status {r.status_code}.') # otherwise report the error else: print(f'Error code {r.status_code} disabling default track(s) for video ID {video_id}:') print(r.text)
def download_video(video: dict): """ This will download the highest resolution MP4 from a video. """ video_id = str(video.get('id')) source_url, source_w, source_h = None, 0, 0 # get sources for the video and try to find the biggest MP4 video sourceList = get_cms().GetVideoSources(video_id=video_id).json() for source in sourceList: sourceType = source.get('container') if sourceType and sourceType=='MP4': w, h = source.get('width'), source.get('height') if h and w and w>source_w: source_w, source_h, source_url = w, h, source.get('src') # if a source was found download it, using the video ID as filename if source_url: print(f'{video_id}: highest resolution MP4 source is {source_w}x{source_h}. Downloading...') r = requests.get(source_url, stream=True) with open(f'{video_id}.mp4', 'wb') as out: total_length = int(r.headers.get('content-length')) for ch in progress.bar(r.iter_content(chunk_size = 2097152), expected_size=(total_length/2097152) + 1): if ch: out.write(ch) out.flush()
def update_tt_label(video: dict): """ This will update a text track's label to be the same as the language. """ # try to get all text tracks if tts := video.get('text_tracks'): # go through all tracks for track in tts: # change the setting track['label'] = track['srclang'] # get the video ID video_id = video.get('id') # create the JSON body json_body = {'text_tracks': tts} # make the PATCH call r = get_cms().UpdateVideo(video_id=video_id, json_body=json_body) # check if all went well if r.status_code in [200, 202]: print( f'Updated track labels for video ID {video_id} with status {r.status_code}.' ) # otherwise report the error else: print( f'Error code {r.status_code} updating track labels for video ID {video_id}:' ) print(r.text)
def report_renditions(video: dict) -> None: """ This will print out the aspectratio of a video. """ video_id = str(video.get('id')) delivery_type = video.get('delivery_type') source_w, source_h, response = None, None, None if delivery_type == 'static_origin': response = get_cms().GetRenditionList(video_id=video_id) elif delivery_type == 'dynamic_origin': response = get_cms().GetDynamicRenditions(video_id=video_id) else: return if response.status_code not in get_cms().success_responses: return results = {} rendition: dict for rendition in response.json(): if rendition.get('media_type' ) == 'video' or rendition.get('audio_only') is False: source_w = rendition.get('frame_width') source_h = rendition.get('frame_height') if source_h and source_w: results[rendition.get('size')] = [ source_w, source_h, rendition.get('size'), 'MP4' if rendition.get('video_container') == 'MP4' else 'HLS/DASH' ] if delivery_type == 'dynamic_origin': response = get_cms().GetVideoSources(video_id=video_id) if response.status_code in get_cms().success_responses: for rendition in response.json(): if rendition.get('container') == 'MP4': source_w = rendition.get('width') source_h = rendition.get('height') if source_h and source_w: results[rendition.get('size')] = [ source_w, source_h, rendition.get('size'), 'MP4' ] for _, values in results.items(): print(video_id, *values, sep=', ')
def retranscode(video: dict): """ This will retranscode a video using the digital master if it exists. If no master exists it will use the best quality MP4 or FLV. """ # get some basic info about the video video_id = str(video.get('id')) delivery_type = video.get('delivery_type') is_shared = video.get('sharing') # if it's not legacy or dynamic delivery we bail if delivery_type not in ('static_origin', 'dynamic_origin'): print( f'{video_id}: can not be retranscoded (delivery type: {delivery_type})' ) return # if it's a shared video we also bail if is_shared and is_shared.get('by_external_acct'): print(f'{video_id}: can not be retranscoded (shared into account)') return # retranscode specific settings ingest_profile = 'multi-platform-extended-static-with-mp4' priority = 'low' capture_images = False # if it has a master then use that for retranscode if video.get('has_digital_master'): print( f'{video_id}: retranscoding using digital master -> {get_di().RetranscodeVideo(video_id=video_id, profile_id=ingest_profile,capture_images=capture_images, priority_queue=priority).status_code}' ) return # otherwise try to find a high resolution MP4 or FLV rendition and use that source_url: str = '' source_w, source_h = 0, 0 # get sources for the video and try to find the biggest MP4 or FLV video source_list = get_cms().GetVideoSources(video_id=video_id).json() for source in source_list: if source.get('container') == 'MP4' or source.get('codec') == 'ON2': w, h = source.get('width', 0), source.get('height', 0) # checking w/h to avoid error by audio only renditions if w > source_w and h > source_h: url: str = source.get('src', '') if url.startswith('http'): source_w, source_h = w, h source_url = url # if a source was found use it as source for replacing the source if source_url: print( f'{video_id}: retranscoding using highest resolution MP4/FLV ({source_w}x{source_h}) -> {get_di().SubmitIngest(video_id=video_id, source_url=source_url, profile_id=ingest_profile,capture_images=capture_images, priority_queue=priority).status_code}' ) else: print( f'{video_id}: can not be retranscoded (no master or MP4/FLV video rendition)' )
def get_created_by_report(video: dict): """ Adds creator of the video to the dictionary. """ creator = get_cms().GetCreatedBy(video) with data_lock: created_by_dict[creator] += 1 show_progress()
def enable_geo(video: dict): """ If no geo restrictions are enabled this will add some. """ if not video.get('geo'): # get the video ID video_id = str(video.get('id')) # create the JSON body json_body = { 'geo' : { 'restricted' : True, 'exclude_countries' : False, 'countries' : ['ca'] } } # make the PATCH call r = get_cms().UpdateVideo(video_id=video_id, json_body=json_body) # check if all went well if r.status_code not in [200,202]: eprint(f'Error code {r.status_code} disabling Geo for video ID {video_id}:') eprint(r.text) with counter_lock: show_progress()
def get_master_storage(video: dict) -> int: """ Function to get the size of the digital master for a video. Returns size of digital master if available, 0 if video has no master or -1 in case of an error. """ if is_shared_by(video): return 0 if video.get('has_digital_master'): try: response = get_cms().GetDigitalMasterInfo(video_id=video.get('id')) except RequestException: return -1 else: if response.status_code == 200: return int(response.json().get('size', 0)) return -1 return 0
def get_master_storage(video: dict) -> int: """ returns size of digital master if avaiable returns 0 if video has no master returns -1 in case of an error """ shared = video.get('sharing') if shared and shared.get('by_external_acct'): return 0 if video.get('has_digital_master'): try: response = get_cms().GetDigitalMasterInfo(video_id=video.get('id')) except RequestException: return -1 else: if response.status_code == 200: return int(response.json().get('size')) return -1 return 0
def enable_drm(video: dict): """ If a video is not enabled for DRM this will enable DRM. """ # does video have DRM? if video.get('drm_disabled') == True: # get the video ID video_id = video.get('id') # create the JSON body json_body = {'drm_disabled': False} # make the PATCH call r = get_cms().UpdateVideo(video_id=video_id, json_body=json_body) # check if all went well if r.status_code in [200, 202]: print( f'Enabled DRM for video ID {video_id} with status {r.status_code}.' ) # otherwise report the error else: print( f'Error code {r.status_code} enabling DRM for video ID {video_id}:' ) print(r.text)
def enable_offline(video: dict): """ If video is not enabled for offline playback this will enable it. """ # does video have DRM? if video.get('offline_enabled') == False: # get the video ID video_id = video.get('id') # create the JSON body json_body = {'offline_enabled': True} # make the PATCH call r = get_cms().UpdateVideo(video_id=video_id, json_body=json_body) # check if all went well if r.status_code in [200, 202]: print( f'Enabled Offline Playback for video ID {video_id} with status {r.status_code}.' ) # otherwise report the error else: print( f'Error code {r.status_code} enabling Offline Playback for video ID {video_id}:' ) print(r.text)
def disable_geo(video: dict): """ If geo restrictions are enabled this will disable them. """ global videos_processed # does video have Geo restrictions? if video.get('geo'): # get the video ID video_id = str(video.get('id')) # create the JSON body json_body = { 'geo': None } # make the PATCH call r = get_cms().UpdateVideo(video_id=video_id, json_body=json_body) # check if all went well if r.status_code not in [200,202]: eprint(f'Error code {r.status_code} disabling Geo for video ID {video_id}:') eprint(r.text) with counter_lock: videos_processed += 1 if videos_processed%100==0: show_progress(videos_processed)
def get_rendition_sizes(video: dict) -> dict: """ Function to get the sizes of all rendtions for a video. Returns a dict with the relevant sizes if available, 0 for sizes if video has no renditions or -1 in case of an error. """ sizes = { 'hls_renditions_size': 0, 'mp4_renditions_size': 0, 'audio_renditions_size': 0, 'flv_renditions_size': 0, } if is_shared_by(video): return sizes rendition_types = { 'MP4': 'mp4_renditions_size', 'M2TS': 'hls_renditions_size', 'FLV': 'flv_renditions_size', 'audio': 'audio_renditions_size', 'video': 'hls_renditions_size', } response = None delivery_type = video.get('delivery_type') video_id = video.get('id') try: if delivery_type == 'static_origin': response = get_cms().GetRenditionList(video_id=video_id) elif delivery_type == 'dynamic_origin': response = get_cms().GetDynamicRenditions(video_id=video_id) else: return sizes except RequestException: return {key: -1 for key in sizes} if response and response.ok: renditions = response.json() for rendition in renditions: size = rendition.get('size', 0) video_container = rendition.get('video_container') media_type = rendition.get('media_type') try: # legacy rendition types if video_container: sizes[rendition_types[video_container]] += size # dyd rendition types elif media_type: sizes[rendition_types[media_type]] += size # something I haven't seen before? except KeyError: eprint( f'WARNING: unexpected container/media type for video ID {video_id}: "{video_container}"/"{media_type}"' ) eprint('Please report the above message to MacKenzie Glanzer.') # if it's Dynamic Delivery we need to get MP4 sizes from the sources endpoint if delivery_type == 'dynamic_origin' and sizes[ 'mp4_renditions_size'] == 0: try: response = get_cms().GetVideoSources(video_id=video_id) except RequestException: sizes['mp4_renditions_size'] = -1 else: if response.status_code in get_cms().success_responses: sizes['mp4_renditions_size'] += sum( set( rendition.get('size', 0) for rendition in response.json() if rendition.get('container') == 'MP4')) return sizes