product2204
commited on
Commit
•
cd5bf5b
1
Parent(s):
02d2d4f
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
import re
|
3 |
+
import requests
|
4 |
+
from gtts import gTTS
|
5 |
+
import moviepy.editor as mpe
|
6 |
+
from moviepy.editor import concatenate_videoclips
|
7 |
+
|
8 |
+
# API key and basic setup for Pixabay
|
9 |
+
API_KEY = '43444686-8ab8011dcadf5ec78f23cbff8'
|
10 |
+
|
11 |
+
|
12 |
+
PIXABAY_URL = f"https://pixabay.com/api/?key={API_KEY}"
|
13 |
+
import pixabay.core
|
14 |
+
import google.generativeai as genai
|
15 |
+
from google.colab import userdata
|
16 |
+
|
17 |
+
def gemini_ai_config():
|
18 |
+
#@title Configure Gemini API key
|
19 |
+
|
20 |
+
#Access your Gemini API key
|
21 |
+
try:
|
22 |
+
GOOGLE_API_KEY="AIzaSyD3XZWTlW3S5a2qDoWAFSH3lsOpzVYVpSs"
|
23 |
+
genai.configure(api_key=GOOGLE_API_KEY)
|
24 |
+
model = genai.GenerativeModel('gemini-pro')
|
25 |
+
return model
|
26 |
+
except Exception as e:
|
27 |
+
# unknown error
|
28 |
+
print(f"There was an unknown error. Ensure you have a secret stored in Colab and it's a valid key from https://makersuite.google.com/app/apikey")
|
29 |
+
raise e
|
30 |
+
|
31 |
+
|
32 |
+
def generate_voice_from_text(text, query,lang='en'):
|
33 |
+
"""Generates an MP3 file from the given text using gTTS."""
|
34 |
+
tts = gTTS(text=text, lang=lang)
|
35 |
+
audio_path = f'temp_{query}_audio.mp3'
|
36 |
+
tts.save(audio_path)
|
37 |
+
return audio_path
|
38 |
+
|
39 |
+
|
40 |
+
|
41 |
+
def read_script(content):
|
42 |
+
"""Reads a script file and returns a list of text and queries."""
|
43 |
+
'''with open(filename, "r") as file:
|
44 |
+
content = file.read().strip()
|
45 |
+
# This pattern assumes there could be multiple lines between ####TEXT: and ####QUERY:'''
|
46 |
+
pattern = r"###TEXT:\s*(.*?)\s*###QUERY:\s*(.*?)(?=###TEXT:|$)"
|
47 |
+
|
48 |
+
segments = re.findall(pattern, content, re.DOTALL)
|
49 |
+
if not segments:
|
50 |
+
print("No valid segments found in the script. Please check the script format.")
|
51 |
+
return segments
|
52 |
+
|
53 |
+
def fetch_video_from_pixabay(query, i):
|
54 |
+
try:
|
55 |
+
|
56 |
+
px = pixabay.core(API_KEY)
|
57 |
+
space = px.queryVideo(query)
|
58 |
+
print("{} hits".format(len(space)))
|
59 |
+
filename = f"{query}_{i}.mp4"
|
60 |
+
space[0].download(filename, "large")
|
61 |
+
return filename
|
62 |
+
except Exception as e:
|
63 |
+
print(f"Error fetching video for query '{query}': {e}")
|
64 |
+
return None
|
65 |
+
|
66 |
+
def process_segment(text, query, index):
|
67 |
+
video_url = fetch_video_from_pixabay(query, index)
|
68 |
+
print("index",index,"query",query)
|
69 |
+
|
70 |
+
if video_url:
|
71 |
+
video_clip = mpe.VideoFileClip(video_url)
|
72 |
+
audio_path = generate_voice_from_text(text, query)
|
73 |
+
|
74 |
+
audio_clip = mpe.AudioFileClip(audio_path)
|
75 |
+
# Trim the video to the desired duration (first 10 seconds)
|
76 |
+
if video_clip.duration > audio_clip.duration:
|
77 |
+
video_clip = video_clip.subclip(0, audio_clip.duration)
|
78 |
+
else:
|
79 |
+
if video_clip.duration < audio_clip.duration:
|
80 |
+
loop_count = int( audio_clip.duration// video_clip.duration)
|
81 |
+
video_clip = mpe.concatenate_videoclips([video_clip] * loop_count)
|
82 |
+
|
83 |
+
# Combine the audio and video
|
84 |
+
final_clip = video_clip.set_audio(audio_clip)
|
85 |
+
|
86 |
+
final_clip = video_clip.set_audio(audio_clip)
|
87 |
+
video_file_path = f"{query}_{index}.mp4" # Removed the redundant assignment here
|
88 |
+
|
89 |
+
final_clip.write_videofile(video_file_path, codec="libx264", fps=24)
|
90 |
+
return video_file_path
|
91 |
+
else:
|
92 |
+
print(f"Skipping segment due to no available video for query: {query}")
|
93 |
+
return None
|
94 |
+
|
95 |
+
# Main process
|
96 |
+
def main_text_2_video(text):
|
97 |
+
|
98 |
+
model=gemini_ai_config()
|
99 |
+
response = model.generate_content(text)
|
100 |
+
print(f'**You**: what is add\n\n**Gemini**:\n{response.text}')
|
101 |
+
video_segments = read_script(response.text)
|
102 |
+
video_clips=[]
|
103 |
+
print(f"Number of segments: {len(video_segments)}")
|
104 |
+
for index, segment in enumerate(video_segments):
|
105 |
+
text, query = segment[0],segment[1]
|
106 |
+
print(f"Processing segment {index + 1}/{len(video_segments)} - Text: {text} Query: {query}")
|
107 |
+
video_clip_path=process_segment(text, query,index)
|
108 |
+
if video_clip_path:
|
109 |
+
# Load the video clip and add to the list
|
110 |
+
video_clip = mpe.VideoFileClip(video_clip_path)
|
111 |
+
video_clips.append(video_clip)
|
112 |
+
else:
|
113 |
+
print("No video segments to concatenate.")
|
114 |
+
|
115 |
+
if video_clips:
|
116 |
+
final_video = concatenate_videoclips(video_clips)
|
117 |
+
final_video.write_videofile("final_output.mp4", codec="libx264", fps=24)
|
118 |
+
print("Final video created successfully.")
|
119 |
+
else:
|
120 |
+
print("No video segments to concatenate.")
|
121 |
+
|
122 |
+
from google.colab import files
|
123 |
+
|
124 |
+
# This will prompt a download dialog in the browser
|
125 |
+
files.download('final_output.mp4')
|
126 |
+
|
127 |
+
import gradio as gr
|
128 |
+
|
129 |
+
|
130 |
+
text="""
|
131 |
+
You are attention deficit coach , for a college student, write about best way to productive if you have attention deficit disorder
|
132 |
+
We will provide you with an idea of the video along with some reference content. Using the idea create a 1-2 min video for it.
|
133 |
+
Create a text for 1-2 min minute video (around 200-400 words),
|
134 |
+
video title (make it clickbait super interesting, include numbers into title and maybe open question), video description (optimize for more tags for youtube and google search).
|
135 |
+
For actual video content I will be using pixelbay content to compose a series of videos
|
136 |
+
into my video. So for the text you provide you have to provide a search query for every
|
137 |
+
part so i can search it in pixelbay and pick videos from there.
|
138 |
+
Make video, engaging, include different stories, history, make it fun at some points.
|
139 |
+
Make it as interesting as possible.
|
140 |
+
Avoid any
|
141 |
+
kind of lists 1), 2) .. in the text part in the video, also avoid everything
|
142 |
+
which is usually not said by humans in the video including various symbols and etc. use just
|
143 |
+
words and numbers because the video text will be used for voice over.
|
144 |
+
Please provide the output to meet the following format:
|
145 |
+
|
146 |
+
|
147 |
+
###TEXT: <text of what you will say in the video, this should complement to the query video which will be shown in the video>
|
148 |
+
###QUERY: <text of what video i should search on storyblocks to match the text above, the query should be short, 1-2 words max, should be as general as possible but on the given topic>
|
149 |
+
|
150 |
+
Always include pair of ###QUERY and ###TEXT for next parts, a video should have a new query around every 10-30 seconds. Initial 1st minute of video should be more
|
151 |
+
dynamic and contain more queries 10s each.
|
152 |
+
End video asking to like and subscribe to channel, like and share."""
|
153 |
+
|
154 |
+
# Define the Gradio interface
|
155 |
+
interface = gr.Interface(
|
156 |
+
fn=process_video_paragraph,
|
157 |
+
inputs=gr.Textbox(label="Input Paragraph", placeholder=text, default=text),
|
158 |
+
outputs=gr.Video(label="video")
|
159 |
+
title="Paragraph to Video Generator",
|
160 |
+
description="Enter a paragraph of text and receive a filepath to the generated video."
|
161 |
+
)
|
162 |
+
|
163 |
+
# Run the Gradio app
|
164 |
+
if __name__ == "__main__":
|
165 |
+
interface.launch(debug=True)
|
166 |
+
|
167 |
+
|