예제 #1
0
    def setUp(self):
        self.VP = VideoProto(client_title='Test Title', veda_id='TESTID')

        with patch.object(VALAPICall, '_AUTH',
                          PropertyMock(return_value=lambda: CONFIG_DATA)):
            self.VAC = VALAPICall(video_proto=self.VP, val_status='complete')

        self.auth_yaml = CONFIG_DATA
예제 #2
0
def urlpatch(upload_data):
    """

    # :param upload_data: dict
    # :return:
    """
    if upload_data['status'] == 'Failure':
        return None
    try:
        test_id = Video.objects.filter(edx_id=upload_data['edx_id']).latest()
    except:
        upload_data['status'] = 'Failure'
        return

    if upload_data['status'] == 'Successful':
        LOGGER.info('[YOUTUBE CALLBACK] : Urlpatch : Upload status is successful : {upload_data}'.format(
            upload_data=upload_data
        ))
        url_query = URL.objects.filter(
            encode_url=upload_data['youtube_id']
        )

        if len(url_query) == 0:
            u1 = URL(
                videoID=Video.objects.filter(
                    edx_id=test_id.edx_id
                ).latest()
            )
            u1.encode_profile = Encode.objects.get(
                encode_suffix=upload_data['file_suffix']
            )
            u1.encode_url = upload_data['youtube_id']
            u1.url_date = upload_data['datetime']
            u1.encode_duration = test_id.video_orig_duration
            u1.encode_bitdepth = 0
            u1.encode_size = 0
            u1.save()

            """
            Report to Email

            """
            if 'EDXABVID' in upload_data['edx_id']:
                v1 = Video.objects.filter(edx_id=upload_data['edx_id']).latest()
                if v1.abvid_serial is not None:

                    report_status(
                        status="Complete",
                        abvid_serial=v1.abvid_serial,
                        youtube_id=upload_data['youtube_id']
                    )

        video_check = Video.objects.filter(edx_id=test_id.edx_id).latest()

        if video_check.video_trans_status == 'Youtube Duplicate':
            Video.objects.filter(
                edx_id=video_check.edx_id
            ).update(
                video_trans_status='Progress'
            )

        """
        Update Status & VAL
        """
        video_proto = VideoProto(
            veda_id=test_id.edx_id,
            val_id=test_id.studio_id,
            client_title=test_id.client_title,
            duration=test_id.video_orig_duration,
            bitrate='0',
            s3_filename=test_id.studio_id
        )
        VF = Metadata(
            video_object=test_id
        )

        encode_list = VF._FAULT(
            video_object=test_id
        )

        """
        Review can stop here
        """
        if upload_data['file_suffix'] == 'RVW':
            return None

        if len(encode_list) == 0:
            Video.objects.filter(edx_id=upload_data['edx_id']).update(video_trans_status='Complete')
            val_status = 'file_complete'
        else:
            val_status = 'transcode_active'

        ApiConn = VALAPICall(
            video_proto=video_proto,
            val_status=val_status,
            endpoint_url=upload_data['youtube_id'],
            encode_profile='youtube'
        )
        ApiConn.call()

    elif upload_data['status'] == 'Duplicate' and \
            upload_data['file_suffix'] == '100':

        LOGGER.info('[YOUTUBE CALLBACK] : Urlpatch : Upload status is duplicate : {upload_data}'.format(
            upload_data=upload_data
        ))

        url_query = URL.objects.filter(
            videoID=Video.objects.filter(
                edx_id=upload_data['edx_id']
            ).latest(),
            encode_profile=Encode.objects.get(
                encode_suffix=upload_data['file_suffix']
            )
        )
        if len(url_query) == 0:

            if 'EDXABVID' in upload_data['edx_id']:
                report_status(
                    status="Youtube Duplicate",
                    abvid_serial=test_id.abvid_serial,
                    youtube_id=''
                )

            Video.objects.filter(edx_id=upload_data['edx_id']).update(video_trans_status='Youtube Duplicate')
            video_proto = VideoProto(
                veda_id=test_id.edx_id,
                val_id=test_id.studio_id,
                client_title=test_id.client_title,
                duration=test_id.video_orig_duration,
                bitrate='0',
                s3_filename=test_id.studio_id
            )
            ApiConn = VALAPICall(
                video_proto=video_proto,
                val_status="duplicate",
                endpoint_url="DUPLICATE",
                encode_profile='youtube'
            )
            ApiConn.call()
예제 #3
0
class TestVALAPI(TestCase):
    def setUp(self):
        self.VP = VideoProto(client_title='Test Title', veda_id='TESTID')

        with patch.object(VALAPICall, '_AUTH',
                          PropertyMock(return_value=lambda: CONFIG_DATA)):
            self.VAC = VALAPICall(video_proto=self.VP, val_status='complete')

        self.auth_yaml = CONFIG_DATA

    def test_val_setup(self):
        # register val url to send api response
        responses.add(responses.POST,
                      CONFIG_DATA['val_token_url'],
                      '{"access_token": "1234567890"}',
                      status=200)

        salient_variables = [
            'val_api_url',
            'val_client_id',
            'val_password',
            'val_secret_key',
            'val_username',
            'val_token_url',
        ]
        for salient_variable in salient_variables:
            self.assertTrue(len(self.VAC.auth_dict[salient_variable]) > 0)

    @responses.activate
    def test_val_connection(self):
        # register val url to send api response
        responses.add(responses.POST,
                      CONFIG_DATA['val_token_url'],
                      '{"access_token": "1234567890"}',
                      status=200)
        responses.add(responses.GET, CONFIG_DATA['val_api_url'], status=200)

        self.VAC.val_tokengen()
        self.assertFalse(self.VAC.val_token is None)

        response = requests.get(self.VAC.auth_dict['val_api_url'],
                                headers=self.VAC.headers,
                                timeout=20)

        self.assertFalse(response.status_code == 404)
        self.assertFalse(response.status_code > 299)

    @data(
        {
            'encode_list': [],
            'val_status': 'file_complete',
            'expected_response': False
        },
        {
            'encode_list': [],
            'val_status': ValTranscriptStatus.TRANSCRIPT_READY,
            'expected_response': False
        },
        {
            'encode_list': [],
            'val_status': ValTranscriptStatus.TRANSCRIPTION_IN_PROGRESS,
            'expected_response': False
        },
        {
            'encode_list': ['abc.mp4'],
            'val_status': 'file_complete',
            'expected_response': True
        },
        {
            'encode_list': ['abc.mp4'],
            'val_status': ValTranscriptStatus.TRANSCRIPT_READY,
            'expected_response': True
        },
        {
            'encode_list': ['abc.mp4'],
            'val_status': ValTranscriptStatus.TRANSCRIPTION_IN_PROGRESS,
            'expected_response': True
        },
    )
    @unpack
    def test_val_should_update_status(self, encode_list, val_status,
                                      expected_response):
        """
        Verify that `should_update_status` works as expected.
        """
        response = self.VAC.should_update_status(encode_list, val_status)
        self.assertEqual(response, expected_response)
예제 #4
0
def handle_video_translations(video, translations, file_id, api_key,
                              log_prefix):
    """
    It is a sub-module of `retrieve_three_play_translations` to handle
    all the completed translations for a single video.

    Arguments:
        video: Video data object whose translations need to be handled here.
        translations: A list containing translations metadata information received from 3play Media.
        file_id: It is file identifier that is assigned to a Video by 3Play Media.
        api_key: An api key to communicate to the 3Play Media.
        log_prefix: A logging prefix used by the main process.

    Steps include:
        - Fetch translated transcript content from 3Play Media.
        - Validate the content of received translated transcript.
        - Convert translated SRT transcript to SJson format and upload it to S3.
        - Update edx-val for a completed transcript.
        - update transcript status for video in edx-val as well as edx-video-pipeline.
    """
    video_translation_processes = get_in_progress_translation_processes(video)
    for translation_metadata in translations:

        translation_id = translation_metadata['id']
        translation_state = translation_metadata['state']
        target_language = translation_metadata[
            'target_language_iso_639_1_code']

        LOGGER.info(
            '[3PlayMedia Task] Translation metadata retrieved -- video=%s, translation_id=%s, language=%s, status=%s.',
            video.studio_id, translation_id, target_language,
            translation_state)

        if translation_state == COMPLETE:
            # Fetch the corresponding tracking process.
            translation_process = get_in_progress_translation_process(
                video_translation_processes,
                file_id=file_id,
                translation_id=translation_id,
                target_language=target_language)
            if translation_process is None:
                continue

            # 1 - Fetch translated transcript content from 3Play Media.
            srt_transcript = get_transcript_content_from_3play_media(
                api_key=api_key,
                edx_video_id=video.studio_id,
                file_id=file_id,
                translation_id=translation_id,
                target_language=target_language,
            )
            if srt_transcript is None:
                continue

            # 2 - Validate the content of received translated transcript.
            is_transcript_valid = validate_transcript_response(
                edx_video_id=video.studio_id,
                file_id=file_id,
                transcript=srt_transcript,
                lang_code=target_language,
                log_prefix=log_prefix)
            if is_transcript_valid:
                translation_process.update(status=TranscriptStatus.READY)
            else:
                translation_process.update(status=TranscriptStatus.FAILED)
                continue

            # 3 - Convert SRT translation to SJson format and upload it to S3.
            sjson_file = convert_to_sjson_and_upload_to_s3(
                srt_transcript=srt_transcript,
                target_language=target_language,
                edx_video_id=video.studio_id,
                file_id=file_id,
            )

            # 4 Update edx-val with completed transcript information
            val_api = VALAPICall(video_proto=None, val_status=None)
            val_api.update_val_transcript(
                video_id=video.studio_id,
                lang_code=target_language,
                name=sjson_file,
                transcript_format=TRANSCRIPT_SJSON,
                provider=TranscriptProvider.THREE_PLAY,
            )

            LOGGER.info(
                '[3PlayMedia Task] Translation retrieval was successful -- video=%s, translation_id=%s, language=%s.',
                video.studio_id, translation_id, target_language)

            # 5 - if all the processes for this video are complete, update transcript status
            # for video in edx-val as well as edx-video-pipeline.
            video_jobs = TranscriptProcessMetadata.objects.filter(video=video)
            if all(video_job.status == TranscriptStatus.READY
                   for video_job in video_jobs):
                utils.update_video_status(val_api_client=val_api,
                                          video=video,
                                          status=TranscriptStatus.READY)
예제 #5
0
def three_play_transcription_callback(sender, **kwargs):
    """
    This is a receiver for 3Play Media callback signal.

    Arguments:
        sender: sender of the signal
        kwargs(dict): video transcription metadata

    Process:
        * download transcript(SRT) from 3PlayMedia
        * convert SRT to SJSON
        * upload SJSON to AWS S3
        * order translations for all the preferred languages
        * update transcript status in VAL
    """
    log_prefix = u'3PlayMedia Callback'
    # Extract all the must have attributes
    org = kwargs['org']
    edx_video_id = kwargs['edx_video_id']
    lang_code = kwargs['lang_code']
    file_id = kwargs['file_id']
    state = kwargs['status']

    try:
        process = TranscriptProcessMetadata.objects.filter(
            provider=TranscriptProvider.THREE_PLAY,
            process_id=file_id,
            lang_code=lang_code,
        ).latest()
    except TranscriptProcessMetadata.DoesNotExist:
        LOGGER.exception(
            u'[3PlayMedia Callback] Unable to get transcript process for org=%s, edx_video_id=%s, file_id=%s.',
            org,
            edx_video_id,
            file_id,
        )
        return

    # On completion of a transcript
    # Indicates that the default video speech transcription has been done successfully.
    if state == COMPLETE:
        log_args = (edx_video_id, lang_code, file_id)

        # 1 - Retrieve transcript credentials
        transcript_secrets = get_transcript_credentials(
            provider=TranscriptProvider.THREE_PLAY,
            org=org,
            edx_video_id=edx_video_id,
            file_id=file_id,
            log_prefix=log_prefix,
        )
        if not transcript_secrets:
            process.update(status=TranscriptStatus.FAILED)
            return

        # 2 - Fetch the transcript from 3Play Media.
        try:
            srt_transcript = fetch_srt_data(
                THREE_PLAY_TRANSCRIPT_URL.format(file_id=file_id),
                apikey=transcript_secrets.api_key,
            )
        except TranscriptFetchError:
            LOGGER.exception(
                u'[3PlayMedia Callback] Fetch request failed for video=%s -- lang_code=%s -- process_id=%s',
                *log_args)
            process.update(status=TranscriptStatus.FAILED)
            return

        # 3 - Validate transcript content received from 3Play Media and mark the transcription process.
        is_valid_transcript = validate_transcript_response(
            edx_video_id=edx_video_id,
            file_id=file_id,
            transcript=srt_transcript,
            lang_code=lang_code,
            log_prefix=log_prefix,
        )
        if is_valid_transcript:
            process.update(status=TranscriptStatus.READY)
        else:
            process.update(status=TranscriptStatus.FAILED)

        # 4 - Convert SRT transcript to SJson format and upload it to S3.
        try:
            sjson_transcript = convert_srt_to_sjson(srt_transcript)
            sjson_file = upload_sjson_to_s3(CONFIG, sjson_transcript)
        except Exception:
            # in case of any exception, log and raise.
            LOGGER.exception(
                u'[3PlayMedia Callback] Request failed for video=%s -- lang_code=%s -- process_id=%s',
                *log_args)
            raise

        # 5 - Update edx-val with completed transcript information.
        val_api = VALAPICall(video_proto=None, val_status=None)
        val_api.update_val_transcript(
            video_id=process.video.studio_id,
            lang_code=lang_code,
            name=sjson_file,
            transcript_format=TRANSCRIPT_SJSON,
            provider=TranscriptProvider.THREE_PLAY,
        )

        # 6 - Translation Phase
        # That's the phase for kicking off translation processes for all the
        # preferred languages except the video's speech language.
        target_languages = list(process.video.preferred_languages)
        target_languages.remove(lang_code)

        # Create the translation tracking processes for all the target languages.
        for target_language in target_languages:
            TranscriptProcessMetadata.objects.create(
                video=process.video,
                provider=TranscriptProvider.THREE_PLAY,
                process_id=file_id,
                lang_code=target_language,
                status=TranscriptStatus.PENDING,
            )

        # Order translations for target languages
        try:
            order_translations(file_id,
                               transcript_secrets.api_key,
                               transcript_secrets.api_secret,
                               source_language=lang_code,
                               target_languages=target_languages)
        except TranscriptTranslationError:
            LOGGER.exception(
                u'[3PlayMedia Callback] Translation could not be performed - video=%s, lang_code=%s, file_id=%s.',
                *log_args)
        except Exception:
            LOGGER.exception(
                u'[3PlayMedia Callback] Error while translating the transcripts - video=%s, lang_code=%s, file_id=%s',
                *log_args)
            raise

        # 7 - Update transcript status.
        # It will be for edx-val as well as edx-video-pipeline and this will be the case when
        # there is only one transcript language for a video(that is, already been processed).
        if not target_languages:
            utils.update_video_status(val_api_client=val_api,
                                      video=process.video,
                                      status=TranscriptStatus.READY)

        # On success, a happy farewell log.
        LOGGER.info((
            u'[3PlayMedia Callback] Video speech transcription was successful for'
            u' video=%s -- lang_code=%s -- process_id=%s'), *log_args)

    elif state == ERROR:
        # Fail the process
        process.status = TranscriptStatus.FAILED
        process.save()
        # Log the error information
        LOGGER.error(
            u'[3PlayMedia Callback] Error while transcription - error=%s, org=%s, edx_video_id=%s, file_id=%s.',
            kwargs['error_description'],
            org,
            edx_video_id,
            file_id,
        )
    else:
        # Status must be either 'complete' or 'error'
        # more details on http://support.3playmedia.com/hc/en-us/articles/227729828-Files-API-Methods
        LOGGER.error(
            u'[3PlayMedia Callback] Got invalid status - status=%s, org=%s, edx_video_id=%s, file_id=%s.',
            state,
            org,
            edx_video_id,
            file_id,
        )
예제 #6
0
def cielo24_transcript_callback(sender, **kwargs):
    """
    * download transcript(SRT) from Cielo24
    * convert SRT to SJSON
    * upload SJSON to AWS S3
    * update transcript status in VAL
    """
    process_metadata = None
    transcript_prefs = None

    org = kwargs['org']
    job_id = kwargs['job_id']
    video_id = kwargs['video_id']
    iwp_name = kwargs['iwp_name']
    lang_code = kwargs['lang_code']

    LOGGER.info(
        '[CIELO24 TRANSCRIPTS] Transcript complete request received for '
        'video=%s -- org=%s -- lang=%s -- job_id=%s -- iwp_name=%s', video_id,
        org, lang_code, job_id, iwp_name)

    # get transcript credentials for an organization
    try:
        transcript_prefs = TranscriptCredentials.objects.get(
            org=org,
            provider=TranscriptProvider.CIELO24,
        )
    except TranscriptCredentials.DoesNotExist:
        LOGGER.exception(
            '[CIELO24 TRANSCRIPTS] Unable to get transcript credentials for job_id=%s',
            job_id)

    # mark the transcript for a particular language as ready
    try:
        process_metadata = TranscriptProcessMetadata.objects.filter(
            provider=TranscriptProvider.CIELO24,
            process_id=job_id,
            lang_code=lang_code).latest()
    except TranscriptProcessMetadata.DoesNotExist:
        LOGGER.exception(
            '[CIELO24 TRANSCRIPTS] Unable to get transcript process metadata for job_id=%s',
            job_id)

    # if transcript credentials are missing then we can do nothing
    if not transcript_prefs and process_metadata:
        process_metadata.status = TranscriptStatus.FAILED
        process_metadata.save()

    if transcript_prefs and process_metadata:
        api_key = transcript_prefs.api_key
        try:
            srt_data = fetch_srt_data(CIELO24_GET_CAPTION_URL,
                                      v=CIELO24_API_VERSION,
                                      job_id=job_id,
                                      api_token=api_key,
                                      caption_format='SRT')
        except TranscriptFetchError:
            process_metadata.status = TranscriptStatus.FAILED
            process_metadata.save()
            LOGGER.exception(
                '[CIELO24 TRANSCRIPTS] Fetch request failed for video=%s -- lang=%s -- job_id=%s',
                video_id, lang_code, job_id)
            return

        process_metadata.status = TranscriptStatus.READY
        process_metadata.save()

        try:
            sjson = convert_srt_to_sjson(srt_data)
            sjson_file_name = upload_sjson_to_s3(CONFIG, sjson)
        except Exception:
            LOGGER.exception(
                '[CIELO24 TRANSCRIPTS] Request failed for video=%s -- lang=%s -- job_id=%s.',
                video_id, lang_code, job_id)
            raise

        # update edx-val with completed transcript information
        val_api = VALAPICall(process_metadata.video, val_status=None)
        val_api.update_val_transcript(
            video_id=process_metadata.video.studio_id,
            lang_code=lang_code,
            name=sjson_file_name,
            transcript_format=TRANSCRIPT_SJSON,
            provider=TranscriptProvider.CIELO24)

        # update transcript status for video in edx-val only if all langauge transcripts are ready
        video_jobs = TranscriptProcessMetadata.objects.filter(
            video__studio_id=video_id)
        if all(video_job.status == TranscriptStatus.READY
               for video_job in video_jobs):
            utils.update_video_status(val_api_client=val_api,
                                      video=process_metadata.video,
                                      status=TranscriptStatus.READY)