CronCloudPhotoController.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. # -*- encoding: utf-8 -*-
  2. """
  3. @File : CronCloudPhotoController.py
  4. @Time : 2022/10/24 15:48
  5. @Author : stephen
  6. @Email : zhangdongming@asj6.wecom.work
  7. @Software: PyCharm
  8. """
  9. import datetime
  10. import logging
  11. import os
  12. import time
  13. import traceback
  14. import cv2
  15. from django.db import transaction
  16. from django.views import View
  17. from Ansjer.config import PUSH_CLOUD_PHOTO, ACCESS_KEY_ID, SECRET_ACCESS_KEY, REGION_NAME, PUSH_BUCKET
  18. from Model.models import UidSetModel, DeviceCloudPhotoInfo, DevicePicturePushInfo
  19. from Object.AWS.AmazonS3Util import AmazonS3Util
  20. from Object.RedisObject import RedisObject
  21. from Object.ResponseObject import ResponseObject
  22. from Object.utils import LocalDateTimeUtil
  23. from Service.EquipmentInfoService import EquipmentInfoService
  24. LOGGER = logging.getLogger('info')
  25. UID_KEY = 'ANSJER:UID:SET:INFO'
  26. class CronCloudPhotoView(View):
  27. def get(self, request, *args, **kwargs):
  28. request.encoding = 'utf-8'
  29. operation = kwargs.get('operation')
  30. return self.validation(request.GET, request, operation)
  31. def post(self, request, *args, **kwargs):
  32. request.encoding = 'utf-8'
  33. operation = kwargs.get('operation')
  34. return self.validation(request.POST, request, operation)
  35. def validation(self, request_dict, request, operation):
  36. response = ResponseObject()
  37. if operation == 'cache-uid-set':
  38. return self.cache_photo_uid_set(response)
  39. elif operation == 'generate-video':
  40. return self.generate_video(response)
  41. else:
  42. return response.json(404)
  43. @classmethod
  44. def cache_photo_uid_set(cls, response):
  45. """
  46. 缓存uid_set信息
  47. """
  48. try:
  49. now_time = int(time.time())
  50. LOGGER.info('进入读取开启云相册用户并把UID存在redis:{}'.format(now_time))
  51. photo_qs = DeviceCloudPhotoInfo.objects.filter(status=1).values('uid')
  52. if not photo_qs.exists():
  53. return response.json(0)
  54. redis = RedisObject()
  55. for item in photo_qs:
  56. uid_set_qs = UidSetModel.objects.filter(uid=item['uid'], detect_status=1)
  57. if not uid_set_qs:
  58. continue
  59. redis.CONN.rpush(UID_KEY, item['uid'])
  60. return response.json(0)
  61. except Exception as e:
  62. print(e)
  63. LOGGER.info('--->获取uid_set信息异常:{}'.format(traceback.format_exc()))
  64. return response.json(177, repr(e))
  65. @classmethod
  66. def generate_video(cls, response):
  67. """
  68. 生成视频并存库
  69. """
  70. try:
  71. now_time = int(time.time())
  72. LOGGER.info('进入云相册开启用户,进行消息推送图进行合成视频:{}'.format(now_time))
  73. photo_qs = DeviceCloudPhotoInfo.objects.filter(status=1).values('uid', 'user_id')
  74. if not photo_qs.exists():
  75. return response.json(0)
  76. # 获取当前项目路径
  77. poj_path = os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
  78. time_stamp = cls.get_month_stamp()
  79. s3 = AmazonS3Util(ACCESS_KEY_ID, SECRET_ACCESS_KEY, REGION_NAME)
  80. for item in photo_qs:
  81. try:
  82. with transaction.atomic():
  83. last_date = LocalDateTimeUtil.get_cur_month_end()
  84. start_time, end_time = LocalDateTimeUtil.get_start_and_end_time(last_date, '%Y-%m-%d')
  85. picture_qs = DevicePicturePushInfo.objects.filter(uid=item['uid'],
  86. event_time__gt=time_stamp,
  87. event_time__lt=end_time,
  88. type=0) \
  89. .values('uid', 'channel', 'event_time', 'device_nick_name')
  90. if not picture_qs.exists():
  91. continue
  92. device_nickname = picture_qs[0]['device_nick_name']
  93. pic_list = cls.download_push_picture(s3, item['uid'], poj_path, picture_qs)
  94. video_path = poj_path + r'\Ansjer\file\video.mp4' # 输出视频的保存路径
  95. cls.picture_synthesis_video(video_path, poj_path, pic_list) # 图片合成视频
  96. video_name = datetime.datetime.now().strftime('%Y%m')
  97. data = open(video_path, 'rb')
  98. key = '{}/video/{}.mp4'.format(item['uid'], video_name)
  99. s3.upload_file_obj(PUSH_CLOUD_PHOTO, key, data) # 将视频资源上传至S3保存
  100. os.remove(video_path) # 上传完成删除本地资源
  101. push_data = {'type': 1, 'uid': item['uid'], 'channel': 1,
  102. 'event_time': int(video_name), 'updated_time': now_time, 'created_time': now_time,
  103. 'device_nick_name': device_nickname, 'user_id': item['user_id']}
  104. DevicePicturePushInfo.objects.create(**push_data)
  105. except Exception as e:
  106. LOGGER.info('异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  107. continue
  108. return response.json(0)
  109. except Exception as e:
  110. print(e)
  111. LOGGER.info('--->图片合成视频异常:{}'.format(traceback.format_exc()))
  112. return response.json(177)
  113. @staticmethod
  114. def download_push_picture(s3, uid, dir_url, picture_qs):
  115. """
  116. 下载推送图片,讲下载资源保存到项目本地
  117. @param s3: s3对象
  118. @param uid: 设备uid
  119. @param dir_url: 项目文件路径
  120. @param picture_qs: 消息推送图片对象
  121. @return: pic_list 图片文件名集合
  122. """
  123. pic_list = []
  124. for pic in picture_qs:
  125. path = dir_url + r'\Ansjer\file\{}.jpeg'.format(pic['event_time'])
  126. s3_key = '{}/{}/{}.jpeg'.format(uid, pic['channel'], pic['event_time'])
  127. s3.download_object(PUSH_CLOUD_PHOTO, s3_key, path)
  128. pic_list.append('{}.jpeg'.format(pic['event_time']))
  129. return pic_list
  130. @staticmethod
  131. def picture_synthesis_video(video_path, poj_path, pic_list):
  132. """
  133. 图片合成视频
  134. @param video_path: 输出视频的保存路径
  135. @param poj_path: 项目路径
  136. @param pic_list: 图片文件名集合
  137. @return:
  138. """
  139. if not pic_list:
  140. raise Exception('this pic_list is null.')
  141. fps = 1 # 帧率
  142. img_path = poj_path + r'\Ansjer\file\{}'.format(pic_list[0])
  143. image = cv2.imread(img_path)
  144. size = image.shape
  145. w = size[1] # 宽度
  146. h = size[0] # 高度
  147. img_size = (w, h) # 图片尺寸
  148. fourcc = cv2.VideoWriter_fourcc(*"mp4v")
  149. video_writer = cv2.VideoWriter(video_path, fourcc, fps, img_size)
  150. for item in pic_list:
  151. img_path = poj_path + r'\Ansjer\file\{}'.format(item)
  152. frame = cv2.imread(img_path)
  153. if frame is None:
  154. continue
  155. frame = cv2.resize(frame, img_size) # 生成视频 图片尺寸和设定尺寸相同
  156. video_writer.write(frame) # 将图片写进视频里
  157. os.remove(img_path)
  158. video_writer.release() # 释放资源
  159. @staticmethod
  160. def get_month_stamp():
  161. """
  162. 获取当月开始时间戳
  163. """
  164. now_month = LocalDateTimeUtil.get_cur_month_start()
  165. start_time = "{} 00:00:00".format(str(now_month))
  166. time_array = time.strptime(start_time, "%Y-%m-%d %H:%M:%S")
  167. # 转换为时间戳
  168. return int(time.mktime(time_array))