Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 2 additions & 26 deletions cms/djangoapps/contentstore/toggles.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
CMS feature toggles.
"""
from edx_toggles.toggles import SettingDictToggle, WaffleFlag
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag

from openedx.core.djangoapps.content.search import api as search_api
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag

# .. toggle_name: FEATURES['ENABLE_EXPORT_GIT']
# .. toggle_implementation: SettingDictToggle
Expand Down Expand Up @@ -66,30 +67,6 @@ def bypass_olx_failure_enabled():
return BYPASS_OLX_FAILURE.is_enabled()


# .. toggle_name: contentstore.enable_audio_description
# .. toggle_implementation: CourseWaffleFlag
# .. toggle_default: False
# .. toggle_description: Enables the audio description (AD) upload UI in the
# Studio video editor and the corresponding studio_audio_description XBlock
# handler. When disabled, course authors cannot upload, replace, or delete
# audio description files for video blocks. Playback of AD files that were
# already uploaded is NOT gated by this flag and continues to work in the
# LMS -- disable the playback path with a separate flag if needed.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2026-04-07
ENABLE_AUDIO_DESCRIPTION = CourseWaffleFlag(
f'{CONTENTSTORE_NAMESPACE}.enable_audio_description',
__name__,
)


def audio_description_enabled(course_key):
"""
Return True if the audio description upload UI and handler are enabled.
"""
return ENABLE_AUDIO_DESCRIPTION.is_enabled(course_key)


# .. toggle_name: contentstore.enable_transcript_editor
# .. toggle_implementation: CourseWaffleFlag
# .. toggle_default: False
Expand Down Expand Up @@ -660,7 +637,6 @@ def libraries_v2_enabled():

Requires the ENABLE_CONTENT_LIBRARIES feature flag to be enabled, plus Meilisearch.
"""
from openedx.core.djangoapps.content.search import api as search_api # pylint: disable=import-outside-toplevel
return (
ENABLE_CONTENT_LIBRARIES.is_enabled() and
search_api.is_meilisearch_enabled() and
Expand Down
23 changes: 23 additions & 0 deletions openedx/core/djangoapps/video_config/toggles.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,26 @@ def use_xpert_translations_component(course_key):
Returns a boolean if xpert translations ui component is enabled
"""
return XPERT_TRANSLATIONS_UI.is_enabled(course_key)

# .. toggle_name: contentstore.enable_audio_description
# .. toggle_implementation: CourseWaffleFlag
# .. toggle_default: False
# .. toggle_description: Enables the audio description (AD) upload UI in the
# Studio video editor and the corresponding studio_audio_description XBlock
# handler. When disabled, course authors cannot upload, replace, or delete
# audio description files for video blocks. Playback of AD files that were
# already uploaded is NOT gated by this flag and continues to work in the
# LMS -- disable the playback path with a separate flag if needed.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2026-04-07
ENABLE_AUDIO_DESCRIPTION = CourseWaffleFlag(
'contentstore.enable_audio_description',
__name__,
)


def audio_description_enabled(course_key):
"""
Return True if the audio description upload UI and handler are enabled.
"""
return ENABLE_AUDIO_DESCRIPTION.is_enabled(course_key)
27 changes: 14 additions & 13 deletions xmodule/video_block/video_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,18 @@
from xblocks_contrib.video import VideoBlock as _ExtractedVideoBlock

from common.djangoapps.xblock_django.constants import ATTR_KEY_REQUEST_COUNTRY_CODE, ATTR_KEY_USER_ID
from openedx.core.djangoapps.video_config.models import HLSPlaybackEnabledFlag, CourseYoutubeBlockedFlag
from openedx.core.djangoapps.video_config.toggles import PUBLIC_VIDEO_SHARE, TRANSCRIPT_FEEDBACK
from openedx.core.djangoapps.video_config.models import CourseYoutubeBlockedFlag, HLSPlaybackEnabledFlag
from openedx.core.djangoapps.video_config.toggles import (
PUBLIC_VIDEO_SHARE,
TRANSCRIPT_FEEDBACK,
audio_description_enabled
)
from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE
from openedx.core.lib.cache_utils import request_cached
from openedx.core.lib.courses import get_course_by_id
from openedx.core.lib.license import LicenseMixin
from xmodule.contentstore.content import StaticContent
from xmodule.course_block import (
COURSE_VIDEO_SHARING_ALL_VIDEOS,
COURSE_VIDEO_SHARING_NONE,
)
from xmodule.course_block import COURSE_VIDEO_SHARING_ALL_VIDEOS, COURSE_VIDEO_SHARING_NONE
from xmodule.editing_block import EditingMixin
from xmodule.exceptions import NotFoundError
from xmodule.mako_block import MakoTemplateBlockBase
Expand All @@ -52,11 +53,15 @@
from xmodule.validation import StudioValidation, StudioValidationMessage
from xmodule.video_block import manage_video_subtitles_save
from xmodule.x_module import (
PUBLIC_VIEW, STUDENT_VIEW,
ResourceTemplates, shim_xmodule_js,
XModuleMixin, XModuleToXBlockMixin,
PUBLIC_VIEW,
STUDENT_VIEW,
ResourceTemplates,
XModuleMixin,
XModuleToXBlockMixin,
shim_xmodule_js
)
from xmodule.xml_block import XmlMixin, deserialize_field, is_pointer_tag, name_to_pathname

from .bumper_utils import bumperize
from .sharing_sites import sharing_sites_info_for_video
from .transcripts_utils import (
Expand Down Expand Up @@ -476,9 +481,6 @@ def get_html(self, view=STUDENT_VIEW, context=None): # lint-amnesty, pylint: di
metadata['audioDescriptionUrl'] = audio_description_url

try:
from cms.djangoapps.contentstore.toggles import ( # pylint: disable=import-outside-toplevel
audio_description_enabled
)
ad_feature_enabled = bool(audio_description_enabled(self.course_id))
except Exception: # pylint: disable=broad-except
ad_feature_enabled = False
Expand Down Expand Up @@ -991,7 +993,6 @@ def get_youtube_link(video_id):
}

_context.update({'transcripts_basic_tab_metadata': metadata})
from cms.djangoapps.contentstore.toggles import audio_description_enabled # pylint: disable=import-outside-toplevel

# Audio description upload context for studio editor
ad_upload_enabled = bool(
Expand Down
7 changes: 3 additions & 4 deletions xmodule/video_block/video_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
from django.utils.timezone import now
from edxval.api import create_external_video, create_or_update_video_transcript, delete_video_transcript
from opaque_keys.edx.locator import CourseLocator, LibraryLocatorV2

from webob import Response
from xblock.core import XBlock
from xblock.exceptions import JsonHandlerError

from openedx.core.djangoapps.content_libraries import api as lib_api
from openedx.core.djangoapps.video_config.toggles import audio_description_enabled
from xmodule.exceptions import NotFoundError
from xmodule.fields import RelativeTime
from openedx.core.djangoapps.content_libraries import api as lib_api

from .transcripts_utils import (
Transcript,
Expand Down Expand Up @@ -694,9 +694,8 @@ def studio_audio_description(self, request, suffix=''): # pylint: disable=unuse
AudioDescriptionUploadError,
delete_audio_description,
get_audio_description_url,
upload_audio_description,
upload_audio_description
)
from cms.djangoapps.contentstore.toggles import audio_description_enabled # pylint: disable=import-outside-toplevel

if not audio_description_enabled or not audio_description_enabled(self.course_id):
return Response(status=404)
Expand Down
Loading