File size: 3,644 Bytes
fad001e
05ae0b9
 
fad001e
623bad5
ef27e6d
c4bca54
05ae0b9
 
623bad5
bcae6dd
fad001e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
05ae0b9
e0ea972
78eeeb4
e0ea972
 
eb4c41a
fad001e
05ae0b9
fad001e
bcae6dd
 
 
fad001e
 
 
 
bcae6dd
fad001e
bcae6dd
fad001e
 
bcae6dd
 
 
 
 
 
 
 
eb4c41a
fad001e
eb4c41a
 
fad001e
eb4c41a
c4bca54
fad001e
6955891
 
80ca058
eb4c41a
 
 
fad001e
 
bcae6dd
fad001e
 
623bad5
bcae6dd
fad001e
 
05ae0b9
e9456a0
78eeeb4
fad001e
 
 
 
 
e9456a0
c4bca54
 
 
 
05ae0b9
e0ea972
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
from fastapi import FastAPI, HTTPException, UploadFile, Form, File, Body
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
import uvicorn, os, shutil, uuid, json, asyncio
from agent import analyze_only, generate_only
from utils import get_history_from_gcs

app = FastAPI(title="Continuity", description="AI Video Bridging Service")
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])

os.makedirs("outputs", exist_ok=True)
app.mount("/outputs", StaticFiles(directory="outputs"), name="outputs")

class JobQueue:
    def __init__(self):
        self.queue = asyncio.Queue()
        self.is_processing = False

    async def add_job(self, job_func, *args):
        await self.queue.put((job_func, args))
        if not self.is_processing:
            asyncio.create_task(self.process_queue())

    async def process_queue(self):
        self.is_processing = True
        while not self.queue.empty():
            func, args = await self.queue.get()
            try:
                await asyncio.to_thread(func, *args)
            except Exception as e:
                print(f"Queue Error: {e}")
            self.queue.task_done()
        self.is_processing = False

job_queue = JobQueue()

@app.get("/")
def read_root():
    return FileResponse("stitch_continuity_dashboard/code.html")

@app.post("/analyze")
def analyze_endpoint(video_a: UploadFile = File(...), video_c: UploadFile = File(...)):
    try:
        rid = str(uuid.uuid4())
        pa = os.path.join("outputs", f"{rid}_a.mp4")
        pc = os.path.join("outputs", f"{rid}_c.mp4")
        
        with open(pa, "wb") as b:
            shutil.copyfileobj(video_a.file, b)
        with open(pc, "wb") as b:
            shutil.copyfileobj(video_c.file, b)
            
        res = analyze_only(os.path.abspath(pa), os.path.abspath(pc), job_id=rid)
        
        if res.get("status") == "error":
            raise HTTPException(500, res.get("detail"))
            
        return {
            "analysis_a": res.get("analysis_a"),
            "analysis_c": res.get("analysis_c"),
            "prompt": res["prompt"],
            "video_a_path": os.path.abspath(pa),
            "video_c_path": os.path.abspath(pc)
        }
    except Exception as e:
        raise HTTPException(500, str(e))

@app.post("/generate")
async def generate_endpoint(
    prompt: str = Body(...),
    style: str = Body("Cinematic"),
    audio_prompt: str = Body("Cinematic"),
    negative_prompt: str = Body(""),
    guidance_scale: float = Body(5.0),
    motion_strength: int = Body(5),
    video_a_path: str = Body(...),
    video_c_path: str = Body(...)
):
    if not os.path.exists(video_a_path) or not os.path.exists(video_c_path):
        raise HTTPException(400, "Videos not found.")
        
    job_id = str(uuid.uuid4())
    with open(f"outputs/{job_id}.json", "w") as f:
        json.dump({"status": "queued", "progress": 0, "log": "Queued..."}, f)
        
    await job_queue.add_job(generate_only, prompt, video_a_path, video_c_path, job_id, style, audio_prompt, negative_prompt, guidance_scale, motion_strength)
    return {"job_id": job_id}

@app.get("/status/{job_id}")
def get_status(job_id: str):
    path = f"outputs/{job_id}.json"
    if not os.path.exists(path):
        raise HTTPException(404, "Job not found")
    with open(path, "r") as f:
        return json.load(f)

@app.get("/history")
def get_history():
    return get_history_from_gcs()

if __name__ == "__main__":
    uvicorn.run("server:app", host="0.0.0.0", port=7860, reload=False)