├── .gitignore ├── requirements.txt ├── resources.json ├── README.md ├── add.py ├── tts.py └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | api_keys.txt 2 | scripts.json -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | moviepy 3 | pillow 4 | pyttsx3 -------------------------------------------------------------------------------- /resources.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "tts_path": "audio/tts/1.mp3", 4 | "image_generation_prompts": [ 5 | "Man crying with open wallet, no money, melancholic, sad, 8K, depressed, hyperrealistic, 1920x1080", 6 | "One ai beating another ai, using a sword, 16K, anime-style, 1920x1080", 7 | "Happy, smiling person, multiple yellow plus signs in background, standing for benefits, melancholic, hyperrealistic, 1920x1080" 8 | ] 9 | } 10 | ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Marketer 2 | 3 | Automatically generate Short-Form videos for social media platforms like Instagram, TikTok, YouTube, etc. 4 | 5 | # ⚡ Prerequisites 6 | 7 | - Python 3.6 or higher 8 | - HuggingFace API Key 9 | - ElevenLabs API Key 10 | 11 | ## ⚙️ Installation 12 | 13 | ```bash 14 | git clone https://github.com/FujiwaraChoki/Marketer.git 15 | cd Marketer 16 | pip install -r requirements.txt 17 | ``` 18 | 19 | ## 🗣️ Usage 20 | 21 | 22 | 23 | ```bash 24 | python main.py 25 | ``` 26 | 27 | ## 🎫 License 28 | 29 | [MIT](https://choosealicense.com/licenses/mit/) 30 | 31 | ## 🚿 Acknowledgements 32 | 33 | - [ElevenLabs](https://elevenlabs.io/) 34 | - [HuggingFace](https://huggingface.co/) 35 | 36 | ## 🤵🏻 Authors 37 | 38 | - [@FujiwaraChoki](https://www.github.com/FujiwaraChoki) -------------------------------------------------------------------------------- /add.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from moviepy.editor import * 3 | 4 | def combine_audio_sounds(tts_files: List[str]) -> str: 5 | """ 6 | Combine multiple audio files into one. 7 | """ 8 | print("Combining audio files...") 9 | audio_clips = [AudioFileClip(tts_file) for tts_file in tts_files] 10 | final_clip = concatenate_audioclips(audio_clips) 11 | final_clip.write_audiofile("final.mp3") 12 | print("Done!") 13 | 14 | return "final.mp3" 15 | 16 | files = [ 17 | "audio/tts/7af68c49-e3ff-4dde-bdf5-c7f89f3c7350.mp3", 18 | "audio/tts/bd2372c4-dfc2-437b-b300-ea9b54fe4cb4.mp3", 19 | "audio/tts/e7aac85f-c241-4d36-a8c4-07f8f0ffcf30.mp3", 20 | "audio/tts/cc534b1e-57cf-4bf7-a9ef-6b17cec48f3b.mp3", 21 | "audio/tts/fcfa8b8a-296d-4a11-8b58-0e777cfa77c0.mp3", 22 | "audio/tts/c5528af1-097f-435b-8d65-241221af87c8.mp3" 23 | ] 24 | 25 | print(files) 26 | 27 | combine_audio_sounds(files) -------------------------------------------------------------------------------- /tts.py: -------------------------------------------------------------------------------- 1 | import os 2 | import uuid 3 | import requests 4 | 5 | from typing import List 6 | from moviepy.editor import * 7 | 8 | def split_into_sentences(text: str) -> List[str]: 9 | """ 10 | Splits a text into a list of sentences. 11 | """ 12 | return text.split(".") 13 | 14 | def create_random_id() -> str: 15 | """ 16 | Create a random ID for the audio file. 17 | """ 18 | return str(uuid.uuid4()) 19 | 20 | def generate_tts(text: str) -> str: 21 | """ 22 | Generate TTS for a text and return file path. 23 | """ 24 | voice = "adam" 25 | output = f"audio/tts/{create_random_id()}.mp3" 26 | 27 | if os.path.exists(output): 28 | os.remove(output) 29 | 30 | print("Generating TTS...") 31 | r = requests.get(f"https://api.pawan.krd/tts?text={text}&voice={voice}") 32 | 33 | if r.status_code != 200: 34 | print(r.json()) 35 | 36 | with open(output, "wb") as f: 37 | f.write(r.content) 38 | 39 | print("Done!") 40 | 41 | return output 42 | 43 | def combine_audio_sounds(tts_files: List[str]) -> str: 44 | """ 45 | Combine multiple audio files into one. 46 | """ 47 | print("Combining audio files...") 48 | audio_clips = [AudioFileClip(tts_file) for tts_file in tts_files] 49 | final_clip = concatenate_audioclips(audio_clips) 50 | final_clip.write_audiofile("final.mp3") 51 | print("Done!") 52 | 53 | return "final.mp3" 54 | 55 | text = "DID YOU KNOW that the AI industry is worth 15.7 Trillion dollars, and is STILL growing!" 56 | 57 | #sentences = split_into_sentences(text) 58 | 59 | generate_tts(text) 60 | 61 | #final_audio = combine_audio_sounds(tts_files) -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import io 2 | import json 3 | import pyttsx3 4 | import requests 5 | 6 | from moviepy.editor import * 7 | from PIL import Image 8 | 9 | HUGGING_FACE_API_KEY = open('api_keys.txt', 'r').read() 10 | 11 | ENGINE = pyttsx3.init() 12 | 13 | def clean_script_to_file_name(script: str): 14 | return script.replace(' ', '_').replace('\n', '_').replace('\t', '_').replace('\r', '_').lower() 15 | 16 | def generate_images(image_generation_prompts): 17 | file_paths = [] 18 | 19 | headers = {"Authorization": f"Bearer {HUGGING_FACE_API_KEY}"} 20 | 21 | for prompt in image_generation_prompts: 22 | # Generate image 23 | r = requests.post("https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0", headers=headers, json={ 24 | "inputs": prompt 25 | }) 26 | 27 | # Save image 28 | image = Image.open(io.BytesIO(r.content)) 29 | file_name = clean_script_to_file_name(prompt) 30 | file_path = f'./images/{file_name}.png' 31 | image.save(file_path) 32 | 33 | # Add to list of file paths 34 | file_paths.append(file_path) 35 | 36 | return file_paths 37 | 38 | def combine_tts_and_images(tts_file_path, image_file_paths, output_path): 39 | # Load TTS audio 40 | tts_audio = AudioFileClip(tts_file_path) 41 | 42 | # Load images 43 | image_clips = [ImageClip(image_path, duration=tts_audio.duration) for image_path in image_file_paths] 44 | 45 | # Combine audio and images 46 | final_video = concatenate_videoclips([tts_audio.set_audio(None).set_duration(tts_audio.duration)] + image_clips, method="compose") 47 | 48 | # Write the combined video to the output path 49 | final_video.write_videofile(output_path, codec="libx264") 50 | 51 | def main(): 52 | scripts = json.load(open('resources.json', 'r', encoding='utf-8')) 53 | 54 | for script in scripts: 55 | tts_file_path = script['tts_path'] 56 | image_file_paths = generate_images(script['image_generation_prompts']) 57 | output_path = f'./output_videos/{clean_script_to_file_name(script["text"])}.mp4' 58 | combine_tts_and_images(tts_file_path, image_file_paths, output_path) 59 | 60 | if __name__ == '__main__': 61 | main() 62 | --------------------------------------------------------------------------------