junchenfu commited on
Commit
85923d4
·
verified ·
1 Parent(s): 61e57ee

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +86 -0
app.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import json
4
+ import os
5
+ from diffusers import AnimateDiffPipeline, MotionAdapter, EulerDiscreteScheduler
6
+ from diffusers.utils import export_to_gif
7
+ from huggingface_hub import InferenceClient, hf_hub_download
8
+ from safetensors.torch import load_file
9
+ import spaces
10
+
11
+ # 1. 初始化 LLM 客户端 (使用 Hugging Face 免费的 Serverless API)
12
+ client = InferenceClient("meta-llama/Llama-3.3-70B-Instruct")
13
+
14
+ # 2. 初始化视频生成 Pipeline (AnimateDiff-Lightning)
15
+ device = "cuda" if torch.cuda.is_available() else "cpu"
16
+ dtype = torch.float16 if torch.cuda.is_available() else torch.float32
17
+
18
+ step = 4 # 4-step inference, fast and good quality
19
+ repo = "ByteDance/AnimateDiff-Lightning"
20
+ ckpt = f"animatediff_lightning_{step}step_diffusers.safetensors"
21
+ base = "emilianJR/epiCRealism"
22
+
23
+ adapter = MotionAdapter().to(device, dtype)
24
+ adapter.load_state_dict(load_file(hf_hub_download(repo, ckpt), device=device))
25
+ pipe = AnimateDiffPipeline.from_pretrained(base, motion_adapter=adapter, torch_dtype=dtype).to(device)
26
+ pipe.scheduler = EulerDiscreteScheduler.from_config(
27
+ pipe.scheduler.config, timestep_spacing="trailing", beta_schedule="linear"
28
+ )
29
+
30
+ def generate_llm_content(query):
31
+ system_prompt = "You are a talented video creator. Generate a response in JSON format with 'title', 'cover_prompt', and 'video_prompt' (3s)."
32
+ user_prompt = f"User Query: {query}\n\nRequirements:\n- title: MAX 50 chars\n- cover_prompt: image description\n- video_prompt: 3s motion description\n\nReturn JSON ONLY."
33
+
34
+ response = client.chat_completion(
35
+ messages=[
36
+ {"role": "system", "content": system_prompt},
37
+ {"role": "user", "content": user_prompt}
38
+ ],
39
+ max_tokens=500,
40
+ response_format={"type": "json_object"}
41
+ )
42
+ return json.loads(response.choices[0].message.content)
43
+
44
+ @spaces.GPU(duration=60) # 申请 ZeroGPU A100 资源
45
+ def create_popcorn(query):
46
+ # Step 1: LLM 生成内容
47
+ content = generate_llm_content(query)
48
+ title = content.get("title", "Untitled Video")
49
+ video_prompt = content.get("video_prompt", query)
50
+
51
+ # Step 2: 生成视频
52
+ print(f"Generating video for: {video_prompt}")
53
+ output = pipe(prompt=video_prompt, guidance_scale=1.0, num_inference_steps=4, num_frames=16)
54
+
55
+ # 保存为 GIF (Gradio 支持展示)
56
+ video_path = "output_video.gif"
57
+ export_to_gif(output.frames[0], video_path)
58
+
59
+ return title, content.get("cover_prompt"), video_prompt, video_path
60
+
61
+ # 3. 构建 Gradio UI
62
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
63
+ gr.Markdown("# 🍿 LLMPopcorn Demo")
64
+ gr.Markdown("Input a topic, and LLMPopcorn will generate the **Title**, **Prompts**, and a **3-second AI Video**.")
65
+
66
+ with gr.Row():
67
+ with gr.Column():
68
+ input_text = gr.Textbox(label="Enter your video idea", placeholder="e.g., A futuristic city with flying cars")
69
+ btn = gr.Button("Generate Popcorn!", variant="primary")
70
+
71
+ with gr.Column():
72
+ output_title = gr.Textbox(label="Generated Title")
73
+ output_video = gr.Image(label="Generated 3s Video (GIF)")
74
+
75
+ with gr.Accordion("Prompt Details", open=False):
76
+ output_cover_prompt = gr.Textbox(label="Cover Prompt")
77
+ output_video_prompt = gr.Textbox(label="Video Prompt")
78
+
79
+ btn.click(
80
+ fn=create_popcorn,
81
+ inputs=[input_text],
82
+ outputs=[output_title, output_cover_prompt, output_video_prompt, output_video]
83
+ )
84
+
85
+ if __name__ == "__main__":
86
+ demo.launch()