Esempio n. 1
0
 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)
Esempio n. 2
0
 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")
Esempio n. 3
0
 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)
Esempio n. 4
0
 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')
Esempio n. 5
0
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
Esempio n. 6
0
    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
Esempio n. 7
0
    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)
Esempio n. 8
0
 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)
Esempio n. 9
0
    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),
            })
Esempio n. 11
0
    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('/?'),
        })
Esempio n. 12
0
 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)
Esempio n. 13
0
    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)
Esempio n. 14
0
    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("/?"),
            },
        )