From cd414a0dafd1132cbb382233377a68d1b54b52e7 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Thu, 21 Nov 2024 11:27:41 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(back)=20authorize=20ended=20live?= =?UTF-8?q?=20to=20initiate=20a=20transcription?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a live has been harvested and transform in VOD, then it is possible to initialize a transcription process. --- CHANGELOG.md | 4 ++ src/backend/marsha/core/api/video.py | 2 +- .../api/video/test_initiate_transcript.py | 60 +++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b87bcc4241..ec6d5f37f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed + +- Authorize ended live to initiate a transcription + ## [5.4.0] - 2024-11-13 ### Changed diff --git a/src/backend/marsha/core/api/video.py b/src/backend/marsha/core/api/video.py index 30b921514a..1b6c94cbb7 100644 --- a/src/backend/marsha/core/api/video.py +++ b/src/backend/marsha/core/api/video.py @@ -1215,7 +1215,7 @@ def initiate_transcript(self, request, pk=None): """Initiate the transcript process for the video.""" video = self.get_object() - if video.live_state is not None: + if video.live_state and video.live_state != defaults.ENDED: return Response( {"detail": "Cannot initiate transcript on a live video"}, status=HTTPStatus.BAD_REQUEST, diff --git a/src/backend/marsha/core/tests/api/video/test_initiate_transcript.py b/src/backend/marsha/core/tests/api/video/test_initiate_transcript.py index 7dc33d8556..582a1a1f7f 100644 --- a/src/backend/marsha/core/tests/api/video/test_initiate_transcript.py +++ b/src/backend/marsha/core/tests/api/video/test_initiate_transcript.py @@ -3,6 +3,7 @@ from datetime import datetime, timezone as baseTimezone from http import HTTPStatus import json +import random from unittest import mock from django.db.transaction import atomic @@ -49,6 +50,23 @@ def test_api_video_instructor_initiate_transcript_in_read_only(self): self.assertEqual(response.status_code, HTTPStatus.FORBIDDEN) + def test_api_video_instructor_initiate_transcript_for_live_video(self): + """A video in a live state can not initiate a transcription.""" + video = factories.VideoFactory( + live_type=defaults.JITSI, + live_state=random.choice( + [s[0] for s in defaults.LIVE_CHOICES if s[0] not in [defaults.ENDED]] + ), + ) + jwt_token = InstructorOrAdminLtiTokenFactory(playlist=video.playlist) + + response = self.client.post( + f"/api/videos/{video.id}/initiate-transcript/", + HTTP_AUTHORIZATION=f"Bearer {jwt_token}", + ) + + self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST) + def test_api_video_initiate_transcript_token_user(self): """A token user associated to a video should be able to initiate a transcript.""" video = factories.VideoFactory( @@ -86,6 +104,48 @@ def test_api_video_initiate_transcript_token_user(self): self.assertEqual(timed_text_track.mode, models.TimedTextTrack.TRANSCRIPT) self.assertEqual(timed_text_track.upload_state, defaults.PROCESSING) + def test_api_video_initiate_transcript_token_user_live_state_ended(self): + """ + A token user associated to a video with live_state ended should be able to initiate + a transcript. + """ + video = factories.VideoFactory( + pk="a2f27fde-973a-4e89-8dca-cc59e01d255c", + live_type=defaults.JITSI, + live_state=defaults.ENDED, + upload_state=defaults.READY, + uploaded_on=datetime(2018, 8, 8, tzinfo=baseTimezone.utc), + transcode_pipeline=defaults.PEERTUBE_PIPELINE, + resolutions=[720, 1080], + playlist__title="foo bar", + ) + jwt_token = InstructorOrAdminLtiTokenFactory(playlist=video.playlist) + + with self.settings(LANGUAGES=(("en", "English"),)), mock.patch( + "marsha.core.api.video.launch_video_transcript.delay" + ) as mock_launch_video_transcript, mock.patch.object( + channel_layers_utils, "dispatch_timed_text_track" + ) as mock_dispatch_timed_text_track, mock.patch.object( + channel_layers_utils, "dispatch_video" + ) as mock_dispatch_video: + response = self.client.post( + f"/api/videos/{video.id}/initiate-transcript/", + HTTP_AUTHORIZATION=f"Bearer {jwt_token}", + ) + + self.assertEqual(response.status_code, HTTPStatus.OK) + mock_launch_video_transcript.assert_called_once_with( + video_pk=video.pk, stamp="1533686400", domain="http://testserver" + ) + + timed_text_track = video.timedtexttracks.get() + mock_dispatch_timed_text_track.assert_called_once_with(timed_text_track) + mock_dispatch_video.assert_called_once_with(video) + + self.assertEqual(timed_text_track.language, "en") + self.assertEqual(timed_text_track.mode, models.TimedTextTrack.TRANSCRIPT) + self.assertEqual(timed_text_track.upload_state, defaults.PROCESSING) + def test_api_video_initiate_transcript_staff_or_user(self): """Users authenticated via a session should not be able to retrieve a transcript policy.""" for user in [factories.UserFactory(), factories.UserFactory(is_staff=True)]: