mgbam commited on
Commit
aa5de1c
·
verified ·
1 Parent(s): 057f7a2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -0
app.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import google.generativeai as genai
4
+ # Import other SDKs for Runway, ElevenLabs, Tavily
5
+ # For example: from elevenlabs import generate, play, set_api_key
6
+ import subprocess
7
+ import json
8
+ import time
9
+
10
+ # --- 1. LOAD API KEYS FROM SECRETS ---
11
+ # This is the secure way to do it in Hugging Face Spaces
12
+ genai.configure(api_key=os.environ.get('GEMINI_API_KEY'))
13
+ # set_api_key(os.environ.get('ELEVENLABS_API_KEY'))
14
+ # ... and so on for other APIs
15
+
16
+ # --- 2. DEFINE THE CORE VIDEO GENERATION FUNCTION ---
17
+ # This function will take the client's prompt and do all the work.
18
+ def generate_video_from_topic(topic_prompt):
19
+ print(f"Starting video generation for topic: {topic_prompt}")
20
+
21
+ # Placeholder for the final video path
22
+ final_video_path = None
23
+
24
+ try:
25
+ # STEP A: RESEARCH (Tavily) - Optional but recommended
26
+ # research_results = tavily_client.search(query=f"Key points about {topic_prompt}")
27
+ # facts = research_results['results']
28
+
29
+ # STEP B: SCRIPT & SCENE PROMPTS (Gemini)
30
+ # We ask Gemini for a structured JSON output
31
+ gemini_model = genai.GenerativeModel('gemini-pro')
32
+ prompt = f"""
33
+ Create a short video script about '{topic_prompt}'.
34
+ The video should be about 30 seconds long.
35
+ Return a JSON object with two keys: 'narration_script' (a string) and 'scene_prompts' (a list of 4 detailed, cinematic visual prompts for an AI video generator).
36
+
37
+ Example:
38
+ {{
39
+ "narration_script": "This is the complete narration for the video.",
40
+ "scene_prompts": ["prompt 1", "prompt 2", "prompt 3", "prompt 4"]
41
+ }}
42
+ """
43
+ response = gemini_model.generate_content(prompt)
44
+ script_data = json.loads(response.text)
45
+
46
+ narration = script_data['narration_script']
47
+ scene_prompts = script_data['scene_prompts']
48
+ print(f"Generated Narration: {narration}")
49
+ print(f"Generated Scene Prompts: {scene_prompts}")
50
+
51
+ # STEP C: VOICE OVER (ElevenLabs)
52
+ # audio_bytes = generate(text=narration, voice="Adam", model="eleven_multilingual_v2")
53
+ # with open("audio.mp3", "wb") as f:
54
+ # f.write(audio_bytes)
55
+ # print("Audio file generated.")
56
+
57
+ # --- MOCKUP for now ---
58
+ # Since API calls cost money, let's use a placeholder for testing
59
+ print("MOCK: Skipping real API calls for audio. Using a placeholder.")
60
+ # Create a silent audio file of the right length for testing
61
+ narration_duration = len(narration.split()) / 2.5 # Estimate duration
62
+ subprocess.run(['ffmpeg', '-f', 'lavfi', '-i', 'anullsrc=r=44100:cl=mono', '-t', str(narration_duration), '-q:a', '9', '-acodec', 'libmp3lame', 'audio.mp3', '-y'])
63
+
64
+
65
+ # STEP D: VISUALS (Runway/Hailuo)
66
+ video_clips = []
67
+ for i, scene_prompt in enumerate(scene_prompts):
68
+ print(f"Generating video for scene {i+1}: {scene_prompt}")
69
+ # MOCKUP: Create a simple placeholder video clip
70
+ clip_path = f"scene_{i+1}.mp4"
71
+ subprocess.run([
72
+ 'ffmpeg', '-f', 'lavfi', '-i', f'smptebars=size=1920x1080:rate=30',
73
+ '-t', '4', '-pix_fmt', 'yuv420p', clip_path, '-y'
74
+ ])
75
+ video_clips.append(clip_path)
76
+
77
+ # STEP E: STITCHING (FFmpeg)
78
+ # Create a file list for ffmpeg
79
+ with open("file_list.txt", "w") as f:
80
+ for clip in video_clips:
81
+ f.write(f"file '{clip}'\n")
82
+
83
+ # Concatenate video clips
84
+ subprocess.run(['ffmpeg', '-f', 'concat', '-safe', '0', '-i', 'file_list.txt', '-c', 'copy', 'combined_video.mp4', '-y'])
85
+
86
+ # Add audio to the combined video
87
+ final_video_path = f"final_video_{int(time.time())}.mp4"
88
+ subprocess.run([
89
+ 'ffmpeg', '-i', 'combined_video.mp4', '-i', 'audio.mp3', '-c:v', 'copy',
90
+ '-c:a', 'aac', '-shortest', final_video_path, '-y'
91
+ ])
92
+ print(f"Final video created at: {final_video_path}")
93
+
94
+ except Exception as e:
95
+ print(f"An error occurred: {e}")
96
+ # You can return an error message to the Gradio interface
97
+ raise gr.Error(f"Failed to generate video. Error: {e}")
98
+
99
+ # Return the path to the final video so Gradio can display it
100
+ return final_video_path
101
+
102
+
103
+ # --- 3. CREATE THE GRADIO INTERFACE ---
104
+ with gr.Blocks() as demo:
105
+ gr.Markdown("# 🤖 My Personal AI Video Studio")
106
+ gr.Markdown("Enter a topic to generate a short-form video for social media. Used for fulfilling Fiverr orders.")
107
+
108
+ with gr.Row():
109
+ topic_input = gr.Textbox(label="Video Topic", placeholder="e.g., 'The benefits of a standing desk'")
110
+ generate_button = gr.Button("Generate Video", variant="primary")
111
+
112
+ with gr.Row():
113
+ video_output = gr.Video(label="Generated Video")
114
+
115
+ generate_button.click(
116
+ fn=generate_video_from_topic,
117
+ inputs=topic_input,
118
+ outputs=video_output
119
+ )
120
+
121
+ # --- 4. LAUNCH THE APP ---
122
+ demo.launch()