Spaces:
Running
Running
| # app.py (نسخه نهایی با کسر اعتبار سمت کلاینت) | |
| import io | |
| import os | |
| import warnings | |
| import jwt | |
| from fastapi import FastAPI, Form, File, UploadFile, HTTPException | |
| from fastapi.responses import StreamingResponse, FileResponse | |
| from huggingface_hub import InferenceClient | |
| from typing import Optional | |
| from urllib3.exceptions import InsecureRequestWarning | |
| # --- تنظیمات اولیه --- | |
| warnings.filterwarnings("ignore", category=InsecureRequestWarning) | |
| app = FastAPI( | |
| title="AI Video Studio API", | |
| description="Final version with client-side credit deduction confirmation." | |
| ) | |
| # --- کلید مخفی مشترک --- | |
| SECRET_KEY = os.getenv("INTERNAL_API_KEY", "301101005") | |
| # --- Endpoints --- | |
| async def read_root(): | |
| return FileResponse('index.html') | |
| async def generate_video_logic(prompt: str, token: str, image_bytes: Optional[bytes] = None): | |
| try: | |
| # 1. توکن JWT را اعتبارسنجی کن | |
| payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) | |
| api_token = payload.get("api_key") | |
| # "deduction_token" در اینجا فقط برای اعتبارسنجی است و استفاده نمیشود | |
| deduction_token = payload.get("deduction_token") | |
| if not all([api_token, deduction_token]): | |
| raise ValueError("Invalid token payload.") | |
| except jwt.ExpiredSignatureError: | |
| raise HTTPException(status_code=403, detail="مجوز ساخت ویدیو منقضی شده است. لطفا دوباره تلاش کنید.") | |
| except jwt.InvalidTokenError: | |
| raise HTTPException(status_code=403, detail="مجوز ساخت ویدیو نامعتبر است.") | |
| except Exception as e: | |
| raise HTTPException(status_code=400, detail=f"خطا در پردازش مجوز: {e}") | |
| # 2. با کلید API استخراج شده از توکن، ویدیو را بساز | |
| try: | |
| client = InferenceClient(provider="fal-ai", api_key=api_token) | |
| if image_bytes: | |
| video_bytes = client.image_to_video(image_bytes, prompt=prompt, model="akhaliq/veo3.1-fast-image-to-video") | |
| else: | |
| video_bytes = client.text_to_video(prompt, model="akhaliq/veo3.1-fast") | |
| # 3. ویدیو را به همراه توکن کسر اعتبار به کلاینت برگردان | |
| # مرورگر مسئول ارسال توکن کسر اعتبار خواهد بود. | |
| response = StreamingResponse(io.BytesIO(video_bytes), media_type="video/mp4") | |
| response.headers["X-Deduction-Token"] = deduction_token | |
| return response | |
| except Exception as e: | |
| print(f"Hugging Face API Error: {e}") | |
| raise HTTPException(status_code=500, detail="سرویس ساخت ویدیو با خطا مواجه شد ممکنه درخواست شما طبق قوانین نباشه لطفاً درخواست اصلاح کنید و همچنین با تصاویر کودکان از قسمت تصویر به ویدیو امکان ساخت ویدیو در این سرویس وجود نداره تصویر کودکان رو آپلود نکنید و یا افراد مشهور که باعث نقض قوانین میشه. (اعتباری کسر نشد)") | |
| async def api_text_to_video(prompt: str = Form(...), token: str = Form(...)): | |
| return await generate_video_logic(prompt, token) | |
| async def api_image_to_video(prompt: str = Form(...), token: str = Form(...), image: UploadFile = File(...)): | |
| if not image.content_type.startswith("image/"): | |
| raise HTTPException(status_code=400, detail="فایل نامعتبر است. لطفاً یک تصویر آپلود کنید.") | |
| image_bytes = await image.read() | |
| return await generate_video_logic(prompt, token, image_bytes=image_bytes) |