添加视频切片功能

This commit is contained in:
nnwang
2026-01-09 21:40:03 +08:00
parent 408fcd3f1b
commit cad3a033a3
7 changed files with 156248 additions and 22 deletions

92
main.py
View File

@@ -15,6 +15,7 @@ app = Flask(__name__)
try:
from ffmpeg_utils import process_ffmpeg
from sanjuuni_utils import process_sanjuuni
from video_frame_utils import process_video_frame_extraction
from file_cleanup import start_cleanup_thread
except ImportError as e:
logging.error(f"导入模块时出错: {e}")
@@ -23,6 +24,8 @@ except ImportError as e:
return {'error': 'FFmpeg模块未正确导入'}
def process_sanjuuni(*args, **kwargs):
return {'error': 'Sanjuuni模块未正确导入'}
def process_video_frame_extraction(*args, **kwargs):
return {'error': '视频帧提取模块未正确导入'}
def start_cleanup_thread():
pass
@@ -37,6 +40,14 @@ enter_parameter_table = {
"input_url": str,
"output_format": str,
"args": list
},
"video_frame": {
"video_url": str,
"w": int,
"h": int,
"fps": int,
"force_resolution": bool,
"pad_to_target": bool
}
}
@@ -140,11 +151,11 @@ def sanjuuni_async_api():
# 生成任务ID
task_id = str(uuid.uuid4())[:8]
# 获取请求的主机信息用于构建URL
host = request.host
scheme = request.scheme
# 初始化任务状态
with task_lock:
task_registry[task_id] = {
@@ -155,7 +166,7 @@ def sanjuuni_async_api():
'last_returned_index': 0, # 记录最后返回的日志索引
'progress': 0
}
# 启动异步任务
thread = threading.Thread(
target=run_async_task,
@@ -163,9 +174,9 @@ def sanjuuni_async_api():
)
thread.daemon = True
thread.start()
status_url = f"{scheme}://{host}/api/task/{task_id}"
logging.info(f"创建异步Sanjuuni任务: {task_id}")
return jsonify({
'status': 'success',
@@ -174,6 +185,53 @@ def sanjuuni_async_api():
'message': '任务已创建请使用状态URL查询进度'
}), 202
@app.route('/api/video_frame/async', methods=['POST'])
def video_frame_async_api():
"""创建异步视频帧提取任务"""
logging.info("收到异步视频帧提取API请求")
data = request.get_json()
# 检测参数类型
error_response, status_code = validate_request(data, "video_frame")
if error_response:
return error_response, status_code
# 生成任务ID
task_id = str(uuid.uuid4())[:8]
# 获取请求的主机信息用于构建URL
host = request.host
scheme = request.scheme
# 初始化任务状态
with task_lock:
task_registry[task_id] = {
'status': 'pending',
'type': 'video_frame',
'create_time': time.time(),
'logs': [],
'last_returned_index': 0, # 记录最后返回的日志索引
'progress': 0
}
# 启动异步任务
thread = threading.Thread(
target=run_async_task,
args=(task_id, process_video_frame_extraction, data)
)
thread.daemon = True
thread.start()
status_url = f"{scheme}://{host}/api/task/{task_id}"
logging.info(f"创建异步视频帧提取任务: {task_id}")
return jsonify({
'status': 'success',
'task_id': task_id,
'status_url': status_url,
'message': '任务已创建请使用状态URL查询进度'
}), 202
@app.route('/api/task/<task_id>', methods=['GET'])
def get_task_status(task_id):
"""查询任务状态和进度(自动返回新增日志)"""
@@ -307,6 +365,30 @@ def download_file_endpoint(file_id, filename):
logging.error(f"下载文件时出错: {e}")
return jsonify({'status': 'error', 'error': str(e)}), 500
@app.route('/frames/<job_id>/<filename>', methods=['GET'])
def serve_video_frames(job_id, filename):
"""提供视频帧和音频文件访问"""
import os
from flask import send_from_directory
from video_frame_utils import FRAMES_ROOT
safe_job = os.path.basename(job_id)
safe_file = os.path.basename(filename)
dir_path = os.path.join(FRAMES_ROOT, safe_job)
if not os.path.isdir(dir_path):
return jsonify({"error": "文件不存在"}), 404
allowed = safe_file.endswith(('.png', '.dfpwm'))
if not allowed:
return jsonify({"error": "文件类型不支持"}), 400
try:
return send_from_directory(dir_path, safe_file)
except Exception as e:
logging.error(f"提供文件时出错: {e}")
return jsonify({"error": "文件访问失败"}), 500
@app.route('/health', methods=['GET'])
def health_check():
"""健康检查接口,直接返回 'ok'"""