|
|
|
import re |
|
import requests |
|
from gtts import gTTS |
|
import moviepy.editor as mpe |
|
from moviepy.editor import concatenate_videoclips |
|
import ffmpeg |
|
|
|
|
|
API_KEY = '43444686-8ab8011dcadf5ec78f23cbff8' |
|
|
|
|
|
PIXABAY_URL = f"https://pixabay.com/api/?key={API_KEY}" |
|
import pixabay.core |
|
import google.generativeai as genai |
|
|
|
def gemini_ai_config(): |
|
|
|
|
|
|
|
|
|
try: |
|
GOOGLE_API_KEY="AIzaSyD3XZWTlW3S5a2qDoWAFSH3lsOpzVYVpSs" |
|
genai.configure(api_key=GOOGLE_API_KEY) |
|
model = genai.GenerativeModel('gemini-pro') |
|
return model |
|
except Exception as e: |
|
|
|
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") |
|
raise e |
|
|
|
|
|
def generate_voice_from_text(text, query,lang='en'): |
|
"""Generates an MP3 file from the given text using gTTS.""" |
|
tts = gTTS(text=text, lang=lang) |
|
audio_path = f'temp_{query}_audio.mp3' |
|
tts.save(audio_path) |
|
save_and_return_file(audio_path) |
|
return audio_path |
|
|
|
|
|
def save_and_return_file(filename): |
|
print("save",filename) |
|
|
|
|
|
def read_script(content): |
|
"""Reads a script file and returns a list of text and queries.""" |
|
'''with open(filename, "r") as file: |
|
content = file.read().strip() |
|
# This pattern assumes there could be multiple lines between ####TEXT: and ####QUERY:''' |
|
pattern = r"###TEXT:\s*(.*?)\s*###QUERY:\s*(.*?)(?=###TEXT:|$)" |
|
|
|
segments = re.findall(pattern, content, re.DOTALL) |
|
if not segments: |
|
print("No valid segments found in the script. Please check the script format.") |
|
return segments |
|
|
|
def fetch_video_from_pixabay(query, i): |
|
try: |
|
|
|
px = pixabay.core(API_KEY) |
|
space = px.queryVideo(query) |
|
print("{} hits".format(len(space))) |
|
filename = f"{query}_{i}.mp4" |
|
space[0].download(filename, "large") |
|
return filename |
|
except Exception as e: |
|
print(f"Error fetching video for query '{query}': {e}") |
|
return None |
|
|
|
def process_segment(text, query, index): |
|
video_url = fetch_video_from_pixabay(query, index) |
|
print("index",index,"query",query) |
|
|
|
if video_url: |
|
video_clip = mpe.VideoFileClip(video_url) |
|
audio_path = generate_voice_from_text(text, query) |
|
|
|
audio_clip = mpe.AudioFileClip(audio_path) |
|
|
|
if video_clip.duration > audio_clip.duration: |
|
video_clip = video_clip.subclip(0, audio_clip.duration) |
|
else: |
|
if video_clip.duration < audio_clip.duration: |
|
loop_count = int( audio_clip.duration// video_clip.duration) |
|
video_clip = mpe.concatenate_videoclips([video_clip] * loop_count) |
|
|
|
|
|
|
|
final_clip = video_clip.set_audio(audio_clip) |
|
|
|
final_clip = video_clip.set_audio(audio_clip) |
|
video_file_path = f"{query}_{index}.mp4" |
|
|
|
final_clip.write_videofile(video_file_path, codec="libx264", fps=24) |
|
save_and_return_file(video_file_path) |
|
|
|
return video_file_path |
|
else: |
|
print(f"Skipping segment due to no available video for query: {query}") |
|
return None |
|
|
|
|
|
def process_video_paragraph(text): |
|
|
|
model=gemini_ai_config() |
|
response = model.generate_content(text) |
|
print(f'**You**: what is add\n\n**Gemini**:\n{response.text}') |
|
video_segments = read_script(response.text) |
|
video_clips=[] |
|
print(f"Number of segments: {len(video_segments)}") |
|
for index, segment in enumerate(video_segments): |
|
text, query = segment[0],segment[1] |
|
print(f"Processing segment {index + 1}/{len(video_segments)} - Text: {text} Query: {query}") |
|
video_clip_path=process_segment(text, query,index) |
|
if video_clip_path: |
|
|
|
video_clip = mpe.VideoFileClip(video_clip_path) |
|
video_clips.append(video_clip) |
|
else: |
|
print("No video segments to concatenate.") |
|
if video_clips: |
|
final_video = concatenate_videoclips(video_clips,method="compose") |
|
final_output_path = "final_concatenated_video.mp4" |
|
final_video.write_videofile(final_output_path, codec="libx264", fps=24) |
|
print(f"Final concatenated video created: {final_output_path}") |
|
save_and_return_file(final_output_path) |
|
|
|
return final_output_path |
|
|
|
|
|
import gradio as gr |
|
|
|
|
|
text=""" |
|
You are attention deficit coach , for a college student, write about best way to productive if you have attention deficit disorder |
|
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. |
|
Create a text for 1-2 min minute video (around 200-400 words), |
|
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). |
|
For actual video content I will be using pixelbay content to compose a series of videos |
|
into my video. So for the text you provide you have to provide a search query for every |
|
part so i can search it in pixelbay and pick videos from there. |
|
Make video, engaging, include different stories, history, make it fun at some points. |
|
Make it as interesting as possible. |
|
Avoid any |
|
kind of lists 1), 2) .. in the text part in the video, also avoid everything |
|
which is usually not said by humans in the video including various symbols and etc. use just |
|
words and numbers because the video text will be used for voice over. |
|
Please provide the output to meet the following format: |
|
|
|
|
|
###TEXT: <text of what you will say in the video, this should complement to the query video which will be shown in the video> |
|
###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> |
|
|
|
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 |
|
dynamic and contain more queries 10s each. |
|
End video asking to like and subscribe to channel, like and share.""" |
|
|
|
|
|
interface = gr.Interface( |
|
fn=process_video_paragraph, |
|
inputs=gr.Textbox(label="Input Paragraph", placeholder=text), |
|
outputs=gr.Video(label="video"), |
|
title="Paragraph to Video Generator", |
|
description="Enter a paragraph of text and receive a filepath to the generated video." |
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
interface.launch(debug=True,share=True) |
|
|
|
|
|
|