diff --git a/audio-api/src/main/scala/no/ndla/audioapi/controller/TranscriptionController.scala b/audio-api/src/main/scala/no/ndla/audioapi/controller/TranscriptionController.scala index f0068b747..d675ec62e 100644 --- a/audio-api/src/main/scala/no/ndla/audioapi/controller/TranscriptionController.scala +++ b/audio-api/src/main/scala/no/ndla/audioapi/controller/TranscriptionController.scala @@ -6,9 +6,11 @@ import no.ndla.audioapi.service.{ReadService, TranscriptionService} import no.ndla.network.tapir.TapirController import no.ndla.network.tapir.TapirUtil.errorOutputsFor import no.ndla.network.tapir.auth.Permission.DRAFT_API_WRITE +import software.amazon.awssdk.services.transcribe.model.TranscriptionJobStatus import sttp.tapir.server.ServerEndpoint import sttp.tapir.{EndpointInput, endpoint, path} import sttp.tapir.* +import sttp.tapir.json.circe.jsonBody import scala.util.{Failure, Success} trait TranscriptionController { @@ -82,12 +84,15 @@ trait TranscriptionController { .description("Get the transcription of a video.") .in(videoId) .in(language) - .errorOut(errorOutputsFor(400, 404, 500)) + .errorOut(errorOutputsFor(400, 404, 405, 500)) + .out(stringBody) .requirePermission(DRAFT_API_WRITE) .serverLogicPure { _ => { case (videoId, language) => transcriptionService.getTranscription(videoId, language) match { - case Success(_) => Right(()) + case Success(Right(transcriptionContent)) => Right(transcriptionContent) + case Success(Left(jobStatus)) => + Right(jobStatus.toString) case Failure(ex: NoSuchElementException) => returnLeftError(ex) case Failure(ex) => returnLeftError(ex) } diff --git a/audio-api/src/main/scala/no/ndla/audioapi/service/TranscriptionService.scala b/audio-api/src/main/scala/no/ndla/audioapi/service/TranscriptionService.scala index 7d6d463f9..aeb07ec4c 100644 --- a/audio-api/src/main/scala/no/ndla/audioapi/service/TranscriptionService.scala +++ b/audio-api/src/main/scala/no/ndla/audioapi/service/TranscriptionService.scala @@ -21,12 +21,14 @@ trait TranscriptionService { def transcribeVideo(videoId: String, language: String, maxSpeakers: Int): Try[Unit] = { getTranscription(videoId, language) match { - case Success(status) if status == "COMPLETED" => + case Success(Right(string)) => logger.info(s"Transcription already completed for videoId: $videoId") return Failure(new JobAlreadyFoundException(s"Transcription already completed for videoId: $videoId")) - case Success(status) if status == "IN_PROGRESS" => + case Success(Left("IN_PROGRESS")) => logger.info(s"Transcription already in progress for videoId: $videoId") return Failure(new JobAlreadyFoundException(s"Transcription already in progress for videoId: $videoId")) + case Success(Left(_)) => + logger.info(s"Error occurred while checking transcription status for videoId") case _ => logger.info(s"No existing transcription job for videoId: $videoId") } @@ -47,7 +49,7 @@ trait TranscriptionService { val audioUri = s"s3://${props.TranscribeStorageName}/audio-extraction/$language/$videoId.mp3" logger.info(s"Transcribing audio from: $audioUri") - val jobName = s"transcription-$videoId-$language" + val jobName = s"transcribe-$videoId-$language" val mediaFormat = "mp3" val outputKey = s"transcription/$language/$videoId" val languageCode = language @@ -69,12 +71,28 @@ trait TranscriptionService { } } - def getTranscription(videoId: String, language: String): Try[String] = { - val jobName = s"transcription-$videoId-$language" + def getTranscription( + videoId: String, + language: String, + subtitles: Boolean = true + ): Try[Either[String, String]] = { + val jobName = s"transcribe-$videoId-$language" - transcribeClient.getTranscriptionJob(jobName).map { transcriptionJobResponse => - val transcriptionJobStatus = transcriptionJobResponse.transcriptionJob().transcriptionJobStatus() - transcriptionJobStatus.toString + transcribeClient.getTranscriptionJob(jobName).flatMap { transcriptionJobResponse => + val transcriptionJob = transcriptionJobResponse.transcriptionJob() + val transcriptionJobStatus = transcriptionJob.transcriptionJobStatus().toString + + if (transcriptionJobStatus == "COMPLETED") { + val transcribeUri = s"transcription/$language/${videoId}" + (if (subtitles) ".vtt" else "") + + s3TranscribeClient.getObject(transcribeUri).map { s3Object => + val content = scala.io.Source.fromInputStream(s3Object.stream).mkString + s3Object.stream.close() + Right(content) + } + } else { + Success(Left(transcriptionJobStatus)) + } } }