import gradio as gr import json import requests import random import subprocess import os from gtts import gTTS from moviepy.editor import VideoFileClip, AudioFileClip, concatenate_videoclips # Function to fetch portrait videos from Pexels def get_pexels_video(keyword): headers = {"Authorization": "P310n0wKAlr05spr9UrtHeQXqouRlCL7r1jT6RQD55I1FIqyZt4fx7SL"} params = { "query": keyword, "per_page": 10, "orientation": "portrait", "size": "large", "min_width": 1080, "min_height": 1920, } response = requests.get("https://api.pexels.com/videos/search", headers=headers, params=params) if response.status_code == 200: videos = response.json()['videos'] portrait_videos = [video for video in videos if video['width'] < video['height']] # Check for portrait videos if portrait_videos: selected_video = random.choice(portrait_videos) return selected_video['video_files'][0]['link'] else: print(f"No portrait video found on Pexels for {keyword}") return None else: print("Failed to fetch video from Pexels") return None # Function to generate voiceover using gTTS def generate_voiceover(text, filename, speed=1.0): tts = gTTS(text=text, lang='pt', slow=False) tts.save(filename) # Function to generate video content and create data.json def generate_video_content(topic): api_key = "AIzaSyAtVhAjcUi7tHYnYZTWA4_L2ExvsAeupQY" url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro:generateContent?key={api_key}" payload = { "contents": [ { "role": "user", "parts": [ { "text": f"Create a short one-minute video on {topic} and the keyword under each scene will be used for pexels search query, so give a precise keyword for each scene and create very short scenes. Give upto 15 related tags. Give response in this json format and give just the json: {{ \"title\": \"\", \"description\": \"\", \"video\": [ {{ \"scene\": \"\", \"keyword\": \"\", \"voiceover\": \"\" }} ], \"tags\": [\"\", \"\", \"\"] }}" } ] } ], "generationConfig": { "temperature": 0.9, "topK": 1, "topP": 1, "maxOutputTokens": 2048, "stopSequences": [] }, "safetySettings": [ { "category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE" }, { "category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE" }, { "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE" }, { "category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE" } ] } headers = { 'Content-Type': 'application/json' } response = requests.post(url, headers=headers, json=payload) if response.status_code == 200: try: with open("data.json", "w") as f: f.write(response.json()["candidates"][0]["content"]["parts"][0]["text"]) print("Data saved successfully as data.json") except KeyError: print("Error: Could not find the desired data in the response") else: print("Error occurred while fetching data") # Function to concatenate videos using FFmpeg def concatenate_videos_ffmpeg(scene_videos, output_filename): # Write scene_videos to temporary files temp_filenames = [] for i, video_clip in enumerate(scene_videos): temp_filename = f'temp_video_{i}.mp4' video_clip.write_videofile(temp_filename, codec="libx264", audio_codec="aac", temp_audiofile="temp-audio.m4a", remove_temp=True, verbose=False) temp_filenames.append(temp_filename) # Create a text file containing the list of videos to concatenate with open('video_list.txt', 'w') as f: for temp_filename in temp_filenames: f.write(f"file '{temp_filename}'\n") # Use FFmpeg to concatenate the videos without resizing subprocess.run(['ffmpeg', '-f', 'concat', '-safe', '0', '-i', 'video_list.txt', '-vf', 'scale=1080:1920', '-c:a', 'aac', '-b:a', '256k', '-c:v', 'libx264', '-preset', 'medium', output_filename]) # Clean up the video list file and temporary video files os.remove('video_list.txt') for temp_filename in temp_filenames: os.remove(temp_filename) def process_video(topic): generate_video_content(topic) with open('data.json', 'r') as f: data = json.load(f) title = data.get('title', '') description = data.get('description', '') tags = ", ".join(data.get('tags', [])) scene_info = [] for scene in data['video']: voiceover_text = scene['voiceover'] voiceover_filename = f"{scene['scene']}_voiceover.mp3" generate_voiceover(voiceover_text, voiceover_filename) voiceover_duration = AudioFileClip(voiceover_filename).duration scene_info.append({'scene': scene['scene'], 'voiceover_filename': voiceover_filename, 'voiceover_duration': voiceover_duration, 'keyword': scene['keyword']}) # Step 3: Fetch videos from Pexels based on portrait orientation for scene in scene_info: video_urls = [get_pexels_video(scene['keyword']) for _ in range(3)] # Fetch 3 videos for each scene video_filenames = [] for video_url in video_urls: if video_url: # Download video file locally video_filename = f"{scene['scene']}_video_{len(video_filenames)}.mp4" with open(video_filename, 'wb') as f: f.write(requests.get(video_url).content) video_filenames.append(video_filename) scene['video_filenames'] = video_filenames # Step 4: Create Scene Videos without resizing scene_videos = [] for scene in scene_info: video_clips = [] for video_filename in scene['video_filenames']: video_clip = VideoFileClip(video_filename) video_clips.append(video_clip) concatenated_clip = concatenate_videoclips(video_clips) # Trim the concatenated clip to match the voiceover duration concatenated_clip = concatenated_clip.subclip(0, scene['voiceover_duration']) # Add audio to video clip concatenated_clip = concatenated_clip.set_audio(AudioFileClip(scene['voiceover_filename'])) scene_videos.append(concatenated_clip) final_filename = title + '.mp4' concatenate_videos_ffmpeg(scene_videos, final_filename) # Clean up downloaded files for scene in scene_info: os.remove(scene['voiceover_filename']) for video_filename in scene['video_filenames']: os.remove(video_filename) return final_filename, title, description, tags iface = gr.Interface( fn=process_video, inputs="text", outputs=["video", "text", "text", "text"], css="footer {visibility: hidden}", description="Generate a free short video just with a word or topic. Best for YouTube, Reels and TikTok. This is a prototype. If you want better software, please inbox or email me at aheedsajid@gmail.com and do like this space. [Click here to Donate](https://nowpayments.io/donation/aheed) Want to make long landscape videos? [Click here](https://huggingface.co/spaces/aheedsajid/invideo-clone)", title="Text to Short Video - Invideo AI Clone" ) iface.launch()