def test_get_urls_for_profiles_no_profiles(self): """ Tests when the video is found, but not hte profiles. """ profiles = ["not", "found"] edx_video_id = constants.VIDEO_DICT_FISH["edx_video_id"] urls = api.get_urls_for_profiles(edx_video_id, profiles) self.assertEqual(len(urls), 2) self.assertEqual(urls["not"], None) self.assertEqual(urls["found"], None)
def test_get_urls_for_profiles(self): """ Tests when the profiles to the video are found """ profiles = ["mobile", "desktop"] edx_video_id = constants.VIDEO_DICT_FISH["edx_video_id"] urls = api.get_urls_for_profiles(edx_video_id, profiles) self.assertEqual(len(urls), 2) self.assertEqual(urls["mobile"], u"http://www.meowmix.com") self.assertEqual(urls["desktop"], u"http://www.meowmagic.com")
def test_get_urls_for_profiles_no_profiles(self): """ Tests when the video is found, but not hte profiles. """ profiles = ["not", "found"] edx_video_id = constants.VIDEO_DICT_FISH['edx_video_id'] urls = api.get_urls_for_profiles(edx_video_id, profiles) self.assertEqual(len(urls), 2) self.assertEqual(urls["not"], None) self.assertEqual(urls["found"], None)
def test_get_urls_for_profiles(self): """ Tests when the profiles to the video are found """ profiles = ["mobile", "desktop"] edx_video_id = constants.VIDEO_DICT_FISH['edx_video_id'] urls = api.get_urls_for_profiles(edx_video_id, profiles) self.assertEqual(len(urls), 2) self.assertEqual(urls["mobile"], u'http://www.meowmix.com') self.assertEqual(urls["desktop"], u'http://www.meowmagic.com')
def get_bumper_sources(video): """ Get bumper sources from edxval. Returns list of sources. """ try: val_profiles = ["desktop_webm", "desktop_mp4"] val_video_urls = edxval_api.get_urls_for_profiles(video.bumper['edx_video_id'], val_profiles) bumper_sources = filter(None, [val_video_urls[p] for p in val_profiles]) except edxval_api.ValInternalError: # if no bumper sources, nothing will be showed log.warning( "Could not retrieve information from VAL for Bumper edx Video ID: %s.", video.bumper['edx_video_id'] ) return [] return bumper_sources
def get_context(self): """ Extend context by data for transcript basic tab. """ _context = super(VideoDescriptor, self).get_context() metadata_fields = copy.deepcopy(self.editable_metadata_fields) display_name = metadata_fields['display_name'] video_url = metadata_fields['html5_sources'] video_id = metadata_fields['edx_video_id'] youtube_id_1_0 = metadata_fields['youtube_id_1_0'] def get_youtube_link(video_id): """ Returns the fully-qualified YouTube URL for the given video identifier """ # First try a lookup in VAL. If we have a YouTube entry there, it overrides the # one passed in. if self.edx_video_id and edxval_api: val_youtube_id = edxval_api.get_url_for_profile(self.edx_video_id, "youtube") if val_youtube_id: video_id = val_youtube_id return self.create_youtube_url(video_id) _ = self.runtime.service(self, "i18n").ugettext video_url.update({ 'help': _('The URL for your video. This can be a YouTube URL or a link to an .mp4, .ogg, or .webm video file hosted elsewhere on the Internet.'), # pylint: disable=line-too-long 'display_name': _('Default Video URL'), 'field_name': 'video_url', 'type': 'VideoList', 'default_value': [get_youtube_link(youtube_id_1_0['default_value'])] }) source_url = self.create_youtube_url(youtube_id_1_0['value']) # First try a lookup in VAL. If any video encoding is found given the video id then # override the source_url with it. if self.edx_video_id and edxval_api: val_profiles = ['youtube', 'desktop_webm', 'desktop_mp4'] if HLSPlaybackEnabledFlag.feature_enabled(self.runtime.course_id.for_branch(None)): val_profiles.append('hls') # Get video encodings for val profiles. val_video_encodings = edxval_api.get_urls_for_profiles(self.edx_video_id, val_profiles) # VAL's youtube source has greater priority over external youtube source. if val_video_encodings.get('youtube'): source_url = self.create_youtube_url(val_video_encodings['youtube']) # If no youtube source is provided externally or in VAl, update source_url in order: hls > mp4 and webm if not source_url: if val_video_encodings.get('hls'): source_url = val_video_encodings['hls'] elif val_video_encodings.get('desktop_mp4'): source_url = val_video_encodings['desktop_mp4'] elif val_video_encodings.get('desktop_webm'): source_url = val_video_encodings['desktop_webm'] # Only add if html5 sources do not already contain source_url. if source_url and source_url not in video_url['value']: video_url['value'].insert(0, source_url) metadata = { 'display_name': display_name, 'video_url': video_url, 'edx_video_id': video_id } _context.update({'transcripts_basic_tab_metadata': metadata}) return _context
def get_html(self): track_status = (self.download_track and self.track) transcript_download_format = self.transcript_download_format if not track_status else None sources = filter(None, self.html5_sources) download_video_link = None branding_info = None youtube_streams = "" # Determine if there is an alternative source for this video # based on user locale. This exists to support cases where # we leverage a geography specific CDN, like China. cdn_url = getattr(settings, 'VIDEO_CDN_URL', {}).get(self.system.user_location) # If we have an edx_video_id, we prefer its values over what we store # internally for download links (source, html5_sources) and the youtube # stream. if self.edx_video_id and edxval_api: try: val_profiles = ["youtube", "desktop_webm", "desktop_mp4"] if HLSPlaybackEnabledFlag.feature_enabled(self.course_id): val_profiles.append('hls') # strip edx_video_id to prevent ValVideoNotFoundError error if unwanted spaces are there. TNL-5769 val_video_urls = edxval_api.get_urls_for_profiles(self.edx_video_id.strip(), val_profiles) # VAL will always give us the keys for the profiles we asked for, but # if it doesn't have an encoded video entry for that Video + Profile, the # value will map to `None` # add the non-youtube urls to the list of alternative sources # use the last non-None non-youtube non-hls url as the link to download the video for url in [val_video_urls[p] for p in val_profiles if p != "youtube"]: if url: if url not in sources: sources.append(url) # don't include hls urls for download if self.download_video and not url.endswith('.m3u8'): # function returns None when the url cannot be re-written rewritten_link = rewrite_video_url(cdn_url, url) if rewritten_link: download_video_link = rewritten_link else: download_video_link = url # set the youtube url if val_video_urls["youtube"]: youtube_streams = "1.00:{}".format(val_video_urls["youtube"]) except edxval_api.ValInternalError: # VAL raises this exception if it can't find data for the edx video ID. This can happen if the # course data is ported to a machine that does not have the VAL data. So for now, pass on this # exception and fallback to whatever we find in the VideoDescriptor. log.warning("Could not retrieve information from VAL for edx Video ID: %s.", self.edx_video_id) # If the user comes from China use China CDN for html5 videos. # 'CN' is China ISO 3166-1 country code. # Video caching is disabled for Studio. User_location is always None in Studio. # CountryMiddleware disabled for Studio. if getattr(self, 'video_speed_optimizations', True) and cdn_url: branding_info = BrandingInfoConfig.get_config().get(self.system.user_location) for index, source_url in enumerate(sources): new_url = rewrite_video_url(cdn_url, source_url) if new_url: sources[index] = new_url # If there was no edx_video_id, or if there was no download specified # for it, we fall back on whatever we find in the VideoDescriptor if not download_video_link and self.download_video: if self.source: download_video_link = self.source elif self.html5_sources: download_video_link = self.html5_sources[0] # don't give the option to download HLS video urls if download_video_link and download_video_link.endswith('.m3u8'): download_video_link = None track_url, transcript_language, sorted_languages = self.get_transcripts_for_student(self.get_transcripts_info()) # CDN_VIDEO_URLS is only to be used here and will be deleted # TODO([email protected]): Delete this after the CDN experiment has completed. html_id = self.location.html_id() if self.system.user_location == 'CN' and \ settings.FEATURES.get('ENABLE_VIDEO_BEACON', False) and \ html_id in getattr(settings, 'CDN_VIDEO_URLS', {}).keys(): cdn_urls = getattr(settings, 'CDN_VIDEO_URLS', {})[html_id] cdn_exp_group, new_source = random.choice(zip(range(len(cdn_urls)), cdn_urls)) if cdn_exp_group > 0: sources[0] = new_source cdn_eval = True else: cdn_eval = False cdn_exp_group = None self.youtube_streams = youtube_streams or create_youtube_string(self) # pylint: disable=W0201 settings_service = self.runtime.service(self, 'settings') yt_api_key = None if settings_service: xblock_settings = settings_service.get_settings_bucket(self) if xblock_settings and 'YOUTUBE_API_KEY' in xblock_settings: yt_api_key = xblock_settings['YOUTUBE_API_KEY'] poster = None if edxval_api and self.edx_video_id: poster = edxval_api.get_course_video_image_url( course_id=self.runtime.course_id.for_branch(None), edx_video_id=self.edx_video_id.strip() ) metadata = { 'saveStateUrl': self.system.ajax_url + '/save_user_state', 'autoplay': settings.FEATURES.get('AUTOPLAY_VIDEOS', False), 'streams': self.youtube_streams, 'sub': self.sub, 'sources': sources, 'poster': poster, # This won't work when we move to data that # isn't on the filesystem 'captionDataDir': getattr(self, 'data_dir', None), 'showCaptions': json.dumps(self.show_captions), 'generalSpeed': self.global_speed, 'speed': self.speed, 'savedVideoPosition': self.saved_video_position.total_seconds(), 'start': self.start_time.total_seconds(), 'end': self.end_time.total_seconds(), 'transcriptLanguage': transcript_language, 'transcriptLanguages': sorted_languages, 'ytTestTimeout': settings.YOUTUBE['TEST_TIMEOUT'], 'ytApiUrl': settings.YOUTUBE['API'], 'ytMetadataUrl': settings.YOUTUBE['METADATA_URL'], 'ytKey': yt_api_key, 'transcriptTranslationUrl': self.runtime.handler_url( self, 'transcript', 'translation/__lang__' ).rstrip('/?'), 'transcriptAvailableTranslationsUrl': self.runtime.handler_url( self, 'transcript', 'available_translations' ).rstrip('/?'), ## For now, the option "data-autohide-html5" is hard coded. This option ## either enables or disables autohiding of controls and captions on mouse ## inactivity. If set to true, controls and captions will autohide for ## HTML5 sources (non-YouTube) after a period of mouse inactivity over the ## whole video. When the mouse moves (or a key is pressed while any part of ## the video player is focused), the captions and controls will be shown ## once again. ## ## There is no option in the "Advanced Editor" to set this option. However, ## this option will have an effect if changed to "True". The code on ## front-end exists. 'autohideHtml5': False, # This is the server's guess at whether youtube is available for # this user, based on what was recorded the last time we saw the # user, and defaulting to True. 'recordedYoutubeIsAvailable': self.youtube_is_available, } bumperize(self) context = { 'bumper_metadata': json.dumps(self.bumper['metadata']), # pylint: disable=E1101 'metadata': json.dumps(OrderedDict(metadata)), 'poster': json.dumps(get_poster(self)), 'branding_info': branding_info, 'cdn_eval': cdn_eval, 'cdn_exp_group': cdn_exp_group, 'id': self.location.html_id(), 'display_name': self.display_name_with_default, 'handout': self.handout, 'download_video_link': download_video_link, 'track': track_url, 'transcript_download_format': transcript_download_format, 'transcript_download_formats_list': self.descriptor.fields['transcript_download_format'].values, 'license': getattr(self, "license", None), } return self.system.render_template('video.html', context)
def test_get_urls_for_profiles_no_video(self): """ Tests when there is no video found. """ urls = api.get_urls_for_profiles("not found", ["mobile"]) self.assertEqual(urls["mobile"], None)
def get_html(self): transcript_download_format = self.transcript_download_format if not (self.download_track and self.track) else None sources = filter(None, self.html5_sources) download_video_link = None youtube_streams = "" # If we have an edx_video_id, we prefer its values over what we store # internally for download links (source, html5_sources) and the youtube # stream. if self.edx_video_id and edxval_api: try: val_profiles = ["youtube", "desktop_webm", "desktop_mp4"] val_video_urls = edxval_api.get_urls_for_profiles(self.edx_video_id, val_profiles) # VAL will always give us the keys for the profiles we asked for, but # if it doesn't have an encoded video entry for that Video + Profile, the # value will map to `None` # add the non-youtube urls to the list of alternative sources # use the last non-None non-youtube url as the link to download the video for url in [val_video_urls[p] for p in val_profiles if p != "youtube"]: if url: if url not in sources: sources.append(url) if self.download_video: download_video_link = url # set the youtube url if val_video_urls["youtube"]: youtube_streams = "1.00:{}".format(val_video_urls["youtube"]) except edxval_api.ValInternalError: # VAL raises this exception if it can't find data for the edx video ID. This can happen if the # course data is ported to a machine that does not have the VAL data. So for now, pass on this # exception and fallback to whatever we find in the VideoDescriptor. log.warning("Could not retrieve information from VAL for edx Video ID: %s.", self.edx_video_id) # If the user comes from China use China CDN for html5 videos. # 'CN' is China ISO 3166-1 country code. # Video caching is disabled for Studio. User_location is always None in Studio. # CountryMiddleware disabled for Studio. cdn_url = getattr(settings, 'VIDEO_CDN_URL', {}).get(self.system.user_location) if getattr(self, 'video_speed_optimizations', True) and cdn_url: for index, source_url in enumerate(sources): new_url = get_video_from_cdn(cdn_url, source_url) if new_url: sources[index] = new_url # If there was no edx_video_id, or if there was no download specified # for it, we fall back on whatever we find in the VideoDescriptor if not download_video_link and self.download_video: if self.source: download_video_link = self.source elif self.html5_sources: download_video_link = self.html5_sources[0] track_url, transcript_language, sorted_languages = self.get_transcripts_for_student() return self.system.render_template('video.html', { 'ajax_url': self.system.ajax_url + '/save_user_state', 'autoplay': settings.FEATURES.get('AUTOPLAY_VIDEOS', False), # This won't work when we move to data that # isn't on the filesystem 'data_dir': getattr(self, 'data_dir', None), 'display_name': self.display_name_with_default, 'end': self.end_time.total_seconds(), 'handout': self.handout, 'id': self.location.html_id(), 'show_captions': json.dumps(self.show_captions), 'download_video_link': download_video_link, 'sources': json.dumps(sources), 'speed': json.dumps(self.speed), 'general_speed': self.global_speed, 'saved_video_position': self.saved_video_position.total_seconds(), 'start': self.start_time.total_seconds(), 'sub': self.sub, 'track': track_url, 'youtube_streams': youtube_streams or create_youtube_string(self), # TODO: Later on the value 1500 should be taken from some global # configuration setting field. 'yt_test_timeout': 1500, 'yt_api_url': settings.YOUTUBE['API'], 'yt_test_url': settings.YOUTUBE['TEST_URL'], 'transcript_download_format': transcript_download_format, 'transcript_download_formats_list': self.descriptor.fields['transcript_download_format'].values, 'transcript_language': transcript_language, 'transcript_languages': json.dumps(sorted_languages), 'transcript_translation_url': self.runtime.handler_url(self, 'transcript', 'translation').rstrip('/?'), 'transcript_available_translations_url': self.runtime.handler_url(self, 'transcript', 'available_translations').rstrip('/?'), })
def get_html(self): transcript_download_format = self.transcript_download_format if not ( self.download_track and self.track) else None sources = filter(None, self.html5_sources) download_video_link = None branding_info = None youtube_streams = "" # If we have an edx_video_id, we prefer its values over what we store # internally for download links (source, html5_sources) and the youtube # stream. if self.edx_video_id and edxval_api: try: val_profiles = ["youtube", "desktop_webm", "desktop_mp4"] val_video_urls = edxval_api.get_urls_for_profiles( self.edx_video_id, val_profiles) # VAL will always give us the keys for the profiles we asked for, but # if it doesn't have an encoded video entry for that Video + Profile, the # value will map to `None` # add the non-youtube urls to the list of alternative sources # use the last non-None non-youtube url as the link to download the video for url in [ val_video_urls[p] for p in val_profiles if p != "youtube" ]: if url: if url not in sources: sources.append(url) if self.download_video: download_video_link = url # set the youtube url if val_video_urls["youtube"]: youtube_streams = "1.00:{}".format( val_video_urls["youtube"]) except edxval_api.ValInternalError: # VAL raises this exception if it can't find data for the edx video ID. This can happen if the # course data is ported to a machine that does not have the VAL data. So for now, pass on this # exception and fallback to whatever we find in the VideoDescriptor. log.warning( "Could not retrieve information from VAL for edx Video ID: %s.", self.edx_video_id) # If the user comes from China use China CDN for html5 videos. # 'CN' is China ISO 3166-1 country code. # Video caching is disabled for Studio. User_location is always None in Studio. # CountryMiddleware disabled for Studio. cdn_url = getattr(settings, 'VIDEO_CDN_URL', {}).get(self.system.user_location) if getattr(self, 'video_speed_optimizations', True) and cdn_url: branding_info = BrandingInfoConfig.get_config().get( self.system.user_location) for index, source_url in enumerate(sources): new_url = get_video_from_cdn(cdn_url, source_url) if new_url: sources[index] = new_url # If there was no edx_video_id, or if there was no download specified # for it, we fall back on whatever we find in the VideoDescriptor if not download_video_link and self.download_video: if self.source: download_video_link = self.source elif self.html5_sources: download_video_link = self.html5_sources[0] track_url, transcript_language, sorted_languages = self.get_transcripts_for_student( ) # CDN_VIDEO_URLS is only to be used here and will be deleted # TODO([email protected]): Delete this after the CDN experiment has completed. html_id = self.location.html_id() if self.system.user_location == 'CN' and \ settings.FEATURES.get('ENABLE_VIDEO_BEACON', False) and \ html_id in getattr(settings, 'CDN_VIDEO_URLS', {}).keys(): cdn_urls = getattr(settings, 'CDN_VIDEO_URLS', {})[html_id] cdn_exp_group, new_source = random.choice( zip(range(len(cdn_urls)), cdn_urls)) if cdn_exp_group > 0: sources[0] = new_source cdn_eval = True else: cdn_eval = False cdn_exp_group = None return self.system.render_template( 'video.html', { 'ajax_url': self.system.ajax_url + '/save_user_state', 'autoplay': settings.FEATURES.get('AUTOPLAY_VIDEOS', False), 'branding_info': branding_info, 'cdn_eval': cdn_eval, 'cdn_exp_group': cdn_exp_group, # This won't work when we move to data that # isn't on the filesystem 'data_dir': getattr(self, 'data_dir', None), 'display_name': self.display_name_with_default, 'end': self.end_time.total_seconds(), 'handout': self.handout, 'id': self.location.html_id(), 'show_captions': json.dumps(self.show_captions), 'download_video_link': download_video_link, 'sources': json.dumps(sources), 'speed': json.dumps(self.speed), 'general_speed': self.global_speed, 'saved_video_position': self.saved_video_position.total_seconds(), 'start': self.start_time.total_seconds(), 'sub': self.sub, 'track': track_url, 'youtube_streams': youtube_streams or create_youtube_string(self), # TODO: Later on the value 1500 should be taken from some global # configuration setting field. 'yt_test_timeout': 1500, 'yt_api_url': settings.YOUTUBE['API'], 'yt_test_url': settings.YOUTUBE['TEST_URL'], 'transcript_download_format': transcript_download_format, 'transcript_download_formats_list': self.descriptor.fields['transcript_download_format'].values, 'transcript_language': transcript_language, 'transcript_languages': json.dumps(sorted_languages), 'transcript_translation_url': self.runtime.handler_url(self, 'transcript', 'translation').rstrip('/?'), 'transcript_available_translations_url': self.runtime.handler_url( self, 'transcript', 'available_translations').rstrip('/?'), 'license': getattr(self, "license", None), })
def get_html(self): transcript_download_format = self.transcript_download_format if not (self.download_track and self.track) else None sources = filter(None, self.html5_sources) # If the user comes from China use China CDN for html5 videos. # 'CN' is China ISO 3166-1 country code. # Video caching is disabled for Studio. User_location is always None in Studio. # CountryMiddleware disabled for Studio. cdn_url = getattr(settings, 'VIDEO_CDN_URL', {}).get(self.system.user_location) if getattr(self, 'video_speed_optimizations', True) and cdn_url: for index, source_url in enumerate(sources): new_url = get_video_from_cdn(cdn_url, source_url) if new_url: sources[index] = new_url download_video_link = None youtube_streams = "" # If we have an edx_video_id, we prefer its values over what we store # internally for download links (source, html5_sources) and the youtube # stream. if self.edx_video_id and edxval_api: val_video_urls = edxval_api.get_urls_for_profiles( self.edx_video_id, ["desktop_mp4", "youtube"] ) # VAL will always give us the keys for the profiles we asked for, but # if it doesn't have an encoded video entry for that Video + Profile, the # value will map to `None` if val_video_urls["desktop_mp4"]: download_video_link = val_video_urls["desktop_mp4"] if val_video_urls["youtube"]: youtube_streams = "1.00:{}".format(val_video_urls["youtube"]) # If there was no edx_video_id, or if there was no download specified # for it, we fall back on whatever we find in the VideoDescriptor if not download_video_link and self.download_video: if self.source: download_video_link = self.source elif self.html5_sources: download_video_link = self.html5_sources[0] track_url, transcript_language, sorted_languages = self.get_transcripts_for_student() return self.system.render_template('video.html', { 'ajax_url': self.system.ajax_url + '/save_user_state', 'autoplay': settings.FEATURES.get('AUTOPLAY_VIDEOS', False), # This won't work when we move to data that # isn't on the filesystem 'data_dir': getattr(self, 'data_dir', None), 'display_name': self.display_name_with_default, 'end': self.end_time.total_seconds(), 'handout': self.handout, 'id': self.location.html_id(), 'show_captions': json.dumps(self.show_captions), 'download_video_link': download_video_link, 'sources': json.dumps(sources), 'speed': json.dumps(self.speed), 'general_speed': self.global_speed, 'saved_video_position': self.saved_video_position.total_seconds(), 'start': self.start_time.total_seconds(), 'sub': self.sub, 'track': track_url, 'youtube_streams': youtube_streams or create_youtube_string(self), # TODO: Later on the value 1500 should be taken from some global # configuration setting field. 'yt_test_timeout': 1500, 'yt_api_url': settings.YOUTUBE['API'], 'yt_test_url': settings.YOUTUBE['TEST_URL'], 'transcript_download_format': transcript_download_format, 'transcript_download_formats_list': self.descriptor.fields['transcript_download_format'].values, 'transcript_language': transcript_language, 'transcript_languages': json.dumps(sorted_languages), 'transcript_translation_url': self.runtime.handler_url(self, 'transcript', 'translation').rstrip('/?'), 'transcript_available_translations_url': self.runtime.handler_url(self, 'transcript', 'available_translations').rstrip('/?'), })
def get_html(self): transcript_download_format = ( self.transcript_download_format if not (self.download_track and self.track) else None ) sources = filter(None, self.html5_sources) download_video_link = None branding_info = None youtube_streams = "" # If we have an edx_video_id, we prefer its values over what we store # internally for download links (source, html5_sources) and the youtube # stream. if self.edx_video_id and edxval_api: try: val_profiles = ["youtube", "desktop_webm", "desktop_mp4"] val_video_urls = edxval_api.get_urls_for_profiles(self.edx_video_id, val_profiles) # VAL will always give us the keys for the profiles we asked for, but # if it doesn't have an encoded video entry for that Video + Profile, the # value will map to `None` # add the non-youtube urls to the list of alternative sources # use the last non-None non-youtube url as the link to download the video for url in [val_video_urls[p] for p in val_profiles if p != "youtube"]: if url: if url not in sources: sources.append(url) if self.download_video: download_video_link = url # set the youtube url if val_video_urls["youtube"]: youtube_streams = "1.00:{}".format(val_video_urls["youtube"]) except edxval_api.ValInternalError: # VAL raises this exception if it can't find data for the edx video ID. This can happen if the # course data is ported to a machine that does not have the VAL data. So for now, pass on this # exception and fallback to whatever we find in the VideoDescriptor. log.warning("Could not retrieve information from VAL for edx Video ID: %s.", self.edx_video_id) # If the user comes from China use China CDN for html5 videos. # 'CN' is China ISO 3166-1 country code. # Video caching is disabled for Studio. User_location is always None in Studio. # CountryMiddleware disabled for Studio. cdn_url = getattr(settings, "VIDEO_CDN_URL", {}).get(self.system.user_location) if getattr(self, "video_speed_optimizations", True) and cdn_url: branding_info = BrandingInfoConfig.get_config().get(self.system.user_location) for index, source_url in enumerate(sources): new_url = get_video_from_cdn(cdn_url, source_url) if new_url: sources[index] = new_url # If there was no edx_video_id, or if there was no download specified # for it, we fall back on whatever we find in the VideoDescriptor if not download_video_link and self.download_video: if self.source: download_video_link = self.source elif self.html5_sources: download_video_link = self.html5_sources[0] track_url, transcript_language, sorted_languages = self.get_transcripts_for_student(self.get_transcripts_info()) # CDN_VIDEO_URLS is only to be used here and will be deleted # TODO([email protected]): Delete this after the CDN experiment has completed. html_id = self.location.html_id() if ( self.system.user_location == "CN" and settings.FEATURES.get("ENABLE_VIDEO_BEACON", False) and html_id in getattr(settings, "CDN_VIDEO_URLS", {}).keys() ): cdn_urls = getattr(settings, "CDN_VIDEO_URLS", {})[html_id] cdn_exp_group, new_source = random.choice(zip(range(len(cdn_urls)), cdn_urls)) if cdn_exp_group > 0: sources[0] = new_source cdn_eval = True else: cdn_eval = False cdn_exp_group = None self.youtube_streams = youtube_streams or create_youtube_string(self) # pylint: disable=W0201 metadata = { "saveStateUrl": self.system.ajax_url + "/save_user_state", "autoplay": settings.FEATURES.get("AUTOPLAY_VIDEOS", False), "streams": self.youtube_streams, "sub": self.sub, "sources": sources, # This won't work when we move to data that # isn't on the filesystem "captionDataDir": getattr(self, "data_dir", None), "showCaptions": json.dumps(self.show_captions), "generalSpeed": self.global_speed, "speed": self.speed, "savedVideoPosition": self.saved_video_position.total_seconds(), "start": self.start_time.total_seconds(), "end": self.end_time.total_seconds(), "transcriptLanguage": transcript_language, "transcriptLanguages": sorted_languages, # TODO: Later on the value 1500 should be taken from some global # configuration setting field. "ytTestTimeout": 1500, "ytApiUrl": settings.YOUTUBE["API"], "ytTestUrl": settings.YOUTUBE["TEST_URL"], "transcriptTranslationUrl": self.runtime.handler_url(self, "transcript", "translation/__lang__").rstrip( "/?" ), "transcriptAvailableTranslationsUrl": self.runtime.handler_url( self, "transcript", "available_translations" ).rstrip("/?"), ## For now, the option "data-autohide-html5" is hard coded. This option ## either enables or disables autohiding of controls and captions on mouse ## inactivity. If set to true, controls and captions will autohide for ## HTML5 sources (non-YouTube) after a period of mouse inactivity over the ## whole video. When the mouse moves (or a key is pressed while any part of ## the video player is focused), the captions and controls will be shown ## once again. ## ## There is no option in the "Advanced Editor" to set this option. However, ## this option will have an effect if changed to "True". The code on ## front-end exists. "autohideHtml5": False, } bumperize(self) context = { "bumper_metadata": json.dumps(self.bumper["metadata"]), # pylint: disable=E1101 "metadata": json.dumps(OrderedDict(metadata)), "poster": json.dumps(get_poster(self)), "branding_info": branding_info, "cdn_eval": cdn_eval, "cdn_exp_group": cdn_exp_group, "id": self.location.html_id(), "display_name": self.display_name_with_default, "handout": self.handout, "download_video_link": download_video_link, "track": track_url, "transcript_download_format": transcript_download_format, "transcript_download_formats_list": self.descriptor.fields["transcript_download_format"].values, "license": getattr(self, "license", None), } return self.system.render_template("video.html", context)
def get_html(self): transcript_download_format = ( self.transcript_download_format if not (self.download_track and self.track) else None ) sources = filter(None, self.html5_sources) download_video_link = None branding_info = None youtube_streams = "" # If we have an edx_video_id, we prefer its values over what we store # internally for download links (source, html5_sources) and the youtube # stream. if self.edx_video_id and edxval_api: try: val_profiles = ["youtube", "desktop_webm", "desktop_mp4"] val_video_urls = edxval_api.get_urls_for_profiles(self.edx_video_id, val_profiles) # VAL will always give us the keys for the profiles we asked for, but # if it doesn't have an encoded video entry for that Video + Profile, the # value will map to `None` # add the non-youtube urls to the list of alternative sources # use the last non-None non-youtube url as the link to download the video for url in [val_video_urls[p] for p in val_profiles if p != "youtube"]: if url: if url not in sources: sources.append(url) if self.download_video: download_video_link = url # set the youtube url if val_video_urls["youtube"]: youtube_streams = "1.00:{}".format(val_video_urls["youtube"]) except edxval_api.ValInternalError: # VAL raises this exception if it can't find data for the edx video ID. This can happen if the # course data is ported to a machine that does not have the VAL data. So for now, pass on this # exception and fallback to whatever we find in the VideoDescriptor. log.warning("Could not retrieve information from VAL for edx Video ID: %s.", self.edx_video_id) # If the user comes from China use China CDN for html5 videos. # 'CN' is China ISO 3166-1 country code. # Video caching is disabled for Studio. User_location is always None in Studio. # CountryMiddleware disabled for Studio. cdn_url = getattr(settings, "VIDEO_CDN_URL", {}).get(self.system.user_location) if getattr(self, "video_speed_optimizations", True) and cdn_url: branding_info = BrandingInfoConfig.get_config().get(self.system.user_location) for index, source_url in enumerate(sources): new_url = get_video_from_cdn(cdn_url, source_url) if new_url: sources[index] = new_url # If there was no edx_video_id, or if there was no download specified # for it, we fall back on whatever we find in the VideoDescriptor if not download_video_link and self.download_video: if self.source: download_video_link = self.source elif self.html5_sources: download_video_link = self.html5_sources[0] track_url, transcript_language, sorted_languages = self.get_transcripts_for_student() # CDN_VIDEO_URLS is only to be used here and will be deleted # TODO([email protected]): Delete this after the CDN experiment has completed. html_id = self.location.html_id() if ( self.system.user_location == "CN" and settings.FEATURES.get("ENABLE_VIDEO_BEACON", False) and html_id in getattr(settings, "CDN_VIDEO_URLS", {}).keys() ): cdn_urls = getattr(settings, "CDN_VIDEO_URLS", {})[html_id] cdn_exp_group, new_source = random.choice(zip(range(len(cdn_urls)), cdn_urls)) if cdn_exp_group > 0: sources[0] = new_source cdn_eval = True else: cdn_eval = False cdn_exp_group = None return self.system.render_template( "video.html", { "ajax_url": self.system.ajax_url + "/save_user_state", "autoplay": settings.FEATURES.get("AUTOPLAY_VIDEOS", False), "branding_info": branding_info, "cdn_eval": cdn_eval, "cdn_exp_group": cdn_exp_group, # This won't work when we move to data that # isn't on the filesystem "data_dir": getattr(self, "data_dir", None), "display_name": self.display_name_with_default, "end": self.end_time.total_seconds(), "handout": self.handout, "id": self.location.html_id(), "show_captions": json.dumps(self.show_captions), "download_video_link": download_video_link, "sources": json.dumps(sources), "speed": json.dumps(self.speed), "general_speed": self.global_speed, "saved_video_position": self.saved_video_position.total_seconds(), "start": self.start_time.total_seconds(), "sub": self.sub, "track": track_url, "youtube_streams": youtube_streams or create_youtube_string(self), # TODO: Later on the value 1500 should be taken from some global # configuration setting field. "yt_test_timeout": 1500, "yt_api_url": settings.YOUTUBE["API"], "yt_test_url": settings.YOUTUBE["TEST_URL"], "transcript_download_format": transcript_download_format, "transcript_download_formats_list": self.descriptor.fields["transcript_download_format"].values, "transcript_language": transcript_language, "transcript_languages": json.dumps(sorted_languages), "transcript_translation_url": self.runtime.handler_url(self, "transcript", "translation").rstrip("/?"), "transcript_available_translations_url": self.runtime.handler_url( self, "transcript", "available_translations" ).rstrip("/?"), }, )