mirror of
https://github.com/mediacms-io/mediacms.git
synced 2026-06-06 17:13:02 -04:00
fix: update documentation and fix smaller issues (#1520)
This commit is contained in:
@@ -120,9 +120,11 @@ class MediaList(APIView):
|
||||
operation_description='Delete media for MediaCMS managers and reviewers',
|
||||
)
|
||||
def delete(self, request, format=None):
|
||||
if not is_mediacms_manager(request.user):
|
||||
return Response({"detail": "bad permissions"}, status=status.HTTP_403_FORBIDDEN)
|
||||
tokens = request.GET.get("tokens")
|
||||
if tokens:
|
||||
tokens = tokens.split(",")
|
||||
tokens = [t for t in tokens.split(",") if t][:50]
|
||||
Media.objects.filter(friendly_token__in=tokens).delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@@ -177,7 +179,7 @@ class CommentList(APIView):
|
||||
def delete(self, request, format=None):
|
||||
comment_ids = request.GET.get("comment_ids")
|
||||
if comment_ids:
|
||||
comments = comment_ids.split(",")
|
||||
comments = [c for c in comment_ids.split(",") if c][:50]
|
||||
Comment.objects.filter(uid__in=comments).delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
+13
-9
@@ -453,17 +453,21 @@ def kill_ffmpeg_process(filepath):
|
||||
filepath: Path to the file being processed by ffmpeg
|
||||
|
||||
Returns:
|
||||
subprocess.CompletedProcess: Result of the kill command
|
||||
bool: True if the lookup ran, False if input was unusable
|
||||
"""
|
||||
if not filepath:
|
||||
if not filepath or not isinstance(filepath, str):
|
||||
return False
|
||||
cmd = "ps aux|grep 'ffmpeg'|grep %s|grep -v grep |awk '{print $2}'" % filepath
|
||||
result = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True)
|
||||
pid = result.stdout.decode("utf-8").strip()
|
||||
if pid:
|
||||
cmd = "kill -9 %s" % pid
|
||||
result = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True)
|
||||
return result
|
||||
try:
|
||||
ps = subprocess.run(["ps", "aux"], stdout=subprocess.PIPE, check=False)
|
||||
except OSError:
|
||||
return False
|
||||
for line in ps.stdout.decode("utf-8", "replace").splitlines():
|
||||
if "ffmpeg" not in line or filepath not in line or "grep" in line:
|
||||
continue
|
||||
parts = line.split()
|
||||
if len(parts) > 1 and parts[1].isdigit():
|
||||
subprocess.run(["kill", "-9", parts[1]], check=False)
|
||||
return True
|
||||
|
||||
|
||||
def copy_video(original_media, copy_encodings=True, title_suffix="(Trimmed)"):
|
||||
|
||||
@@ -6,7 +6,6 @@ from django.core.files import File
|
||||
from django.db import models
|
||||
from django.db.models.signals import post_delete, post_save
|
||||
from django.dispatch import receiver
|
||||
from django.urls import reverse
|
||||
|
||||
from .. import helpers
|
||||
from .utils import (
|
||||
@@ -136,9 +135,6 @@ class Encoding(models.Model):
|
||||
def __str__(self):
|
||||
return f"{self.profile.name}-{self.media.title}"
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("api_get_encoding", kwargs={"encoding_id": self.id})
|
||||
|
||||
|
||||
@receiver(post_save, sender=Encoding)
|
||||
def encoding_file_save(sender, instance, created, **kwargs):
|
||||
|
||||
@@ -559,9 +559,8 @@ class Media(models.Model):
|
||||
profiles.remove(profile)
|
||||
encoding = Encoding(media=self, profile=profile)
|
||||
encoding.save()
|
||||
enc_url = settings.SSL_FRONTEND_HOST + encoding.get_absolute_url()
|
||||
tasks.encode_media.apply_async(
|
||||
args=[self.friendly_token, profile.id, encoding.id, enc_url],
|
||||
args=[self.friendly_token, profile.id, encoding.id],
|
||||
kwargs={"force": force},
|
||||
priority=0,
|
||||
)
|
||||
@@ -575,13 +574,12 @@ class Media(models.Model):
|
||||
continue
|
||||
encoding = Encoding(media=self, profile=profile)
|
||||
encoding.save()
|
||||
enc_url = settings.SSL_FRONTEND_HOST + encoding.get_absolute_url()
|
||||
if profile.resolution in settings.MINIMUM_RESOLUTIONS_TO_ENCODE:
|
||||
priority = 9
|
||||
else:
|
||||
priority = 0
|
||||
tasks.encode_media.apply_async(
|
||||
args=[self.friendly_token, profile.id, encoding.id, enc_url],
|
||||
args=[self.friendly_token, profile.id, encoding.id],
|
||||
kwargs={"force": force},
|
||||
priority=priority,
|
||||
)
|
||||
|
||||
+2
-5
@@ -171,8 +171,7 @@ def chunkize_media(self, friendly_token, profiles, force=True):
|
||||
continue
|
||||
encoding = Encoding(media=media, profile=profile)
|
||||
encoding.save()
|
||||
enc_url = settings.SSL_FRONTEND_HOST + encoding.get_absolute_url()
|
||||
encode_media.delay(friendly_token, profile.id, encoding.id, enc_url, force=force)
|
||||
encode_media.delay(friendly_token, profile.id, encoding.id, force=force)
|
||||
return False
|
||||
|
||||
chunks = [os.path.join(cwd, ch) for ch in chunks]
|
||||
@@ -202,13 +201,12 @@ def chunkize_media(self, friendly_token, profiles, force=True):
|
||||
)
|
||||
|
||||
encoding.save()
|
||||
enc_url = settings.SSL_FRONTEND_HOST + encoding.get_absolute_url()
|
||||
if profile.resolution in settings.MINIMUM_RESOLUTIONS_TO_ENCODE:
|
||||
priority = 0
|
||||
else:
|
||||
priority = 9
|
||||
encode_media.apply_async(
|
||||
args=[friendly_token, profile.id, encoding.id, enc_url],
|
||||
args=[friendly_token, profile.id, encoding.id],
|
||||
kwargs={"force": force, "chunk": True, "chunk_file_path": chunk},
|
||||
priority=priority,
|
||||
)
|
||||
@@ -246,7 +244,6 @@ def encode_media(
|
||||
friendly_token,
|
||||
profile_id,
|
||||
encoding_id,
|
||||
encoding_url,
|
||||
force=True,
|
||||
chunk=False,
|
||||
chunk_file_path="",
|
||||
|
||||
@@ -61,11 +61,6 @@ urlpatterns = [
|
||||
views.MediaDetail.as_view(),
|
||||
name="api_get_media",
|
||||
),
|
||||
re_path(
|
||||
r"^api/v1/media/encoding/(?P<encoding_id>[\w]*)$",
|
||||
views.EncodingDetail.as_view(),
|
||||
name="api_get_encoding",
|
||||
),
|
||||
re_path(r"^api/v1/search$", views.MediaSearch.as_view()),
|
||||
re_path(
|
||||
rf"^api/v1/media/{friendly_token}/share$",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from .auth import custom_login_view, saml_metadata # noqa: F401
|
||||
from .categories import CategoryList, CategoryListContributor, TagList # noqa: F401
|
||||
from .comments import CommentDetail, CommentList # noqa: F401
|
||||
from .encoding import EncodeProfileList, EncodingDetail # noqa: F401
|
||||
from .encoding import EncodeProfileList # noqa: F401
|
||||
from .media import MediaActions # noqa: F401
|
||||
from .media import MediaBulkUserActions # noqa: F401
|
||||
from .media import MediaDetail # noqa: F401
|
||||
|
||||
+1
-158
@@ -1,168 +1,11 @@
|
||||
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 ..models import EncodeProfile
|
||||
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"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user