generativeai_video.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import asyncio
  2. import os
  3. import time
  4. import cv2
  5. import aiohttp
  6. import requests
  7. import google.generativeai as genai
  8. import uuid
  9. from google.generativeai.types import HarmCategory, HarmBlockThreshold
  10. from common import Common
  11. from common.feishu_data import Material
  12. class VideoAnalyzer:
  13. def __init__(self, api_key):
  14. """初始化类,配置 API 密钥和视频路径"""
  15. genai.configure(api_key=api_key)
  16. self.video_file = None
  17. async def process_and_delete_file(self, file_path):
  18. """删除文件"""
  19. try:
  20. print(f"正在处理文件: {file_path}" )
  21. os.remove( file_path )
  22. print( f"文件已删除: {file_path}" )
  23. except Exception as e:
  24. print( f"处理或删除文件时发生错误: {str( e )}" )
  25. async def download_video(self, video_url, save_directory='/root/google_ai_studio/path'):
  26. # async def download_video(self, video_url, save_directory='/Users/tzld/Desktop/google_ai_studio/path'):
  27. """从给定的视频链接下载视频并保存到指定路径"""
  28. random_filename = f"{uuid.uuid4()}.mp4"
  29. save_path = os.path.join(save_directory, random_filename)
  30. max_retries = 3 # 最大重试次数
  31. for attempt in range(max_retries):
  32. try:
  33. # 发送 GET 请求获取视频内容
  34. headers = {}
  35. payload = {}
  36. response = requests.request("GET", video_url, headers=headers, data=payload)
  37. if response.status_code == 200:
  38. # 以二进制写入模式打开文件
  39. with open(save_path, "wb") as file:
  40. # 将响应内容写入文件
  41. file.write(response.content)
  42. print(f"视频已成功下载并保存到: {save_path}")
  43. return save_path
  44. else:
  45. print(f"请求失败,状态码: {response.status_code}")
  46. except requests.exceptions.RequestException as e:
  47. print(f"下载视频时出现错误: {e}")
  48. # 如果下载失败,等待一段时间后重试
  49. time.sleep(1)
  50. print("达到最大重试次数,视频下载失败")
  51. return None
  52. async def upload_video(self, save_path, mime_type = None):
  53. """上传视频文件并获取视频文件对象"""
  54. try:
  55. self.video_file = genai.upload_file(save_path, mime_type=mime_type)
  56. await self._wait_for_processing()
  57. except Exception as e:
  58. Common.logger("ai").info(f'上传视频文件并获取视频文件对象失败异常信息{e}')
  59. self.video_file.delete()
  60. return f"上传视频文件并获取视频文件对象失败:{e}"
  61. async def _wait_for_processing(self):
  62. """等待视频文件处理完成"""
  63. while self.video_file.state.name == 'PROCESSING':
  64. print( '等待视频处理完成...' )
  65. await asyncio.sleep(2) # 使用异步睡眠代替阻塞睡眠
  66. self.video_file = genai.get_file( self.video_file.name )
  67. print( f'视频处理完成: {self.video_file.uri}' )
  68. async def create_cache(self):
  69. try:
  70. generation_config = {
  71. "response_mime_type": "application/json"
  72. }
  73. """创建缓存内容,并返回生成模型"""
  74. # 创建生成模型,使用 gemini-1.5-flash 模型
  75. model = genai.GenerativeModel(
  76. model_name="gemini-1.5-flash",
  77. generation_config=generation_config,
  78. safety_settings={
  79. HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
  80. }
  81. )
  82. return model
  83. except Exception as e:
  84. Common.logger("ai").info(f'视频创建缓存内容,并返回生成模型异常信息{e}')
  85. self.video_file.delete()
  86. print(f"视频创建缓存内容,并返回生成模型异常信息{e}")
  87. return f"视频创建缓存内容,并返回生成模型异常信息{e}"
  88. async def analyze_video(self, model, questions, sample_data):
  89. try:
  90. chat_session = model.start_chat(history=[])
  91. message_content = {
  92. "parts": [
  93. self.video_file,
  94. str(questions) +
  95. "输出返回格式样例:\n" + str(sample_data)
  96. ]
  97. }
  98. response = chat_session.send_message( message_content )
  99. self.video_file.delete()
  100. return response
  101. except Exception as e:
  102. Common.logger("ai").info(f'视频处理请求失败:{e}')
  103. self.video_file.delete()
  104. print( f"视频处理请求失败:{e}" )
  105. return f"视频处理请求失败:{e}"
  106. def video_duration(self, filename):
  107. cap = cv2.VideoCapture( filename )
  108. if cap.isOpened():
  109. rate = cap.get( 5 )
  110. frame_num = cap.get( 7 )
  111. duration = frame_num / rate
  112. return int(duration)
  113. return 0
  114. async def main(video_path, api_key, prompt, mark):
  115. """主函数,执行视频上传、缓存创建、问题生成"""
  116. attempt = 0
  117. max_attempts = 1
  118. while attempt < max_attempts:
  119. try:
  120. # 初始化视频分析类
  121. analyzer = VideoAnalyzer(api_key )
  122. for file in genai.list_files():
  123. # file.delete()
  124. print( " ", file.name )
  125. duration = analyzer.video_duration( video_path )
  126. print( f"视频时长为{duration}秒" )
  127. if int( duration ) >= 600 or int( duration ) == 0:
  128. return f"视频时长过长/视频时长为:{duration}秒"
  129. save_path = await analyzer.download_video(video_path)
  130. if not save_path or save_path == None:
  131. if os.path.exists( save_path ):
  132. os.remove( save_path )
  133. print( f"文件已删除: {save_path}" )
  134. print("视频下载失败")
  135. return "视频下载失败"
  136. # 上传并处理视频
  137. upload_response = await analyzer.upload_video( save_path )
  138. if upload_response:
  139. return upload_response, mark
  140. # 创建缓存模型
  141. model =await analyzer.create_cache()
  142. if isinstance( model, str ):
  143. return model, mark
  144. print("创建缓存模型成功")
  145. sample_data = {
  146. "一、基础信息": {
  147. "视觉/音乐/文字": "",
  148. "内容选题": "",
  149. "视频主题": ""
  150. },
  151. "二、主体和场景": {
  152. "视频主体": "",
  153. "视频场景": []
  154. },
  155. "三、情感与风格": {},
  156. "四、视频传播性与观众": {
  157. "片尾引导": {},
  158. "传播性判断": "",
  159. "观众画像": {}
  160. },
  161. "五、音画细节": {
  162. "音频细节": {},
  163. "视频水印": {},
  164. "视频字幕": {},
  165. "视频口播": ""
  166. },
  167. "六、人物与场景": {
  168. "知名人物": {},
  169. "人物年龄段": "",
  170. "场景描述": []
  171. },
  172. "七、时效性与分类": {
  173. "时效性": {},
  174. "视频一级分类": "",
  175. "二级分类": ["品类- 、分数-", "品类- 、分数-", "品类- 、分数-"]
  176. }
  177. }
  178. response =await analyzer.analyze_video( model, prompt, sample_data )
  179. if isinstance( response, str ):
  180. return response, mark
  181. print( response.usage_metadata )
  182. print(response.text)
  183. if os.path.exists( save_path ):
  184. os.remove( save_path )
  185. print( f"文件已删除: {save_path}" )
  186. return response.text, mark
  187. except Exception as e:
  188. attempt += 1 # 增加尝试次数
  189. if attempt < max_attempts:
  190. print(f"重试第 {attempt} 次...")
  191. else:
  192. print( "达到最大重试次数,处理失败" )
  193. Common.logger( "ai" ).info( f'视频分析处理失败异常信息{e}' )
  194. return f"视频分析处理失败:{e}", None
  195. if __name__ == "__main__":
  196. proxy_url = 'http://127.0.0.1:1081'
  197. os.environ["http_proxy"] = proxy_url
  198. os.environ["https_proxy"] = proxy_url
  199. # video_path = 'http://temp.yishihui.com/longvideo/transcode/video/vpc/20240926/66510681PACx7zsp2wDBHJlicE.mp4'
  200. video_path = 'http://temp.yishihui.com/longvideo/transcode/video/vpc/20240605/68754804SJz5E9JNe5hAdSkRwF.mp4'
  201. api_key = "AIzaSyCor0q5w37Dy6fGxloLlCT7KqyEFU3PWP8"
  202. asyncio.run(main(video_path,api_key))