107 lines
3.8 KiB
Python
Executable File
107 lines
3.8 KiB
Python
Executable File
import requests
|
||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||
from django.http import JsonResponse
|
||
from django.views.decorators.csrf import csrf_exempt
|
||
|
||
from .models import VideoGeneration
|
||
|
||
def update_single_video_status(task, query_type):
|
||
"""
|
||
更新单个视频的状态,适用于并发调用
|
||
"""
|
||
url = ''
|
||
headers = {}
|
||
if query_type == 'revid':
|
||
url = f"https://www.revid.ai/api/public/v2/status?pid={task.pid}"
|
||
headers = {
|
||
"key": "c4c0f516-33c0-4f5c-9d29-3b1d4e6a93c3",
|
||
"Content-Type": "text/plain"
|
||
}
|
||
elif query_type == 'runwayml':
|
||
url = f"https://api.aivideoapi.com/status?uuid={task.pid}"
|
||
headers = {
|
||
"Authorization": "12e76710fad2047db8c0cc6b25987e2a2",
|
||
"Content-Type": "application/json"
|
||
}
|
||
|
||
try:
|
||
response = requests.get(url, headers=headers)
|
||
response.raise_for_status()
|
||
data = response.json()
|
||
|
||
# print(f"任务 PID: {task.pid} - 查询类型: {query_type}")
|
||
# print(f"API响应: {data}")
|
||
|
||
# 根据API响应,更新数据库状态
|
||
if query_type == 'runwayml':
|
||
status = data.get('status')
|
||
video_url = data.get('url', None)
|
||
gif_url = data.get('gif_url', None)
|
||
|
||
if status == 'success':
|
||
task.status = 'completed'
|
||
task.video_url = video_url
|
||
task.gif_url = gif_url
|
||
elif status in ['in queue', 'submitted']:
|
||
task.status = 'pending'
|
||
else:
|
||
task.status = 'failed'
|
||
task.description = 'RunwayML 视频生成失败'
|
||
|
||
elif query_type == 'revid':
|
||
success = data.get('success')
|
||
status = data.get('status')
|
||
video_url = data.get('videoUrl', None)
|
||
error_message = data.get('error', '')
|
||
|
||
if success == 1:
|
||
if status == 'ready':
|
||
task.status = 'completed'
|
||
task.video_url = video_url
|
||
elif status == 'building':
|
||
task.status = 'pending'
|
||
elif status == 'error':
|
||
task.status = 'failed'
|
||
task.description = error_message
|
||
|
||
task.save()
|
||
return task.pid, task.status, task.video_url
|
||
|
||
except requests.exceptions.RequestException as e:
|
||
# print(f"任务 PID: {task.pid} 请求失败,错误: {e}")
|
||
return task.pid, 'failed', None
|
||
|
||
@csrf_exempt
|
||
def scan_and_update_video_status(request):
|
||
"""
|
||
扫描所有未完成任务,并发更新每个任务的状态
|
||
"""
|
||
tasks = VideoGeneration.objects.filter(status__in=['pending', 'in_progress'])
|
||
task_count = tasks.count()
|
||
# print(f"开始处理 {task_count} 个任务")
|
||
|
||
results = []
|
||
|
||
if task_count > 0:
|
||
# 使用并发线程池来处理请求
|
||
with ThreadPoolExecutor(max_workers=5) as executor:
|
||
future_to_task = {
|
||
executor.submit(update_single_video_status, task, 'revid' if task.slug in ['music-to-video', 'create-tiktok-video', 'create-avatar-video'] else 'runwayml'): task
|
||
for task in tasks
|
||
}
|
||
|
||
for future in as_completed(future_to_task):
|
||
try:
|
||
task_pid, task_status, task_video_url = future.result()
|
||
results.append({
|
||
'pid': task_pid,
|
||
'status': task_status,
|
||
'video_url': task_video_url
|
||
})
|
||
except Exception as e:
|
||
print(f"Error: {e}")
|
||
|
||
# print("任务处理完成,结果:", results)
|
||
|
||
return JsonResponse({'code': 200, 'message': 'ok', 'data': results})
|