Migrate clip/convert to V3 actions; add background clip support, redirect legacy route; update frontend guide
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import aiofiles, datetime, hashlib, mimetypes, os, pathlib, random, shutil, subprocess, shlex, tempfile, time
|
||||
from fastapi import APIRouter, Body, Depends, File, Form, Header, HTTPException, Path, Query, Response, status, UploadFile
|
||||
from fastapi.responses import FileResponse, StreamingResponse
|
||||
from fastapi.responses import FileResponse, StreamingResponse, RedirectResponse
|
||||
from urllib.parse import quote
|
||||
from pydantic import BaseModel, EmailStr, Field
|
||||
from typing import Dict, List, Optional, Set, Union
|
||||
|
||||
@@ -9,9 +10,9 @@ from app.config import settings
|
||||
from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, redis_lookup_id_random
|
||||
|
||||
from app.methods.hosted_file_methods import (
|
||||
create_hosted_file_obj, handle_delete_hosted_file, load_hosted_file_obj,
|
||||
save_file, save_file_to_hosted_file, create_hosted_file_link,
|
||||
delete_hosted_file_link, get_hosted_file_link_rec_list, lookup_file_hash,
|
||||
create_hosted_file_obj, handle_delete_hosted_file, load_hosted_file_obj,
|
||||
save_file, save_file_to_hosted_file, create_hosted_file_link,
|
||||
delete_hosted_file_link, get_hosted_file_link_rec_list, lookup_file_hash,
|
||||
check_for_hosted_file_hash_file, directory_check_method
|
||||
)
|
||||
from app.methods.lib_media import clip_video_method, convert_file_method
|
||||
@@ -35,10 +36,10 @@ async def directory_check(
|
||||
"""
|
||||
log.setLevel(logging.INFO)
|
||||
result_list = directory_check_method(rm_orphan=rm_orphan)
|
||||
|
||||
|
||||
if result_list is False:
|
||||
return mk_resp(data=False, status_code=500, response=commons.response, status_message='Hosted files directory not found.')
|
||||
|
||||
|
||||
return mk_resp(data=result_list, response=commons.response, status_message=f'Processed {len(result_list)} files.')
|
||||
# ### END ### API Hosted File ### directory_check() ###
|
||||
|
||||
@@ -52,7 +53,7 @@ async def download_hosted_file(
|
||||
commons: Common_Route_Params = Depends(common_route_params),
|
||||
):
|
||||
log.setLevel(logging.INFO)
|
||||
|
||||
|
||||
# ID Resolve
|
||||
if hfid_int := redis_lookup_id_random(record_id_random=hosted_file_id, table_name='hosted_file'): pass
|
||||
else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The hosted_file ID was invalid or not found.')
|
||||
@@ -63,7 +64,7 @@ async def download_hosted_file(
|
||||
|
||||
target_filename = filename or hosted_file_obj.filename
|
||||
hash_sha256 = hosted_file_obj.hash_sha256
|
||||
|
||||
|
||||
hosted_files_path = settings.FILES_PATH['hosted_files_root']
|
||||
subdir = hosted_file_obj.subdirectory_path or ''
|
||||
file_path = os.path.join(hosted_files_path, subdir, f'{hash_sha256}.file')
|
||||
@@ -151,7 +152,7 @@ async def upload_files(
|
||||
Legacy Upload Route (V2). Preserved for frontend compatibility.
|
||||
"""
|
||||
log.setLevel(logging.INFO)
|
||||
|
||||
|
||||
acc_id_rand = account_id
|
||||
if acc_id_int := redis_lookup_id_random(record_id_random=acc_id_rand, table_name='account'): pass
|
||||
else: return mk_resp(data=None, status_code=400, response=response)
|
||||
@@ -192,7 +193,7 @@ async def upload_files(
|
||||
|
||||
# Final metadata and linking
|
||||
hosted_file_dict.update({'saved': True, 'already_exists': file_info['already_exists'], 'copy_timer': file_info['copy_timer']})
|
||||
|
||||
|
||||
if link_to_type not in ['event', 'event_location', 'event_session', 'event_presentation', 'event_presenter', 'event_badge', 'event_exhibit', 'event_person']:
|
||||
create_hosted_file_link(account_id=acc_id_int, hosted_file_id=hfid_int, link_to_type=link_to_type, link_to_id=lid_int)
|
||||
|
||||
@@ -301,21 +302,23 @@ async def clip_video(
|
||||
"""
|
||||
Modularized video clipping route.
|
||||
"""
|
||||
if lid_int := redis_lookup_id_random(record_id_random=link_to_id, table_name=link_to_type):
|
||||
result = await clip_video_method(
|
||||
hosted_file_id = hosted_file_id,
|
||||
start_time = start_time,
|
||||
end_time = end_time,
|
||||
account_id = commons.x_account_id,
|
||||
account_id_random = commons.x_account_id_random,
|
||||
link_to_type = link_to_type,
|
||||
link_to_id = lid_int,
|
||||
filename_no_ext = filename_no_ext,
|
||||
reencode = reencode,
|
||||
scale_down = scale_down
|
||||
)
|
||||
if result: return mk_resp(data=result, response=commons.response)
|
||||
return mk_resp(data=None, status_code=400, response=commons.response)
|
||||
# Deprecated legacy route — redirect clients to the V3 action endpoint
|
||||
# New V3 action: /v3/action/hosted_file/{hosted_file_id}/clip_video
|
||||
params = [
|
||||
f"link_to_type={quote(link_to_type)}",
|
||||
f"link_to_id={quote(link_to_id)}",
|
||||
f"start_time={quote(start_time)}",
|
||||
f"end_time={quote(end_time)}",
|
||||
]
|
||||
if filename_no_ext:
|
||||
params.append(f"filename_no_ext={quote(filename_no_ext)}")
|
||||
if reencode:
|
||||
params.append(f"reencode=true")
|
||||
if scale_down:
|
||||
params.append(f"scale_down=true")
|
||||
|
||||
target = f"/v3/action/hosted_file/{hosted_file_id}/clip_video?" + "&".join(params)
|
||||
return RedirectResponse(url=target, status_code=307)
|
||||
# ### END ### API Hosted File ### clip_video() ###
|
||||
|
||||
|
||||
@@ -332,7 +335,7 @@ async def create_video(
|
||||
# Specialized utility route kept inline for now.
|
||||
from wand.image import Image
|
||||
from wand.drawing import Drawing
|
||||
|
||||
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix='.mp3') as audio_file:
|
||||
audio_file.write(await file.read())
|
||||
audio_file_path = audio_file.name
|
||||
@@ -359,5 +362,5 @@ async def create_video(
|
||||
video_name = f"{tempfile.gettempdir()}/{title_part_1}.mp4"
|
||||
cmd = f"ffmpeg -y -loop 1 -i {title_image_path} -i {audio_file_path} -c:a copy -c:v libx264 -shortest {video_name}"
|
||||
subprocess.run(shlex.split(cmd), check=True)
|
||||
|
||||
|
||||
return FileResponse(video_name, media_type='video/mp4', filename=f'{title_part_1}.mp4')
|
||||
|
||||
Reference in New Issue
Block a user