ai_admin/WebAdmin/create_text_img_video.py
2024-09-20 04:29:09 +00:00

333 lines
14 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import time
import requests
from django.http import JsonResponse
from .models import VideoGeneration
from django.views.decorators.csrf import csrf_exempt
from .base import logger,deduct_points
def generate_video_id(user_id):
"""
根据用户ID和当前时间戳生成唯一的视频ID
"""
timestamp = int(time.time())
video_id = f"{timestamp}_{user_id}"
print(f"生成的视频ID: {video_id}")
return video_id
def get_dimensions(model, width=None, height=None):
"""
根据模型返回相应的宽高分辨率:
gen3: 最大1280x768
gen2: 可传入前端指定的宽高默认最大1920x1080
"""
if model == 'gen3':
return 1280, 768
elif model == 'gen2':
# 如果前端提供了 width 和 height则使用传入的值否则使用默认值
if width and height:
return width, height
return 1920, 1080
else:
raise ValueError(f"不支持的模型: {model}")
def get_headers():
"""
返回统一的请求头
"""
return {
"accept": "application/json",
"content-type": "application/json",
"Authorization": "12e76710fad2047db8c0cc6b25987e2a2" # 替换为你的真实授权密钥
}
@csrf_exempt
def text_to_video(request):
"""
文本生成视频接口
"""
if request.method == "POST":
try:
if not request.user.is_authenticated:
return JsonResponse({'code': 401, 'message': '用户未登录'})
user = request.user
data = json.loads(request.body)
# 获取参数
text_prompt = data.get('text_prompt')
style = data.get('style', '') # 选择的风格,默认是 'general'
model = data.get('model', 'gen3') # 选择模型,默认是 'gen3'
time_duration = int(data.get('time', 5)) # 视频时长
motion = int(data.get('motion', 5)) # 视频丰富度参数
width = data.get('width') # 由前端传入的宽度仅限gen2
height = data.get('height') # 由前端传入的高度仅限gen2
print(f"生成模型: {model}, 时长: {time_duration}, 文本: {text_prompt}, 宽高: {width}x{height}, 画面丰富度: {motion}")
result = deduct_points(user, "text-to-video")
if result is not True:
return result # 返回积分不足的响应
# 验证模型和时长限制
if model == 'gen3' and time_duration not in [5, 10]:
return JsonResponse({'code': 400, 'message': 'gen3 模型只支持 5s 或 10s 的时长'})
if model == 'gen2' and time_duration != 4:
return JsonResponse({'code': 400, 'message': 'gen2 模型只支持 4s 的时长'})
# 生成视频ID
video_id = generate_video_id(user.id)
# 根据模型获取宽高
width, height = get_dimensions(model, width, height)
print(f"生成的视频分辨率: {width}x{height}")
# 准备POST请求数据
payload = {
"text_prompt": f"{text_prompt}. Style: {style}",
"model": model,
"width": width,
"height": height,
"motion": motion, # 视频画面丰富度
"seed": 0,
"upscale": False,
"interpolate": False,
"callback_url": "https://www.typeframes.ai/api/callback/",
"time": time_duration # 视频时长
}
print(f'text_to_video 请求体: {payload}')
# 发送请求到API
response = requests.post('https://api.aivideoapi.com/runway/generate/text', json=payload, headers=get_headers())
print(f"API响应状态码: {response.status_code}")
print(f"API响应内容: {response.text}")
# 解析响应数据
if response.status_code == 200:
res_data = response.json()
uuid = res_data.get('uuid')
# 保存生成记录到数据库
video_generation = VideoGeneration.objects.create(
video_id=video_id,
user=user,
text=text_prompt,
status='in_progress',
pid=uuid,
media_type=f'{model}_text_to_video',
slug=f'text-to-video',
ratio=f"{width}:{height}"
)
video_generation.save()
# 返回成功响应
return JsonResponse({
'code': 200,
'message': '请求成功,视频正在生成中',
'data': {
'video_id': video_generation.video_id,
'status': video_generation.status,
'pid': uuid
}
})
else:
return JsonResponse({'code': response.status_code, 'message': 'API请求失败', 'data': {}})
except Exception as e:
print(f"发生错误: {str(e)}")
return JsonResponse({'code': 500, 'message': f'内部错误: {str(e)}', 'data': {}})
return JsonResponse({'code': 405, 'message': '请求方法错误', 'data': {}})
@csrf_exempt
def image_to_video(request):
"""
图片生成视频接口,图片宽高自适应
"""
if request.method == "POST":
try:
if not request.user.is_authenticated:
return JsonResponse({'code': 401, 'message': '用户未登录'})
user = request.user
data = json.loads(request.body)
# 获取参数
text_prompt = data.get('text_prompt')
image_url = data.get('image_url')
model = data.get('model', 'gen3') # 选择模型,默认是 'gen3'
time_duration = int(data.get('time', 5)) # 视频时长
motion = int(data.get('motion', 5)) # 视频丰富度
print(f"生成模型: {model}, 图片地址: {image_url}, 时长: {time_duration}, 画面丰富度: {motion}")
result = deduct_points(user, "img-to-video")
if result is not True:
return result # 返回积分不足的响应
# 验证模型和时长限制
if model == 'gen3' and time_duration not in [5, 10]:
return JsonResponse({'code': 400, 'message': 'gen3 模型只支持 5s 或 10s 的时长'})
if model == 'gen2' and time_duration != 4:
return JsonResponse({'code': 400, 'message': 'gen2 模型只支持 4s 的时长'})
# 生成视频ID
video_id = generate_video_id(user.id)
# 准备POST请求数据宽高不需要传入图片自适应
payload = {
"text_prompt": text_prompt,
"model": model,
"img_prompt": image_url,
"image_as_end_frame": False, # 图片不作为最后一帧
"motion": motion, # 视频丰富度
"seed": 0,
"upscale": False,
"interpolate": False,
"callback_url": "https://www.typeframes.ai/api/callback/",
"time": time_duration # 视频时长
}
print(f'img_to_video 请求体: {payload}')
# 请求头
headers = get_headers()
# 发送请求到API
response = requests.post('https://api.aivideoapi.com/runway/generate/imageDescription', json=payload, headers=headers)
print(f"API响应状态码: {response.status_code}")
print(f"API响应内容: {response.text}")
# 解析响应数据
if response.status_code == 200:
res_data = response.json()
uuid = res_data.get('uuid')
# 保存生成记录到数据库
video_generation = VideoGeneration.objects.create(
video_id=video_id,
user=user,
text=text_prompt,
status='in_progress',
pid=uuid,
media_type=f'{model}_img_to_video',
slug=f'img-to-video',
ratio="auto" # 图片自适应宽高
)
video_generation.save()
# 返回成功响应
return JsonResponse({
'code': 200,
'message': '请求成功,视频正在生成中',
'data': {
'video_id': video_generation.video_id,
'status': video_generation.status,
'pid': uuid
}
})
else:
return JsonResponse({'code': response.status_code, 'message': 'API请求失败', 'data': {}})
except Exception as e:
print(f"发生错误: {str(e)}")
return JsonResponse({'code': 500, 'message': f'内部错误: {str(e)}', 'data': {}})
return JsonResponse({'code': 405, 'message': '请求方法错误', 'data': {}})
@csrf_exempt
def extend_video(request):
"""
延长视频的函数,发送请求到 /runway/extend
"""
if request.method == "POST":
try:
if not request.user.is_authenticated:
return JsonResponse({'code': 401, 'message': '用户未登录'})
user = request.user
data = json.loads(request.body)
# 获取参数
pid = data.get('pid')
motion = int(data.get('motion', 5)) # 视频丰富度
# 获取当前视频生成记录
video_generation = VideoGeneration.objects.get(pid=pid)
# 通过 media_type 判断模型是 gen3 还是 gen2
if 'gen3' in video_generation.media_type:
model = 'gen3'
# 验证 gen3 的延长逻辑
if video_generation.extension_count >= 1 or video_generation.time_duration >= 10:
return JsonResponse({'code': 400, 'message': 'gen3 最大时长为 10s无法继续延长'})
time_extension = 5 # 每次延长 5 秒
elif 'gen2' in video_generation.media_type:
model = 'gen2'
# 验证 gen2 的延长逻辑
if video_generation.extension_count >= 2 or video_generation.time_duration >= 12:
return JsonResponse({'code': 400, 'message': 'gen2 最大时长为 12s无法继续延长'})
time_extension = 4 # 每次延长 4 秒
else:
return JsonResponse({'code': 400, 'message': '未知的模型类型'})
result = deduct_points(user, video_generation.slug)
if result is not True:
return result # 返回积分不足的响应
# 生成新的视频ID
new_video_id = generate_video_id(user.id)
# 默认请求体
payload = {
"uuid": pid, # 视频的 UUID
"motion": motion, # 视频丰富度
"seed": 0, # 默认 seed 为 0
"upscale": False, # 默认开启 upscale
"interpolate": False, # 默认开启 interpolate
"callback_url": "https://www.typeframes.ai/api/callback/"
}
print(f"extend_video 请求体: {payload}")
headers = get_headers()
# 发送 POST 请求
response = requests.post('https://api.aivideoapi.com/runway/extend', json=payload, headers=headers)
print(f"API响应状态码: {response.status_code}")
print(f"API响应内容: {response.text}")
# 解析响应内容
if response.status_code == 200:
res_data = response.json()
new_pid = res_data.get('uuid')
# 创建新的延长视频记录,复制上一条视频的参数
new_video_generation = VideoGeneration.objects.create(
video_id=new_video_id,
user=user,
text=video_generation.text,
voice_name=video_generation.voice_name,
style=video_generation.style,
rate=video_generation.rate,
media_type=video_generation.media_type,
ratio=video_generation.ratio,
status='in_progress',
pid=new_pid,
time_duration=video_generation.time_duration + time_extension, # 增加对应模型的时长
extension_count=video_generation.extension_count + 1, # 增加延长次数
slug=video_generation.slug # slug 使用中划线
)
print(f"延长视频成功: {res_data}")
return JsonResponse({'code': 200, 'message': '视频延长请求成功', 'data': {'new_pid': new_pid}})
else:
return JsonResponse({'code': response.status_code, 'message': 'API请求失败', 'data': {}})
except Exception as e:
print(f"发生错误: {str(e)}")
return JsonResponse({'code': 500, 'message': f'内部错误: {str(e)}', 'data': {}})
return JsonResponse({'code': 405, 'message': '请求方法错误', 'data': {}})