file_util.py 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import os
  2. from pathlib import Path
  3. import cv2
  4. from PIL import Image
  5. from flask import current_app
  6. from moviepy import VideoFileClip
  7. from werkzeug.utils import secure_filename
  8. from app import Config
  9. # 读取文件类型配置
  10. ALLOWED_IMAGE_EXTENSIONS = Config.ALLOWED_IMAGE_EXTENSIONS
  11. ALLOWED_VIDEO_EXTENSIONS = Config.ALLOWED_VIDEO_EXTENSIONS
  12. def handle_file_upload(file, file_location):
  13. if not file:
  14. current_app.logger.warning(f"{file_location} 文件为空")
  15. return None
  16. folder = current_app.config[f'{file_location.upper()}_FOLDER'] # 动态获取文件夹配置
  17. # 确保文件夹存在
  18. os.makedirs(folder, exist_ok=True)
  19. # 保存文件
  20. filename = secure_filename(file.filename)
  21. file_path = os.path.join('static', file_location, filename) # 存储相对路径
  22. file.save(os.path.join(folder, filename)) # 存储文件
  23. current_app.logger.debug(f"{file_location} 文件已保存:{file_path}")
  24. return file_path
  25. def get_media_info(file_abs_path):
  26. file_type = Path(file_abs_path).suffix[1:].lower()
  27. file_size = os.path.getsize(file_abs_path) / 1024 # 文件大小(KB)
  28. resolution_width = resolution_height = 0 # 默认分辨率为 0
  29. frame_count = 1 # 默认是图片,帧数为 1
  30. if file_type in ALLOWED_IMAGE_EXTENSIONS: # 图片
  31. with Image.open(file_abs_path) as img:
  32. resolution_width, resolution_height = img.size
  33. frame_count = 1
  34. elif file_type in ALLOWED_VIDEO_EXTENSIONS: # 视频
  35. with VideoFileClip(file_abs_path) as video:
  36. resolution_width, resolution_height = video.size
  37. video = cv2.VideoCapture(file_abs_path)
  38. frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) # 获取视频的帧数
  39. video.release() # 释放视频文件
  40. else:
  41. current_app.logger.warning(f"获取媒体信息失败,不支持的文件类型:{file_type}")
  42. return file_size, resolution_width, resolution_height, frame_count
  43. def delete_file(file_abs_path):
  44. if os.path.exists(file_abs_path):
  45. os.remove(file_abs_path)
  46. current_app.logger.debug(f"文件已删除:{file_abs_path}")
  47. else:
  48. current_app.logger.warning(f"文件不存在,无法删除:{file_abs_path}")
  49. def unify_result_media_format(media, current_user):
  50. original_result_path = os.path.join('static', 'results', current_user.username, os.path.basename(media.media_path))
  51. # 根据文件类型更改扩展名
  52. if media.file_type in ALLOWED_VIDEO_EXTENSIONS: # 视频文件
  53. avi_result_path = os.path.splitext(original_result_path)[0] + '.avi'
  54. new_result_path = os.path.splitext(original_result_path)[0] + '.mp4' # 默认视频格式为 .mp4
  55. avi_abs_path = os.path.join(current_app.root_path, avi_result_path)
  56. new_abs_path = os.path.join(current_app.root_path, new_result_path)
  57. convert_avi_to_mp4(avi_abs_path, new_abs_path)
  58. elif media.file_type in ALLOWED_IMAGE_EXTENSIONS: # 图片文件
  59. new_result_path = os.path.splitext(original_result_path)[0] + '.jpg' # 默认图片格式为 .jpg
  60. else:
  61. new_result_path = original_result_path
  62. return new_result_path
  63. def convert_avi_to_mp4(avi_path, mp4_path):
  64. # 使用 moviepy 读取 avi 文件
  65. video_clip = VideoFileClip(avi_path)
  66. # 写入 mp4 格式
  67. video_clip.write_videofile(mp4_path, codec="libx264")
  68. # 显式释放资源
  69. video_clip.close()
  70. # 删除原 avi 文件
  71. os.remove(avi_path)