from django.conf import settings from drf_yasg.utils import swagger_auto_schema from rest_framework import permissions, status from rest_framework.parsers import ( FileUploadParser, FormParser, JSONParser, MultiPartParser, ) from rest_framework.response import Response from rest_framework.views import APIView from ..helpers import produce_ffmpeg_commands from ..models import EncodeProfile, Encoding from ..serializers import EncodeProfileSerializer class EncodingDetail(APIView): """Experimental. This View is used by remote workers Needs heavy testing and documentation. """ permission_classes = (permissions.IsAdminUser,) parser_classes = (JSONParser, MultiPartParser, FormParser, FileUploadParser) @swagger_auto_schema(auto_schema=None) def post(self, request, encoding_id): ret = {} force = request.data.get("force", False) task_id = request.data.get("task_id", False) action = request.data.get("action", "") chunk = request.data.get("chunk", False) chunk_file_path = request.data.get("chunk_file_path", "") encoding_status = request.data.get("status", "") progress = request.data.get("progress", "") commands = request.data.get("commands", "") logs = request.data.get("logs", "") retries = request.data.get("retries", "") worker = request.data.get("worker", "") temp_file = request.data.get("temp_file", "") total_run_time = request.data.get("total_run_time", "") if action == "start": try: encoding = Encoding.objects.get(id=encoding_id) media = encoding.media profile = encoding.profile except BaseException: Encoding.objects.filter(id=encoding_id).delete() return Response({"status": "fail"}, status=status.HTTP_400_BAD_REQUEST) # TODO: break chunk True/False logic here if ( Encoding.objects.filter( media=media, profile=profile, chunk=chunk, chunk_file_path=chunk_file_path, ).count() > 1 # noqa and force is False # noqa ): Encoding.objects.filter(id=encoding_id).delete() return Response({"status": "fail"}, status=status.HTTP_400_BAD_REQUEST) else: Encoding.objects.filter( media=media, profile=profile, chunk=chunk, chunk_file_path=chunk_file_path, ).exclude(id=encoding.id).delete() encoding.status = "running" if task_id: encoding.task_id = task_id encoding.save() if chunk: original_media_path = chunk_file_path original_media_md5sum = encoding.md5sum original_media_url = settings.SSL_FRONTEND_HOST + encoding.media_chunk_url else: original_media_path = media.media_file.path original_media_md5sum = media.md5sum original_media_url = settings.SSL_FRONTEND_HOST + media.original_media_url ret["original_media_url"] = original_media_url ret["original_media_path"] = original_media_path ret["original_media_md5sum"] = original_media_md5sum # generating the commands here, and will replace these with temporary # files created on the remote server tf = "TEMP_FILE_REPLACE" tfpass = "TEMP_FPASS_FILE_REPLACE" ffmpeg_commands = produce_ffmpeg_commands( original_media_path, media.media_info, resolution=profile.resolution, codec=profile.codec, output_filename=tf, pass_file=tfpass, chunk=chunk, ) if not ffmpeg_commands: encoding.delete() return Response({"status": "fail"}, status=status.HTTP_400_BAD_REQUEST) ret["duration"] = media.duration ret["ffmpeg_commands"] = ffmpeg_commands ret["profile_extension"] = profile.extension return Response(ret, status=status.HTTP_201_CREATED) elif action == "update_fields": try: encoding = Encoding.objects.get(id=encoding_id) except BaseException: return Response({"status": "fail"}, status=status.HTTP_400_BAD_REQUEST) to_update = ["size", "update_date"] if encoding_status: encoding.status = encoding_status to_update.append("status") if progress: encoding.progress = progress to_update.append("progress") if logs: encoding.logs = logs to_update.append("logs") if commands: encoding.commands = commands to_update.append("commands") if task_id: encoding.task_id = task_id to_update.append("task_id") if total_run_time: encoding.total_run_time = total_run_time to_update.append("total_run_time") if worker: encoding.worker = worker to_update.append("worker") if temp_file: encoding.temp_file = temp_file to_update.append("temp_file") if retries: encoding.retries = retries to_update.append("retries") try: encoding.save(update_fields=to_update) except BaseException: return Response({"status": "fail"}, status=status.HTTP_400_BAD_REQUEST) return Response({"status": "success"}, status=status.HTTP_201_CREATED) @swagger_auto_schema(auto_schema=None) def put(self, request, encoding_id, format=None): encoding_file = request.data["file"] encoding = Encoding.objects.filter(id=encoding_id).first() if not encoding: return Response( {"detail": "encoding does not exist"}, status=status.HTTP_400_BAD_REQUEST, ) encoding.media_file = encoding_file encoding.save() return Response({"detail": "ok"}, status=status.HTTP_201_CREATED) class EncodeProfileList(APIView): """List encode profiles""" @swagger_auto_schema( manual_parameters=[], tags=['Encoding Profiles'], operation_summary='List Encoding Profiles', operation_description='Lists all encoding profiles for videos', responses={200: EncodeProfileSerializer(many=True)}, ) def get(self, request, format=None): profiles = EncodeProfile.objects.all() serializer = EncodeProfileSerializer(profiles, many=True, context={"request": request}) return Response(serializer.data)