import os import uuid import subprocess import requests import tempfile import shutil import logging from contextlib import contextmanager import time # 导入 time 模块 @contextmanager def temp_directory(dir=None): temp_dir = tempfile.mkdtemp(dir=dir) try: yield temp_dir finally: pass def download_file(url, temp_dir): try: headers = { 'User-Agent': 'Mozilla/5.0', 'Accept': '*/*' } logging.info(f"开始从URL下载文件: {url}") response = requests.get(url, headers=headers, stream=True, timeout=30) response.raise_for_status() file_path = os.path.join(temp_dir, 'input_audio') with open(file_path, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): if chunk: f.write(chunk) file_size = os.path.getsize(file_path) if file_size < 1024: error_msg = f"下载的文件太小(仅{file_size}字节),可能无效" logging.error(error_msg) raise Exception(error_msg) logging.info(f"文件下载成功,保存到: {file_path} (大小: {file_size}字节)") return file_path except Exception as e: logging.error(f"从 {url} 下载文件时出错: {e}") raise def execute_sanjuuni(input_path, output_path, sanjuuni_args): try: cmd = ['lib/sanjuuni/sanjuuni.exe', '-i', input_path] + sanjuuni_args + ['-o', output_path] logging.info(f"执行Sanjuuni命令: {' '.join(cmd)}") result = subprocess.run( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, encoding='utf-8', errors='replace' ) if result.returncode != 0: error_msg = f"Sanjuuni处理失败,返回码: {result.returncode}, 错误: {result.stderr}" logging.error(error_msg) raise Exception(error_msg) logging.info("Sanjuuni处理成功完成") return True except Exception as e: logging.error(f"执行Sanjuuni时出错: {e}") raise def process_sanjuuni(data, file_registry, file_lock): try: temp_dir = tempfile.mkdtemp(dir='temp_files') logging.info(f"创建临时目录: {temp_dir}") input_url = data.get('input_url') sanjuuni_args = data.get('args', []) # 从请求数据中获取 args 参数 # 定义不允许的参数 disallowed_params = [ '-s', '--http=', '-w', '--websocket=', '-u', '--websocket-client=', '-T', '--streamed', '--disable-opencl', '-i', '--input=', '-o', '--output=', '-S', '--subtitles=' ] # 检查是否有不允许的参数 for arg in sanjuuni_args: for param in disallowed_params: if arg.startswith(param): error_msg = f"不允许使用参数: {arg}" logging.error(error_msg) raise ValueError(error_msg) subtitle = data.get('subtitle', '') output_format = data.get('output_format', 'lua') # 构建 sanjuuni 参数 if 'format' in data: sanjuuni_args.extend(['-f', data['format']]) if output_format == 'lua': sanjuuni_args.append('-l') elif output_format == 'nfp': sanjuuni_args.append('-n') elif output_format == 'raw': sanjuuni_args.append('-r') elif output_format == 'bimg': sanjuuni_args.append('-b') elif output_format == '32vid': sanjuuni_args.append('-3') else: raise ValueError(f"Unsupported output format: {output_format}") input_path = download_file(input_url, temp_dir) output_id = str(uuid.uuid4())[:8] output_filename = f"{output_id}.{output_format}" output_path = os.path.join(temp_dir, output_filename) execute_sanjuuni(input_path, output_path, sanjuuni_args) with file_lock: file_registry[output_id] = { 'path': os.path.abspath(output_path), 'filename': output_filename, 'last_access': time.time(), # 使用 time.time() 记录最后访问时间 'download_count': 0 } logging.info(f"已注册新文件ID: {output_id}, 路径: {output_path}") return { 'status': 'success', 'download_url': f"http://ffmpeg.liulikeji.cn/download/{output_id}/{output_filename}", 'file_id': output_id, 'temp_dir': temp_dir # 返回临时目录路径 } except Exception as e: logging.error(f"处理过程中出错: {e}") return {'error': str(e)}