├── img.png ├── README.md └── app.py /img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nidepapa/video-director/HEAD/img.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vlog-Director 2 | 3 | An automate vlog/video script generator empowered by Metaphor and OpenAI. 4 | 5 | ## Usage 6 | 7 | Download the package 8 | 9 | ```bash 10 | python3 app.py 11 | ``` 12 | 13 | ## Demo 14 | 15 | ```bash 16 | python3 app.py Los Angeles 17 | ``` 18 | 19 | created a script with 3 scenes about LA 20 | 21 | ![img.png](img.png) 22 | 23 | ## API - getMetaphorSearch 24 | 25 | Will interpret user's natural language search to a metaphor query 26 | and return blog content of recent (3 months) related to input tourism attractions 27 | 28 | ```python 29 | 30 | def getMetaphorSearch(self, city): 31 | USER_QUESTION = "What's the popular travelling blog only about {}?".format(city) 32 | SYSTEM_MESSAGE = "You are a helpful assistant that generates search queiries based on user questions. Only generate one search query." 33 | 34 | completion = openai.ChatCompletion.create( 35 | model="gpt-3.5-turbo", 36 | messages=[ 37 | {"role": "system", "content": SYSTEM_MESSAGE}, 38 | {"role": "user", "content": USER_QUESTION}, 39 | ], 40 | ) 41 | 42 | date_90_days_ago = datetime.now() - timedelta(days=90) 43 | # Format the date as "YYYY-MM-DD" 44 | formatted_date = date_90_days_ago.strftime("%Y-%m-%d") 45 | 46 | query = completion.choices[0].message.content 47 | search_response = self.metaphor.search( 48 | query, use_autoprompt=True, start_published_date=formatted_date 49 | ) 50 | 51 | return search_response.get_contents() 52 | ``` 53 | 54 | ## API - vlogScriptGenerator 55 | 56 | Will generate a vlog script based on the very first blog content(for demo purpose) 57 | and return in a formatted string 58 | 59 | ```python 60 | def vlogScriptGenerator(self, search_result): 61 | # choose the very first result as demo 62 | first_content = search_result.contents[0] 63 | SYSTEM_MESSAGE = "You are a helpful assistant that generates vlog script with multiple scenes based on blog " \ 64 | "content." 65 | ASSISTANT_MESSAGE = "some context" 66 | completion = openai.ChatCompletion.create( 67 | model="gpt-3.5-turbo", 68 | messages=[ 69 | {"role": "system", "content": SYSTEM_MESSAGE}, 70 | {"role": "user", "name": "example_user", "content": "help me to generate a random script with some " 71 | "scenes"}, 72 | {"role": "system", "name": "example_assistant", 73 | "content": ASSISTANT_MESSAGE}, 74 | {"role": "user", "content": first_content.extract}, 75 | ], 76 | ) 77 | 78 | result_script = completion.choices[0].message.content 79 | return "Vlog script for {0}: {1}".format(first_content.title, result_script) 80 | ``` 81 | 82 | ## Reference 83 | 84 | metaphor API: 85 | 86 | https://github.com/metaphorsystems/metaphor-python 87 | 88 | OpenAI API: 89 | 90 | https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models 91 | 92 | # Future work 93 | 1. more arguments can be added to make this API more customized, so people can choose any locations they prefer 94 | 2. database can be added to store user preference history for future analysis, like who can be the potential content maker for video platform like Youtube -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import os 2 | import openai 3 | from metaphor_python import Metaphor 4 | from datetime import datetime, timedelta 5 | import sys 6 | 7 | os.environ["OPENAI_API_KEY"] = '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' 8 | os.environ["METAPHOR_API_KEY"] = '3ba9f09f-34e0-493e-a6e2-835304c79916' 9 | 10 | 11 | class VideoDirector: 12 | def __init__(self): 13 | self.metaphor = Metaphor(os.getenv("METAPHOR_API_KEY")) 14 | openai.api_key = os.getenv("OPENAI_API_KEY") 15 | 16 | def getMetaphorSearch(self, city): 17 | USER_QUESTION = "What's the popular travelling blog only about {}?".format(city) 18 | SYSTEM_MESSAGE = "You are a helpful assistant that generates search queiries based on user questions. Only generate one search query." 19 | 20 | completion = openai.ChatCompletion.create( 21 | model="gpt-3.5-turbo", 22 | messages=[ 23 | {"role": "system", "content": SYSTEM_MESSAGE}, 24 | {"role": "user", "content": USER_QUESTION}, 25 | ], 26 | ) 27 | 28 | date_90_days_ago = datetime.now() - timedelta(days=90) 29 | 30 | # Format the date as "YYYY-MM-DD" 31 | formatted_date = date_90_days_ago.strftime("%Y-%m-%d") 32 | 33 | query = completion.choices[0].message.content 34 | search_response = self.metaphor.search( 35 | query, use_autoprompt=True, start_published_date=formatted_date 36 | ) 37 | 38 | return search_response.get_contents() 39 | 40 | def vlogScriptGenerator(self, search_result): 41 | # choose the very first result as demo 42 | first_content = search_result.contents[0] 43 | SYSTEM_MESSAGE = "You are a helpful assistant that generates vlog script with multiple scenes based on blog " \ 44 | "content." 45 | ASSISTANT_MESSAGE = "[SCENE 1: Mount Rainier's Grandeur] Narrator (Voiceover): (Proudly) 'Ascending to 14," \ 46 | "410 feet above sea level, Mount Rainier stands as an icon in the Washington landscape.' " \ 47 | "[Visuals: Breathtaking aerial views of Mount Rainier] Narrator (Voiceover): 'An active " \ 48 | "volcano, Mount Rainier is the most glaciated peak in the contiguous U.S.A., " \ 49 | "spawning five major rivers.' [Visuals: Time-lapse shots of glaciers and rivers] Narrator " \ 50 | "(Voiceover): 'Subalpine wildflower meadows ring the icy volcano while ancient forest " \ 51 | "cloaks Mount Rainier’s lower slopes.' [Visuals: Vibrant wildflowers and lush forest] " \ 52 | "Narrator (Voiceover): 'Wildlife abounds in the park’s ecosystems. A lifetime of " \ 53 | "discovery awaits.' [Visuals: Wildlife, including deer, bears, and birds] [SCENE 2: " \ 54 | "Exploring the Park Narrator (Voiceover): 'Now, let's explore the opportunities that " \ 55 | "await you at Mount Rainier National Park. [Visual transition: A map of the park with " \ 56 | "various icons highlighting key locations] [SCENE 3: Road Status] Narrator (Voiceover): " \ 57 | "'First, let's check out the road status.' [Visuals: A map showing road conditions] " \ 58 | "Narrator (Voiceover): 'Find out current road conditions, including access to Paradise " \ 59 | "during the winter season.' [Visuals: Snowy roads nnnnnnn and tire chains]" 60 | 61 | completion = openai.ChatCompletion.create( 62 | model="gpt-3.5-turbo", 63 | messages=[ 64 | {"role": "system", "content": SYSTEM_MESSAGE}, 65 | {"role": "user", "name": "example_user", "content": "help me to generate a random script with some " 66 | "scenes"}, 67 | {"role": "system", "name": "example_assistant", 68 | "content": ASSISTANT_MESSAGE}, 69 | {"role": "user", "content": first_content.extract}, 70 | ], 71 | ) 72 | 73 | result_script = completion.choices[0].message.content 74 | return "Vlog script for {0}: {1}".format(first_content.title, result_script) 75 | 76 | 77 | if __name__ == "__main__": 78 | director = VideoDirector() 79 | city = sys.argv[1] 80 | query_content = director.getMetaphorSearch(city) 81 | demo_script = director.vlogScriptGenerator(query_content) 82 | print(demo_script) 83 | --------------------------------------------------------------------------------