mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-07 07:58:53 -05:00
tass
This commit is contained in:
parent
f5176d12d7
commit
9b8c860b46
@ -36,7 +36,7 @@ from .helpers import (
|
|||||||
run_command,
|
run_command,
|
||||||
trim_video_method,
|
trim_video_method,
|
||||||
)
|
)
|
||||||
from .methods import list_tasks, notify_users, pre_save_action, copy_video
|
from .methods import list_tasks, notify_users, pre_save_action, copy_video, kill_ffmpeg_process
|
||||||
from .models import (
|
from .models import (
|
||||||
Category,
|
Category,
|
||||||
EncodeProfile,
|
EncodeProfile,
|
||||||
@ -59,6 +59,32 @@ ERRORS_LIST = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def handle_pending_running_encodings(media):
|
||||||
|
"""Handle pending and running encodings for a media object.
|
||||||
|
|
||||||
|
we are trimming the original file. If there are encodings in success, this means that the encoding has run
|
||||||
|
and has succeeded, so we can keep them (they will be trimmed). However for encodings that are in pending
|
||||||
|
or running phase,
|
||||||
|
|
||||||
|
Args:
|
||||||
|
media: The media object to handle encodings for
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if any encodings were deleted, False otherwise
|
||||||
|
"""
|
||||||
|
encodings = media.encodings.filter(status__in=["pending", "running"])
|
||||||
|
deleted = False
|
||||||
|
for encoding in encodings:
|
||||||
|
if encoding.temp_file:
|
||||||
|
kill_ffmpeg_process(encoding.temp_file)
|
||||||
|
if encoding.chunk_file_path:
|
||||||
|
kill_ffmpeg_process(encoding.chunk_file_path)
|
||||||
|
deleted = True
|
||||||
|
encoding.delete()
|
||||||
|
|
||||||
|
return deleted
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@task(name="chunkize_media", bind=True, queue="short_tasks", soft_time_limit=60 * 30 * 4)
|
@task(name="chunkize_media", bind=True, queue="short_tasks", soft_time_limit=60 * 30 * 4)
|
||||||
def chunkize_media(self, friendly_token, profiles, force=True):
|
def chunkize_media(self, friendly_token, profiles, force=True):
|
||||||
@ -326,8 +352,8 @@ def encode_media(
|
|||||||
try:
|
try:
|
||||||
encoding.save(update_fields=["progress", "update_date"])
|
encoding.save(update_fields=["progress", "update_date"])
|
||||||
logger.info("Saved {0}".format(round(percent, 2)))
|
logger.info("Saved {0}".format(round(percent, 2)))
|
||||||
except BaseException:
|
except Exception as e:
|
||||||
pass
|
raise
|
||||||
n_times += 1
|
n_times += 1
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
break
|
break
|
||||||
@ -340,8 +366,7 @@ def encode_media(
|
|||||||
output = e.message
|
output = e.message
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
output = ""
|
output = ""
|
||||||
if isinstance(e, SoftTimeLimitExceeded):
|
kill_ffmpeg_process(encoding.temp_file)
|
||||||
kill_ffmpeg_process(encoding.temp_file)
|
|
||||||
encoding.logs = output
|
encoding.logs = output
|
||||||
encoding.status = "fail"
|
encoding.status = "fail"
|
||||||
encoding.save(update_fields=["status", "logs"])
|
encoding.save(update_fields=["status", "logs"])
|
||||||
@ -426,7 +451,6 @@ def produce_sprite_from_video(friendly_token):
|
|||||||
def create_hls(friendly_token):
|
def create_hls(friendly_token):
|
||||||
"""Creates HLS file for media, uses Bento4 mp4hls command"""
|
"""Creates HLS file for media, uses Bento4 mp4hls command"""
|
||||||
|
|
||||||
logger.info(f"Entering for {friendly_token}")
|
|
||||||
if not hasattr(settings, "MP4HLS_COMMAND"):
|
if not hasattr(settings, "MP4HLS_COMMAND"):
|
||||||
logger.info("Bento4 mp4hls command is missing from configuration")
|
logger.info("Bento4 mp4hls command is missing from configuration")
|
||||||
return False
|
return False
|
||||||
@ -794,15 +818,6 @@ def task_sent_handler(sender=None, headers=None, body=None, **kwargs):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def kill_ffmpeg_process(filepath):
|
|
||||||
# this is not ideal, ffmpeg pid could be linked to the Encoding object
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
@task(name="remove_media_file", base=Task, queue="long_tasks")
|
@task(name="remove_media_file", base=Task, queue="long_tasks")
|
||||||
@ -878,6 +893,8 @@ def post_trim_action(friendly_token):
|
|||||||
media.set_media_type()
|
media.set_media_type()
|
||||||
encodings = media.encodings.filter(status="success", profile__extension='mp4', chunk=False)
|
encodings = media.encodings.filter(status="success", profile__extension='mp4', chunk=False)
|
||||||
for encoding in encodings:
|
for encoding in encodings:
|
||||||
|
# update encoding size, in case they don't have one, due to the
|
||||||
|
# way the copy_video took place
|
||||||
update_encoding_size(encoding.id)
|
update_encoding_size(encoding.id)
|
||||||
|
|
||||||
media.produce_thumbnails_from_video()
|
media.produce_thumbnails_from_video()
|
||||||
@ -933,17 +950,23 @@ def video_trim_task(self, trim_request_id):
|
|||||||
# processing timestamps differently on encodings and original file, since they have different I-frames
|
# processing timestamps differently on encodings and original file, since they have different I-frames
|
||||||
# the cut is made based on the I-frames
|
# the cut is made based on the I-frames
|
||||||
|
|
||||||
|
original_trim_result = trim_video_method(target_media.media_file.path, timestamps_original)
|
||||||
|
if not original_trim_result:
|
||||||
|
logger.info(f"Failed to trim original file for media {target_media.friendly_token}")
|
||||||
|
|
||||||
encodings = target_media.encodings.filter(status="success", profile__extension='mp4', chunk=False)
|
encodings = target_media.encodings.filter(status="success", profile__extension='mp4', chunk=False)
|
||||||
for encoding in encodings:
|
for encoding in encodings:
|
||||||
trim_result = trim_video_method(encoding.media_file.path, timestamps_encodings)
|
trim_result = trim_video_method(encoding.media_file.path, timestamps_encodings)
|
||||||
if not trim_result:
|
if not trim_result:
|
||||||
logger.info(f"Failed to trim encoding {encoding.id} for media {target_media.friendly_token}")
|
logger.info(f"Failed to trim encoding {encoding.id} for media {target_media.friendly_token}")
|
||||||
|
encoding.delete()
|
||||||
|
|
||||||
original_trim_result = trim_video_method(target_media.media_file.path, timestamps_original)
|
deleted_encodings = handle_pending_running_encodings(target_media)
|
||||||
if not original_trim_result:
|
if deleted_encodings:
|
||||||
logger.info(f"Failed to trim original file for media {target_media.friendly_token}")
|
# give the chance to run encodings for encodings that didnt make it
|
||||||
|
target_media.encode(force=False)
|
||||||
|
# TODO: find way to call post_trim_action only after this has finished...
|
||||||
|
|
||||||
# Schedule post-processing
|
|
||||||
post_trim_action.delay(target_media.friendly_token)
|
post_trim_action.delay(target_media.friendly_token)
|
||||||
|
|
||||||
trim_request.status = "success"
|
trim_request.status = "success"
|
||||||
@ -952,19 +975,30 @@ def video_trim_task(self, trim_request_id):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
for i, timestamp in enumerate(timestamps_encodings, start=1):
|
for i, timestamp in enumerate(timestamps_encodings, start=1):
|
||||||
new_media = copy_video(original_media, title_suffix=f"(Trimmed) {i}", copy_encodings=True)
|
# copy the original file for each of the segments. This could be optimized to avoid the overhead but
|
||||||
|
# for now is necessary because the ffmpeg trim command will be run towards the original
|
||||||
|
# file on different times.
|
||||||
|
target_media = copy_video(original_media, title_suffix=f"(Trimmed) {i}", copy_encodings=True)
|
||||||
|
|
||||||
original_trim_result = trim_video_method(new_media.media_file.path, [timestamp])
|
original_trim_result = trim_video_method(target_media.media_file.path, [timestamp])
|
||||||
encodings = new_media.encodings.filter(status="success", profile__extension='mp4', chunk=False)
|
encodings = target_media.encodings.filter(status="success", profile__extension='mp4', chunk=False)
|
||||||
for encoding in encodings:
|
for encoding in encodings:
|
||||||
trim_result = trim_video_method(encoding.media_file.path, [timestamp])
|
trim_result = trim_video_method(encoding.media_file.path, [timestamp])
|
||||||
|
if not trim_result:
|
||||||
|
logger.info(f"Failed to trim encoding {encoding.id} for media {target_media.friendly_token}")
|
||||||
|
encoding.delete()
|
||||||
|
|
||||||
# Schedule post-processing
|
deleted_encodings = handle_pending_running_encodings(target_media)
|
||||||
post_trim_action.delay(new_media.friendly_token)
|
if deleted_encodings:
|
||||||
|
# give the chance to run encodings for encodings that didnt make it
|
||||||
|
target_media.encode(force=False)
|
||||||
|
# TODO: find way to call post_trim_action only after this has finished...
|
||||||
|
|
||||||
|
post_trim_action.delay(target_media.friendly_token)
|
||||||
|
|
||||||
trim_request.status = "success"
|
trim_request.status = "success"
|
||||||
trim_request.save(update_fields=["status"])
|
trim_request.save(update_fields=["status"])
|
||||||
logger.info(f"Successfully processed video trim request {trim_request_id} for media {target_media.friendly_token}")
|
logger.info(f"Successfully processed video trim request {trim_request_id} for media {original_media.friendly_token}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user