analyze_video.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import asyncio
  2. import uvicorn
  3. from datetime import datetime, timedelta
  4. from fastapi import FastAPI
  5. from pydantic import BaseModel
  6. import random
  7. from google_ai.generativeai_video import main
  8. app = FastAPI()
  9. # 初始化 API key 列表,每个 key 包含 '错误计数' 和 '锁定直到' 时间
  10. api_keys = [
  11. {'key': 'AIzaSyDs4FWRuwrEnQzu1M_Skio6NII6Mp4whAw', 'locked': False, 'locked_until': None, 'error_count': 0},
  12. {'key': 'AIzaSyC-IxUvJhbiKWA7uN1RTtVbOjt3pj_-Apc', 'locked': False, 'locked_until': None, 'error_count': 0},
  13. {'key': 'AIzaSyB43Pvugb-CMkEXJUSubXEAxKxYflCPPNU', 'locked': False, 'locked_until': None, 'error_count': 0},
  14. {'key': 'AIzaSyAYgOeHS2NUlVuVe14rgNDaxXRNRt4smuY', 'locked': False, 'locked_until': None, 'error_count': 0},
  15. {'key': 'AIzaSyAa4H7YzIOiqA0QIDuO6kNErFBoWT-BEtc', 'locked': False, 'locked_until': None, 'error_count': 0},
  16. {'key': 'AIzaSyAUvBSpjFcm7b8FsgRUTG6anzoalDp9gYg', 'locked': False, 'locked_until': None, 'error_count': 0},
  17. {'key': 'AIzaSyB43Pvugb-CMkEXJUSubXEAxKxYflCPPNU', 'locked': False, 'locked_until': None, 'error_count': 0}
  18. ]
  19. lock = asyncio.Lock()
  20. class VideoRequest(BaseModel):
  21. video_path: str
  22. async def get_available_api_key():
  23. """获取一个未锁定且没有过期的 API key,如果没有可用的则随机解锁一个"""
  24. while True:
  25. async with lock:
  26. now = datetime.now()
  27. available_key = None
  28. for key_data in api_keys:
  29. if not key_data['locked'] and (key_data['locked_until'] is None or key_data['locked_until'] <= now):
  30. available_key = key_data['key']
  31. key_data['locked'] = True
  32. break
  33. if available_key:
  34. return available_key
  35. else:
  36. # 所有 key 都被锁定,随机解锁一个,并重置错误计数
  37. print("所有 API key 都被锁定,随机解锁一个并重置错误计数...")
  38. random_key_data = random.choice(api_keys)
  39. random_key_data['locked'] = False
  40. random_key_data['locked_until'] = None # 解除时间锁定
  41. random_key_data['error_count'] = 0 # 清空错误计数
  42. random_key_data['locked'] = True
  43. return random_key_data['key']
  44. async def release_api_key(api_key, lock_until=None, reset_error_count=False):
  45. """释放已锁定的 API key,支持设置锁定时间并重置错误计数"""
  46. async with lock:
  47. for key_data in api_keys:
  48. if key_data['key'] == api_key:
  49. key_data['locked'] = False
  50. key_data['locked_until'] = lock_until # 设置锁定时间
  51. if reset_error_count:
  52. key_data['error_count'] = 0 # 重置错误计数
  53. break
  54. def get_next_midnight():
  55. """计算下一天的 0 点"""
  56. now = datetime.now()
  57. next_midnight = (now + timedelta(days=1)).replace(hour=1, minute=0, second=0, microsecond=0)
  58. return next_midnight
  59. @app.post("/process_video/")
  60. async def process_video(request: VideoRequest):
  61. """处理视频请求"""
  62. video_path = request.video_path
  63. # 获取一个可用的 API key
  64. api_key = await get_available_api_key()
  65. try:
  66. print(f"来一个请求,使用 API key: {api_key}")
  67. result, mark = await main(video_path, api_key)
  68. if "too many values to unpack" in result:
  69. async with lock:
  70. for key_data in api_keys:
  71. if key_data['key'] == api_key:
  72. key_data['error_count'] += 1
  73. print( f"API key {api_key} 的错误计数增加到 {key_data['error_count']}" )
  74. # 如果错误计数达到 5 次,锁定该 key 到第二天 00:00
  75. if key_data['error_count'] >= 5:
  76. lock_until = get_next_midnight()
  77. print( f"API key {api_key} 连续返回错误 5 次,锁定至 {lock_until}" )
  78. await release_api_key( api_key, lock_until )
  79. else:
  80. await release_api_key( api_key )
  81. break
  82. return {
  83. "code": 0,
  84. "message": "视频处理失败: too many values to unpack",
  85. "result": result,
  86. "mark": mark
  87. }
  88. else:
  89. # 视频处理成功,重置错误计数
  90. await release_api_key( api_key, reset_error_count=True )
  91. return {
  92. "code": 0,
  93. "message": "视频处理成功",
  94. "result": result,
  95. "mark": mark
  96. }
  97. except ValueError as e:
  98. error_message = str(e)
  99. if "too many values to unpack" in error_message:
  100. # 增加该 key 的错误计数
  101. async with lock:
  102. for key_data in api_keys:
  103. if key_data['key'] == api_key:
  104. key_data['error_count'] += 1
  105. print(f"API key {api_key} 的错误计数增加到 {key_data['error_count']}")
  106. # 如果错误计数达到 10 次,锁定该 key 到第二天 0 点
  107. if key_data['error_count'] >= 10:
  108. lock_until = get_next_midnight()
  109. print(f"API key {api_key} 连续返回错误 5 次,锁定至 {lock_until}")
  110. await release_api_key(api_key, lock_until)
  111. else:
  112. await release_api_key(api_key)
  113. break
  114. else:
  115. await release_api_key(api_key)
  116. return {
  117. "code": 1,
  118. "message": f"视频处理失败: {e}",
  119. "result": f"视频处理失败: {e}",
  120. "mark": f"视频处理失败: {e}"
  121. }
  122. except Exception as e:
  123. print(f"视频处理失败: {str(e)}")
  124. await release_api_key(api_key)
  125. return {
  126. "code": 1,
  127. "message": f"视频处理失败: {e}",
  128. "result": f"视频处理失败: {e}",
  129. "mark": f"视频处理失败: {e}"
  130. }
  131. finally:
  132. await release_api_key(api_key)
  133. if __name__ == "__main__":
  134. uvicorn.run(app, host="0.0.0.0", port=8080)