Skip to content

Commit

Permalink
added Transcoding Job view
Browse files Browse the repository at this point in the history
  • Loading branch information
umar8hassan committed Feb 18, 2025
1 parent c903ed0 commit 0d11318
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/transcoding/mitol/transcoding/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,29 @@ def create_media_convert_job(video_source_key):
f"s3://{settings.AWS_STORAGE_BUCKET_NAME}/{video_source_key}"
)
return client.create_job(**job_dict)


def update_video_job(video_job: VideoJob, results: dict):
"""Update a VideoJob and associated Video, VideoFiles based on MediaConvert results""" # noqa: E501
video_job.job_output = results
status = results.get("status")
video = video_job.video
if status == "COMPLETE":
video_job.status = VideoJobStatus.COMPLETE
try:
process_video_outputs(video, results.get("outputGroupDetails"))
except: # pylint:disable=bare-except # noqa: E722
log.exception("Error processing video outputs for job %s", video_job.job_id)
elif status == "ERROR":
video.status = VideoStatus.FAILED
video_job.status = VideoJobStatus.FAILED
log.error(
"Transcode failure for %s, error code %s: %s",
video.source_key,
results.get("errorCode"),
results.get("errorMessage"),
)
video_job.error_code = str(results.get("errorCode"))
video_job.error_message = results.get("errorMessage")
video_job.save()
video.save()
4 changes: 4 additions & 0 deletions src/transcoding/mitol/transcoding/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""This module contains constants used in the transcoding app."""

BAD_REQUEST_MSG = "Token cannot be empty!"
TRANSCODE_JOB_SUBSCRIPTION_URL = "https://sns.{AWS_REGION}.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:{AWS_REGION}:{AWS_ACCOUNT_ID}:MediaConvertJobAlert&Token={TOKEN}"
12 changes: 12 additions & 0 deletions src/transcoding/mitol/transcoding/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""Videos Exceptions"""

from rest_framework import status
from rest_framework.exceptions import APIException


class BadRequest(APIException):
"""Exception for invalid request data"""

status_code = status.HTTP_400_BAD_REQUEST
default_detail = "Bad request."
default_code = "bad_request"
37 changes: 37 additions & 0 deletions src/transcoding/mitol/transcoding/settings/videos
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from mitol.common.envs import get_string


VIDEO_S3_TRANSCODE_PREFIX = get_string(
name="VIDEO_S3_TRANSCODE_PREFIX",
default="aws_mediaconvert_transcodes",
description=(
"Prefix to be used for S3 keys of files transcoded from AWS MediaConvert"
),
)
VIDEO_S3_TRANSCODE_ENDPOINT = get_string(
name="VIDEO_S3_TRANSCODE_ENDPOINT",
default="aws_mediaconvert_transcodes",
description=("Endpoint to be used for AWS MediaConvert"),
)
VIDEO_TRANSCODE_QUEUE = get_string(
name="VIDEO_TRANSCODE_QUEUE",
default="Default",
description=("Name of MediaConvert queue to use for transcoding"),
)
DRIVE_S3_UPLOAD_PREFIX = get_string(
name="DRIVE_S3_UPLOAD_PREFIX",
default="",
description=("Prefix to be used for S3 keys of files uploaded from Google Drive"),
)
AWS_STORAGE_BUCKET_NAME = get_string(
name="AWS_STORAGE_BUCKET_NAME", default=None, description="S3 Bucket name."
)
AWS_ACCOUNT_ID = get_string(name="AWS_ACCOUNT_ID", description="AWS Account ID")
AWS_REGION = get_string(
name="AWS_REGION", default="us-east-1", description="AWS Region"
)
AWS_ROLE_NAME = get_string(
name="AWS_ROLE_NAME",
default=None,
description="AWS role name to be used for MediaConvert jobs",
)
14 changes: 14 additions & 0 deletions src/transcoding/mitol/transcoding/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Transcoding utilities"""

from mitol.transcoding.constants import TRANSCODE_JOB_SUBSCRIPTION_URL
from django.conf import settings


def get_subscribe_url(token: str) -> str:
"""Get a SNS subscribe url"""

return TRANSCODE_JOB_SUBSCRIPTION_URL.format(
AWS_REGION=settings.AWS_REGION,
AWS_ACCOUNT_ID=settings.AWS_ACCOUNT_ID,
TOKEN=token,
)
53 changes: 53 additions & 0 deletions src/transcoding/mitol/transcoding/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""Views for transcoding app"""


import json
from urllib.parse import urljoin

import requests
from django.conf import settings
from rest_framework.exceptions import PermissionDenied
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

from mitol.transcoding.api import update_video_job
from mitol.transcoding.constants import BAD_REQUEST_MSG
from mitol.transcoding.exceptions import BadRequest
from mitol.transcoding.models import TranscodingJob
from mitol.transcoding.utils import get_subscribe_url


class TranscodeJobView(GenericAPIView):
"""Webhook endpoint for MediaConvert transcode job notifications from Cloudwatch"""

permission_classes = (AllowAny,)

def post(
self,
request,
*args, # noqa: ARG002
**kwargs, # noqa: ARG002
): # pylint: disable=unused-argument
"""Update Video and VideoFile objects based on request body"""
message = json.loads(request.body)
if message.get("SubscribeURL"):
# Confirm the subscription
if settings.AWS_ACCOUNT_ID not in message.get("TopicArn", ""):
raise PermissionDenied

token = message.get("Token", "")
if not token:
raise BadRequest(BAD_REQUEST_MSG)

subscribe_url = get_subscribe_url(token)
requests.get(subscribe_url, timeout=60)
else:
if message.get("account", "") != settings.AWS_ACCOUNT_ID:
raise PermissionDenied
detail = message.get("detail", {})
video_job = TranscodingJob.objects.get(job_id=detail.get("jobId"))
update_video_job(video_job, detail)
return Response(status=200, data={})


1 change: 1 addition & 0 deletions src/transcoding/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ dependencies = [
"django-stubs>=1.13.1",
"django>=3.0",
"edx-opaque-keys==2.2.2",
"boto3==1.36.13",
]
readme = "README.md"
license = "BSD-3-Clause"
Expand Down

0 comments on commit 0d11318

Please sign in to comment.