Add ability to generate thumbnails

This commit is contained in:
Brett Williams
2022-12-11 17:52:56 -08:00
parent 9f291a1282
commit d945d51e56
5 changed files with 81 additions and 18 deletions

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python3
import json
import logging
import os
@@ -16,7 +15,7 @@ from werkzeug.utils import secure_filename
from lib.render_job import RenderJob
from lib.render_queue import RenderQueue
from lib.server_helper import post_job_to_server
from lib.server_helper import post_job_to_server, generate_thumbnail_for_job
from utilities.render_worker import RenderWorkerFactory, string_to_status, RenderStatus
logger = logging.getLogger()
@@ -64,6 +63,25 @@ def job_detail(job_id):
return f'Cannot find job with ID {job_id}', 400
@server.route('/ui/job/<job_id>/thumbnail')
def job_thumbnail(job_id):
found_job = RenderQueue.job_with_id(job_id)
if found_job:
os.makedirs(server.config['THUMBS_FOLDER'], exist_ok=True)
thumb_video_path = os.path.join(server.config['THUMBS_FOLDER'], found_job.id + '.mp4')
thumb_image_path = os.path.join(server.config['THUMBS_FOLDER'], found_job.id + '.jpg')
if not os.path.exists(thumb_video_path) and not os.path.exists(thumb_video_path + '_IN-PROGRESS'):
generate_thumbnail_for_job(found_job, thumb_video_path, thumb_image_path, max_width=120)
if os.path.exists(thumb_video_path) and not os.path.exists(thumb_video_path + '_IN-PROGRESS'):
return send_file(thumb_video_path, mimetype="video/mp4")
elif os.path.exists(thumb_image_path):
return send_file(thumb_image_path, mimetype='image/jpeg')
return send_file('static/spinner.gif', mimetype="image/gif")
# Get job file routing
@server.route('/api/job/<job_id>/file/<filename>', methods=['GET'])
def get_job_file(job_id, filename):
@@ -125,7 +143,6 @@ def get_file_list(job_id):
@server.route('/api/job/<job_id>/download_all')
def download_all(job_id):
zip_filename = None
@after_this_request
@@ -206,7 +223,6 @@ def snapshot():
@server.post('/api/add_job')
def add_job_handler():
try:
"""Create new job and add to server render queue"""
if request.is_json:
@@ -381,6 +397,15 @@ def delete_job(job_id):
if server.config['UPLOAD_FOLDER'] in output_dir and os.path.exists(output_dir):
shutil.rmtree(output_dir)
# Remove any thumbnails
for filename in os.listdir(server.config['THUMBS_FOLDER']):
if job_id in filename:
os.remove(os.path.join(server.config['THUMBS_FOLDER'], filename))
thumb_path = os.path.join(server.config['THUMBS_FOLDER'], found_job.id + '.mp4')
if os.path.exists(thumb_path):
os.remove(thumb_path)
# See if we own the input file (i.e. was it uploaded)
input_dir = os.path.dirname(found_job.worker.input_path)
if server.config['UPLOAD_FOLDER'] in input_dir and os.path.exists(input_dir):

View File

@@ -1,6 +1,10 @@
import subprocess
import requests
import os
import json
import threading
from utilities.render_worker import RenderStatus
from utilities.ffmpeg_presets import generate_fast_preview, save_first_frame
def post_job_to_server(input_path, job_list, client, server_port=8080):
@@ -10,3 +14,29 @@ def post_job_to_server(input_path, job_list, client, server_port=8080):
req = requests.post(f'http://{client}:{server_port}/api/add_job', files=job_files)
return req
def generate_thumbnail_for_job(job, thumb_video_path, thumb_image_path, max_width=320):
# Simple thread to generate thumbs in background
def generate_thumb_thread(source):
in_progress_path = thumb_video_path + '_IN-PROGRESS'
subprocess.run(['touch', in_progress_path])
generate_fast_preview(source_path=source, dest_path=thumb_video_path, max_width=max_width)
os.remove(in_progress_path)
# Determine best source file to use for thumbs
if job.render_status() == RenderStatus.COMPLETED: # use finished file for thumb
source_path = job.file_list()
elif len(job.file_list()) > 1: # if image sequence, use second to last file (last may be in use)
source_path = [job.file_list()[-2]]
else:
source_path = [job.worker.input_path] # use source if nothing else
# Todo: convert image sequence to animated movie
valid_formats = ['.mp4', '.mov', '.avi', '.mpg', '.mpeg', '.jpg', '.png', '.exr', '.mxf']
is_valid_file_type = any(ele in source_path[0] for ele in valid_formats)
if is_valid_file_type and not os.path.exists(thumb_video_path):
save_first_frame(source_path=source_path[0], dest_path=thumb_image_path, max_width=max_width)
x = threading.Thread(target=generate_thumb_thread, args=(source_path[0],))
x.start()