mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-05 23:18:53 -05:00
fix black
This commit is contained in:
parent
68a209501e
commit
77503b38b9
@ -548,4 +548,3 @@ if GLOBAL_LOGIN_REQUIRED:
|
||||
r'/accounts/confirm-email/.*/$',
|
||||
# r'/api/v[0-9]+/',
|
||||
]
|
||||
|
||||
|
||||
@ -13,9 +13,9 @@ from .models import (
|
||||
Encoding,
|
||||
Language,
|
||||
Media,
|
||||
VideoTrimRequest,
|
||||
Subtitle,
|
||||
Tag,
|
||||
VideoTrimRequest,
|
||||
)
|
||||
|
||||
|
||||
@ -199,6 +199,7 @@ class LanguageAdmin(admin.ModelAdmin):
|
||||
class SubtitleAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
class VideoTrimRequestAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ from django import forms
|
||||
from django.conf import settings
|
||||
|
||||
from .methods import get_next_state, is_mediacms_editor
|
||||
from .models import Category, Media, MEDIA_STATES, Subtitle
|
||||
from .models import MEDIA_STATES, Category, Media, Subtitle
|
||||
|
||||
|
||||
class CustomField(Field):
|
||||
@ -92,12 +92,7 @@ class MediaMetadataForm(forms.ModelForm):
|
||||
|
||||
|
||||
class MediaPublishForm(forms.ModelForm):
|
||||
confirm_state = forms.BooleanField(
|
||||
required=False,
|
||||
initial=False,
|
||||
label="Acknowledge sharing status",
|
||||
help_text=""
|
||||
)
|
||||
confirm_state = forms.BooleanField(required=False, initial=False, label="Acknowledge sharing status", help_text="")
|
||||
|
||||
class Meta:
|
||||
model = Media
|
||||
@ -129,7 +124,6 @@ class MediaPublishForm(forms.ModelForm):
|
||||
valid_states.append(self.instance.state)
|
||||
self.fields["state"].choices = [(state, dict(MEDIA_STATES).get(state, state)) for state in valid_states]
|
||||
|
||||
|
||||
if getattr(settings, 'USE_RBAC', False) and 'category' in self.fields:
|
||||
if is_mediacms_editor(user):
|
||||
pass
|
||||
@ -187,7 +181,6 @@ class MediaPublishForm(forms.ModelForm):
|
||||
layout_items.insert(state_index + 1, CustomField('confirm_state'))
|
||||
self.helper.layout = Layout(*layout_items)
|
||||
|
||||
|
||||
if not cleaned_data.get('confirm_state'):
|
||||
error_message = f"I understand that although media state is {state}, the media is also shared with users that have access to the following categories: {', '.join(rbac_categories)}"
|
||||
self.add_error('confirm_state', error_message)
|
||||
|
||||
@ -822,6 +822,7 @@ def seconds_to_timestamp(seconds):
|
||||
|
||||
return f"{hours:02d}:{minutes:02d}:{seconds_int:02d}.{milliseconds:03d}"
|
||||
|
||||
|
||||
def get_trim_timestamps(media_file_path, timestamps_list, run_ffprobe=False):
|
||||
"""Process a list of timestamps to align start times with I-frames for better video trimming
|
||||
|
||||
@ -866,12 +867,17 @@ def get_trim_timestamps(media_file_path, timestamps_list, run_ffprobe=False):
|
||||
# Create ffprobe command to find nearest I-frame
|
||||
cmd = [
|
||||
settings.FFPROBE_COMMAND,
|
||||
"-v", "error",
|
||||
"-select_streams", "v:0",
|
||||
"-show_entries", "frame=pts_time,pict_type",
|
||||
"-of", "csv=p=0",
|
||||
"-read_intervals", f"{search_start}%{startTime}",
|
||||
media_file_path
|
||||
"-v",
|
||||
"error",
|
||||
"-select_streams",
|
||||
"v:0",
|
||||
"-show_entries",
|
||||
"frame=pts_time,pict_type",
|
||||
"-of",
|
||||
"csv=p=0",
|
||||
"-read_intervals",
|
||||
f"{search_start}%{startTime}",
|
||||
media_file_path,
|
||||
]
|
||||
cmd = [str(s) for s in cmd]
|
||||
logger.info(f"trim cmd: {cmd}")
|
||||
@ -889,10 +895,7 @@ def get_trim_timestamps(media_file_path, timestamps_list, run_ffprobe=False):
|
||||
if not i_frames:
|
||||
adjusted_startTime = startTime
|
||||
|
||||
timestamps_results.append({
|
||||
'startTime': adjusted_startTime,
|
||||
'endTime': endTime
|
||||
})
|
||||
timestamps_results.append({'startTime': adjusted_startTime, 'endTime': endTime})
|
||||
|
||||
return timestamps_results
|
||||
|
||||
@ -926,18 +929,9 @@ def trim_video_method(media_file_path, timestamps_list):
|
||||
# For multiple timestamps, we need to create segment files
|
||||
segment_file = output_file if len(timestamps_list) == 1 else os.path.join(temp_dir, f"segment_{i}.mp4")
|
||||
|
||||
cmd = [
|
||||
settings.FFMPEG_COMMAND,
|
||||
"-y",
|
||||
"-ss", str(item['startTime']),
|
||||
"-i", media_file_path,
|
||||
"-t", str(duration),
|
||||
"-c", "copy",
|
||||
"-avoid_negative_ts", "1",
|
||||
segment_file
|
||||
]
|
||||
cmd = [settings.FFMPEG_COMMAND, "-y", "-ss", str(item['startTime']), "-i", media_file_path, "-t", str(duration), "-c", "copy", "-avoid_negative_ts", "1", segment_file]
|
||||
|
||||
result = run_command(cmd)
|
||||
result = run_command(cmd) # noqa
|
||||
|
||||
if os.path.exists(segment_file) and os.path.getsize(segment_file) > 0:
|
||||
if len(timestamps_list) > 1:
|
||||
@ -953,17 +947,9 @@ def trim_video_method(media_file_path, timestamps_list):
|
||||
with open(concat_list_path, "w") as f:
|
||||
for segment in segment_files:
|
||||
f.write(f"file '{segment}'\n")
|
||||
concat_cmd = [
|
||||
settings.FFMPEG_COMMAND,
|
||||
"-y",
|
||||
"-f", "concat",
|
||||
"-safe", "0",
|
||||
"-i", concat_list_path,
|
||||
"-c", "copy",
|
||||
output_file
|
||||
]
|
||||
concat_cmd = [settings.FFMPEG_COMMAND, "-y", "-f", "concat", "-safe", "0", "-i", concat_list_path, "-c", "copy", output_file]
|
||||
|
||||
concat_result = run_command(concat_cmd)
|
||||
concat_result = run_command(concat_cmd) # noqa
|
||||
|
||||
if not os.path.exists(output_file) or os.path.getsize(output_file) == 0:
|
||||
return False
|
||||
|
||||
@ -5,8 +5,8 @@ import itertools
|
||||
import logging
|
||||
import random
|
||||
import re
|
||||
from datetime import datetime
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
@ -448,25 +448,18 @@ def copy_video(original_media, copy_encodings=True, title_suffix="(Trimmed)"):
|
||||
listable=original_media.listable,
|
||||
add_date=timezone.now(),
|
||||
video_height=original_media.video_height,
|
||||
media_info=original_media.media_info
|
||||
media_info=original_media.media_info,
|
||||
)
|
||||
models.Media.objects.bulk_create([new_media])
|
||||
# avoids calling signals since signals will call media_init and we don't want that
|
||||
|
||||
|
||||
if copy_encodings:
|
||||
for encoding in original_media.encodings.filter(chunk=False, status="success"):
|
||||
if encoding.media_file:
|
||||
with open(encoding.media_file.path, "rb") as f:
|
||||
myfile = File(f)
|
||||
new_encoding = models.Encoding(
|
||||
media_file=myfile,
|
||||
media=new_media,
|
||||
profile=encoding.profile,
|
||||
status="success",
|
||||
progress=100,
|
||||
chunk=False,
|
||||
logs=f"Copied from encoding {encoding.id}"
|
||||
media_file=myfile, media=new_media, profile=encoding.profile, status="success", progress=100, chunk=False, logs=f"Copied from encoding {encoding.id}"
|
||||
)
|
||||
models.Encoding.objects.bulk_create([new_encoding])
|
||||
# avoids calling signals as this is still not ready
|
||||
@ -483,13 +476,11 @@ def copy_video(original_media, copy_encodings=True, title_suffix="(Trimmed)"):
|
||||
thumbnail_name = helpers.get_file_name(original_media.thumbnail.path)
|
||||
new_media.thumbnail.save(thumbnail_name, File(f))
|
||||
|
||||
|
||||
if original_media.poster:
|
||||
with open(original_media.poster.path, 'rb') as f:
|
||||
poster_name = helpers.get_file_name(original_media.poster.path)
|
||||
new_media.poster.save(poster_name, File(f))
|
||||
|
||||
|
||||
return new_media
|
||||
|
||||
|
||||
@ -510,13 +501,7 @@ def create_video_trim_request(media, data):
|
||||
elif data.get('saveAsCopy'):
|
||||
video_action = "save_new"
|
||||
|
||||
video_trim_request = models.VideoTrimRequest.objects.create(
|
||||
media=media,
|
||||
status="initial",
|
||||
video_action=video_action,
|
||||
media_trim_style='no_encoding',
|
||||
timestamps=data.get('segments', {})
|
||||
)
|
||||
video_trim_request = models.VideoTrimRequest.objects.create(media=media, status="initial", video_action=video_action, media_trim_style='no_encoding', timestamps=data.get('segments', {}))
|
||||
|
||||
return video_trim_request
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('files', '0007_alter_media_state_videochapterdata'),
|
||||
]
|
||||
|
||||
@ -84,7 +84,6 @@ ENCODE_EXTENSIONS_KEYS = [extension for extension, name in ENCODE_EXTENSIONS]
|
||||
ENCODE_RESOLUTIONS_KEYS = [resolution for resolution, name in ENCODE_RESOLUTIONS]
|
||||
|
||||
|
||||
|
||||
def generate_uid():
|
||||
return get_random_string(length=16)
|
||||
|
||||
@ -651,6 +650,7 @@ class Media(models.Model):
|
||||
|
||||
if encoding and encoding.status == "success" and encoding.profile.codec == "h264" and action == "add" and not encoding.chunk:
|
||||
from . import tasks
|
||||
|
||||
tasks.create_hls.delay(self.friendly_token)
|
||||
|
||||
# TODO: ideally would ensure this is run only at the end when the last encoding is done...
|
||||
@ -692,7 +692,6 @@ class Media(models.Model):
|
||||
# showing the original file
|
||||
return helpers.url_from_path(self.media_file.path)
|
||||
|
||||
|
||||
@property
|
||||
def trim_video_path(self):
|
||||
if self.media_type not in ["video"]:
|
||||
|
||||
@ -2,13 +2,11 @@ import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from celery import Task
|
||||
from celery import shared_task as task
|
||||
from celery.exceptions import SoftTimeLimitExceeded
|
||||
from celery.signals import task_revoked
|
||||
|
||||
# from celery.task.control import revoke
|
||||
@ -16,8 +14,9 @@ from celery.utils.log import get_task_logger
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.core.files import File
|
||||
from django.db.models import Q
|
||||
from django.db import DatabaseError
|
||||
from django.db.models import Q
|
||||
|
||||
from actions.models import USER_MEDIA_ACTIONS, MediaAction
|
||||
from users.models import User
|
||||
|
||||
@ -36,7 +35,13 @@ from .helpers import (
|
||||
run_command,
|
||||
trim_video_method,
|
||||
)
|
||||
from .methods import list_tasks, notify_users, pre_save_action, copy_video, kill_ffmpeg_process
|
||||
from .methods import (
|
||||
copy_video,
|
||||
kill_ffmpeg_process,
|
||||
list_tasks,
|
||||
notify_users,
|
||||
pre_save_action,
|
||||
)
|
||||
from .models import (
|
||||
Category,
|
||||
EncodeProfile,
|
||||
@ -45,7 +50,7 @@ from .models import (
|
||||
Rating,
|
||||
Tag,
|
||||
VideoChapterData,
|
||||
VideoTrimRequest
|
||||
VideoTrimRequest,
|
||||
)
|
||||
|
||||
logger = get_task_logger(__name__)
|
||||
@ -87,7 +92,6 @@ def handle_pending_running_encodings(media):
|
||||
return deleted
|
||||
|
||||
|
||||
|
||||
def pre_trim_video_actions(media):
|
||||
# the reason for this function is to perform tasks before trimming a video
|
||||
|
||||
@ -106,13 +110,7 @@ def pre_trim_video_actions(media):
|
||||
# are still not finished.
|
||||
|
||||
profiles = EncodeProfile.objects.filter(active=True, extension='mp4', resolution__lte=media.video_height)
|
||||
media_encodings = EncodeProfile.objects.filter(
|
||||
encoding__in=media.encodings.filter(
|
||||
status="success",
|
||||
chunk=False
|
||||
),
|
||||
extension='mp4'
|
||||
).distinct()
|
||||
media_encodings = EncodeProfile.objects.filter(encoding__in=media.encodings.filter(status="success", chunk=False), extension='mp4').distinct()
|
||||
|
||||
picked = []
|
||||
for profile in profiles:
|
||||
@ -121,7 +119,6 @@ def pre_trim_video_actions(media):
|
||||
else:
|
||||
picked.append(profile)
|
||||
|
||||
|
||||
if picked:
|
||||
# by calling encode will re-encode all. The logic is explained above...
|
||||
logger.info(f"Encoding media {media.friendly_token} will have to be performed for all profiles")
|
||||
@ -129,6 +126,7 @@ def pre_trim_video_actions(media):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@task(name="chunkize_media", bind=True, queue="short_tasks", soft_time_limit=60 * 30 * 4)
|
||||
def chunkize_media(self, friendly_token, profiles, force=True):
|
||||
"""Break media in chunks and start encoding tasks"""
|
||||
@ -417,7 +415,6 @@ def encode_media(
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
|
||||
try:
|
||||
# output is empty, fail message is on the exception
|
||||
output = e.message
|
||||
@ -496,11 +493,7 @@ def produce_sprite_from_video(friendly_token):
|
||||
with open(output_name, "rb") as f:
|
||||
myfile = File(f)
|
||||
# SOS: avoid race condition, since this runs for a long time and will replace any other media changes on the meanwhile!!!
|
||||
media.sprites.save(
|
||||
content=myfile,
|
||||
name=get_file_name(media.media_file.path) + "sprites.jpg",
|
||||
save=False
|
||||
)
|
||||
media.sprites.save(content=myfile, name=get_file_name(media.media_file.path) + "sprites.jpg", save=False)
|
||||
media.save(update_fields=["sprites"])
|
||||
|
||||
except Exception as e:
|
||||
@ -877,8 +870,6 @@ def task_sent_handler(sender=None, headers=None, body=None, **kwargs):
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
@task(name="remove_media_file", base=Task, queue="long_tasks")
|
||||
def remove_media_file(media_file=None):
|
||||
rm_file(media_file)
|
||||
@ -1006,9 +997,7 @@ def video_trim_task(self, trim_request_id):
|
||||
else:
|
||||
proceed_with_single_file = False
|
||||
|
||||
|
||||
if proceed_with_single_file:
|
||||
|
||||
if trim_request.video_action == "save_new" or trim_request.video_action == "create_segments" and len(timestamps_encodings) == 1:
|
||||
new_media = copy_video(original_media, copy_encodings=True)
|
||||
|
||||
@ -1042,16 +1031,10 @@ def video_trim_task(self, trim_request_id):
|
||||
# file on different times.
|
||||
target_media = copy_video(original_media, title_suffix=f"(Trimmed) {i}", copy_encodings=True)
|
||||
|
||||
video_trim_request = VideoTrimRequest.objects.create(
|
||||
media=target_media,
|
||||
status="running",
|
||||
video_action="create_segments",
|
||||
media_trim_style='no_encoding',
|
||||
timestamps=[timestamp]
|
||||
)
|
||||
video_trim_request = VideoTrimRequest.objects.create(media=target_media, status="running", video_action="create_segments", media_trim_style='no_encoding', timestamps=[timestamp]) # noqa
|
||||
|
||||
original_trim_result = trim_video_method(target_media.media_file.path, [timestamp])
|
||||
deleted_encodings = handle_pending_running_encodings(target_media)
|
||||
deleted_encodings = handle_pending_running_encodings(target_media) # noqa
|
||||
# the following could be un-necessary, read commend in pre_trim_video_actions to see why
|
||||
encodings = target_media.encodings.filter(status="success", profile__extension='mp4', chunk=False)
|
||||
for encoding in encodings:
|
||||
@ -1063,7 +1046,6 @@ def video_trim_task(self, trim_request_id):
|
||||
pre_trim_video_actions(target_media)
|
||||
post_trim_action.delay(target_media.friendly_token)
|
||||
|
||||
|
||||
# set as completed the initial trim_request
|
||||
trim_request.status = "success"
|
||||
trim_request.save(update_fields=["status"])
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
from . import helpers
|
||||
|
||||
from allauth.socialaccount.models import SocialApp
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
@ -38,6 +38,7 @@ from cms.version import VERSION
|
||||
from identity_providers.models import LoginOption
|
||||
from users.models import User
|
||||
|
||||
from . import helpers
|
||||
from .forms import (
|
||||
ContactForm,
|
||||
EditSubtitleForm,
|
||||
@ -393,10 +394,7 @@ def trim_video(request, friendly_token):
|
||||
if not (request.user == media.user or is_mediacms_editor(request.user)):
|
||||
return HttpResponseRedirect("/")
|
||||
|
||||
existing_requests = VideoTrimRequest.objects.filter(
|
||||
media=media,
|
||||
status__in=["initial", "running"]
|
||||
).exists()
|
||||
existing_requests = VideoTrimRequest.objects.filter(media=media, status__in=["initial", "running"]).exists()
|
||||
|
||||
if existing_requests:
|
||||
return JsonResponse({"success": False, "error": "A trim request is already in progress for this video"}, status=400)
|
||||
@ -407,7 +405,7 @@ def trim_video(request, friendly_token):
|
||||
video_trim_task.delay(video_trim_request.id)
|
||||
ret = {"success": True, "request_id": video_trim_request.id}
|
||||
return JsonResponse(ret, safe=False, status=200)
|
||||
except Exception as e:
|
||||
except Exception as e: # noqa
|
||||
ret = {"success": False, "error": "Incorrect request data"}
|
||||
return JsonResponse(ret, safe=False, status=400)
|
||||
|
||||
@ -435,12 +433,8 @@ def edit_video(request):
|
||||
messages.add_message(request, messages.INFO, "Video Trimmer is not enabled")
|
||||
return HttpResponseRedirect(media.get_absolute_url())
|
||||
|
||||
|
||||
# Check if there's a running trim request
|
||||
running_trim_request = VideoTrimRequest.objects.filter(
|
||||
media=media,
|
||||
status__in=["initial", "running"]
|
||||
).exists()
|
||||
running_trim_request = VideoTrimRequest.objects.filter(media=media, status__in=["initial", "running"]).exists()
|
||||
|
||||
if running_trim_request:
|
||||
messages.add_message(request, messages.INFO, "Video trim request is already running")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user