|
7 | 7 | """ |
8 | 8 |
|
9 | 9 | import logging |
| 10 | +from typing import Any |
10 | 11 |
|
| 12 | +from django.conf import settings |
11 | 13 | from opaque_keys.edx.keys import CourseKey, UsageKey |
12 | 14 | from opaque_keys.edx.locator import LibraryLocatorV2 |
13 | 15 | from xblocks_contrib.video.exceptions import TranscriptNotFoundError |
|
32 | 34 | clean_video_id, |
33 | 35 | get_html5_ids, |
34 | 36 | remove_subs_from_store, |
| 37 | + get_transcript_for_video, |
| 38 | + get_transcript, |
35 | 39 | ) |
36 | 40 |
|
| 41 | +from xmodule.exceptions import NotFoundError |
| 42 | + |
| 43 | + |
37 | 44 | log = logging.getLogger(__name__) |
38 | 45 |
|
39 | 46 |
|
@@ -127,17 +134,70 @@ def get_transcript( |
127 | 134 | TranscriptsGenerationException: If the transcript cannot be found or retrieved |
128 | 135 | TranscriptNotFoundError: If the transcript cannot be found or retrieved |
129 | 136 | """ |
130 | | - # Import here to avoid circular dependency |
131 | | - from openedx.core.djangoapps.video_config.transcripts_utils import get_transcript |
132 | | - from xmodule.exceptions import NotFoundError |
133 | | - |
134 | 137 | try: |
135 | 138 | return get_transcript(video_block, lang, output_format, youtube_id) |
136 | 139 | except NotFoundError as exc: |
137 | 140 | raise TranscriptNotFoundError( |
138 | 141 | f"Failed to get transcript: {exc}" |
139 | 142 | ) from exc |
140 | 143 |
|
| 144 | + def available_translations( |
| 145 | + self, |
| 146 | + video_block, |
| 147 | + transcripts: dict[str, Any], |
| 148 | + verify_assets: bool | None = None, |
| 149 | + is_bumper: bool = False, |
| 150 | + ) -> list[str]: |
| 151 | + """ |
| 152 | + Return a list of language codes for which we have transcripts. |
| 153 | +
|
| 154 | + Arguments: |
| 155 | + video_block: The video XBlock instance |
| 156 | + transcripts (dict): A dict with all transcripts and a sub. |
| 157 | + verify_assets (boolean): If True, checks to ensure that the transcripts |
| 158 | + really exist in the contentstore. If False, we just look at the |
| 159 | + VideoBlock fields and do not query the contentstore. One reason |
| 160 | + we might do this is to avoid slamming contentstore() with queries |
| 161 | + when trying to make a listing of videos and their languages. |
| 162 | +
|
| 163 | + Defaults to `not FALLBACK_TO_ENGLISH_TRANSCRIPTS`. |
| 164 | +
|
| 165 | + is_bumper (boolean): If True, indicates this is a bumper video. |
| 166 | +
|
| 167 | + Returns: |
| 168 | + list[str]: List of language codes for available transcripts. |
| 169 | + """ |
| 170 | + translations = [] |
| 171 | + if verify_assets is None: |
| 172 | + verify_assets = not settings.FEATURES.get('FALLBACK_TO_ENGLISH_TRANSCRIPTS') |
| 173 | + |
| 174 | + sub, other_langs = transcripts["sub"], transcripts["transcripts"] |
| 175 | + |
| 176 | + if verify_assets: |
| 177 | + all_langs = dict(**other_langs) |
| 178 | + if sub: |
| 179 | + all_langs.update({'en': sub}) |
| 180 | + |
| 181 | + for language, filename in all_langs.items(): |
| 182 | + try: |
| 183 | + # for bumper videos, transcripts are stored in content store only |
| 184 | + if is_bumper: |
| 185 | + get_transcript_for_video(video_block.location, filename, filename, language) |
| 186 | + else: |
| 187 | + get_transcript(video_block, language) |
| 188 | + except NotFoundError: |
| 189 | + continue |
| 190 | + |
| 191 | + translations.append(language) |
| 192 | + else: |
| 193 | + # If we're not verifying the assets, we just trust our field values |
| 194 | + translations = list(other_langs) |
| 195 | + if not translations or sub: |
| 196 | + translations += ['en'] |
| 197 | + |
| 198 | + # to clean redundant language codes. |
| 199 | + return list(set(translations)) |
| 200 | + |
141 | 201 | def upload_transcript( |
142 | 202 | self, |
143 | 203 | *, |
|
0 commit comments