Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pixeltable as pxt
|
3 |
+
import os
|
4 |
+
import getpass
|
5 |
+
from pixeltable.functions.video import extract_audio
|
6 |
+
from pixeltable.functions import openai as pxop
|
7 |
+
import openai
|
8 |
+
|
9 |
+
# Set your OpenAI API key
|
10 |
+
if 'OPENAI_API_KEY' not in os.environ:
|
11 |
+
os.environ['OPENAI_API_KEY'] = getpass.getpass('OpenAI API Key:')
|
12 |
+
|
13 |
+
# PixelTable setup
|
14 |
+
db_directory = 'video_db'
|
15 |
+
table_name = 'video_table'
|
16 |
+
|
17 |
+
pxt.drop_dir('video_db', force=True)
|
18 |
+
if table_name in pxt.list_tables():
|
19 |
+
pxt.drop_table('video_db.video_table')
|
20 |
+
|
21 |
+
# Check if the directory exists, if not, create it
|
22 |
+
if db_directory not in pxt.list_dirs():
|
23 |
+
pxt.create_dir(db_directory)
|
24 |
+
else:
|
25 |
+
print(f"Directory {db_directory} already exists. Using the existing directory.")
|
26 |
+
|
27 |
+
# Check if the table exists, if not, create it
|
28 |
+
if table_name not in pxt.list_tables():
|
29 |
+
t = pxt.create_table(f'{db_directory}.{table_name}',
|
30 |
+
{
|
31 |
+
'video': pxt.VideoType(),
|
32 |
+
'video_filename': pxt.StringType(),
|
33 |
+
'sm_type': pxt.StringType(),
|
34 |
+
'sm_post': pxt.StringType()
|
35 |
+
})
|
36 |
+
|
37 |
+
else:
|
38 |
+
t = pxt.load_table(f'{db_directory}.{table_name}')
|
39 |
+
print(f"Table {table_name} already exists. Using the existing table.")
|
40 |
+
|
41 |
+
|
42 |
+
# Function to generate social media post using OpenAI GPT-4 API
|
43 |
+
def generate_social_media_post(transcript_text, social_media_type):
|
44 |
+
response = openai.chat.completions.create(
|
45 |
+
model="gpt-4o-mini-2024-07-18",
|
46 |
+
messages=[
|
47 |
+
{"role": "system", "content": f"You are an expert in creating social media content for {social_media_type}."},
|
48 |
+
{"role": "user", "content": f"Generate an effective and casual social media post based on this video transcript below. Make it a viral and suitable post for {social_media_type}. Transcript:\n{transcript_text}."}
|
49 |
+
],
|
50 |
+
max_tokens=500
|
51 |
+
)
|
52 |
+
return response.choices[0].message.content
|
53 |
+
|
54 |
+
|
55 |
+
# Function to process the uploaded video and generate the post
|
56 |
+
def process_and_generate_post(video_file, social_media_type):
|
57 |
+
if video_file:
|
58 |
+
try:
|
59 |
+
video_size = os.path.getsize(video_file.name) / (1024 * 1024) # Convert to MB
|
60 |
+
|
61 |
+
if video_size > 25:
|
62 |
+
return "The video file is larger than 25 MB. Please upload a smaller file."
|
63 |
+
|
64 |
+
video_filename = os.path.basename(video_file.name)
|
65 |
+
video_df = t.where(t.video_filename == video_filename).tail(1)
|
66 |
+
sm_gen_flag = True
|
67 |
+
|
68 |
+
# Check if video and sm type exists
|
69 |
+
video_type_df = t.where((t.video_filename == video_filename) & (t.sm_type == social_media_type)).tail(1)
|
70 |
+
if video_type_df:
|
71 |
+
print('Video & Type Exists')
|
72 |
+
sm_gen_flag = False
|
73 |
+
|
74 |
+
if video_df and not video_type_df:
|
75 |
+
# Insert video into PixelTable
|
76 |
+
t.insert([{'video': video_file.name, 'video_filename': video_filename, 'sm_type': social_media_type, 'sm_post': ''}])
|
77 |
+
|
78 |
+
# Extract audio from video
|
79 |
+
if not t.get_column(name='audio'):
|
80 |
+
t['audio'] = extract_audio(t.video, format='mp3')
|
81 |
+
else:
|
82 |
+
t.audio = extract_audio(t.video, format='mp3')
|
83 |
+
|
84 |
+
# Transcribe audio using OpenAI Whisper API
|
85 |
+
if not t.get_column(name='transcription'):
|
86 |
+
t['transcription'] = pxop.transcriptions(t.audio, model='whisper-1')
|
87 |
+
else:
|
88 |
+
t.transcription = pxop.transcriptions(t.audio, model='whisper-1')
|
89 |
+
|
90 |
+
cur_video_df = t.where((t.video_filename == video_filename) & (t.sm_type == social_media_type)).tail(1)[0]
|
91 |
+
plain_text = cur_video_df['transcription']['text']
|
92 |
+
|
93 |
+
# Generate social media post using GPT-4
|
94 |
+
social_media_post = generate_social_media_post(plain_text, social_media_type)
|
95 |
+
if sm_gen_flag:
|
96 |
+
cur_video_df.update({'sm_post': social_media_post})
|
97 |
+
|
98 |
+
return cur_video_df['sm_post']
|
99 |
+
|
100 |
+
except Exception as e:
|
101 |
+
return f"An error occurred: {e}"
|
102 |
+
else:
|
103 |
+
return "Please upload a video file."
|
104 |
+
|
105 |
+
|
106 |
+
# Gradio Interface
|
107 |
+
def gradio_interface():
|
108 |
+
with gr.Blocks(theme=gr.themes.Glass()) as demo:
|
109 |
+
gr.Markdown("""<center><font size=12>Video to Social Media Post Generator</center>""")
|
110 |
+
gr.Markdown("""<div align="center">
|
111 |
+
<img src="https://raw.githubusercontent.com/pixeltable/pixeltable/main/docs/source/data/pixeltable-logo-large.png" alt="Pixeltable" width="20%" />
|
112 |
+
""")
|
113 |
+
gr.Markdown("""<center><font size=6>Data Ops powered by <a href="https://github.com/pixeltable/pixeltable">Pixeltable</a></center>""")
|
114 |
+
gr.Markdown("""<center>Pixeltable is a Python library providing a declarative interface for multimodal data (text, images, audio, video). It features built-in versioning, lineage tracking, and incremental updates, enabling users to store, transform, index, and iterate on data for their ML workflows. Data transformations, model inference, and custom logic are embedded as computed columns.
|
115 |
+
|
116 |
+
</center>""")
|
117 |
+
video_input = gr.File(label="Upload Video File (max 25 MB):")
|
118 |
+
social_media_type = gr.Dropdown(choices=["X (Twitter)", "Facebook", "LinkedIn"], label="Select Social Media Platform:", value='X (Twitter)')
|
119 |
+
generate_btn = gr.Button("Generate Post")
|
120 |
+
|
121 |
+
output = gr.Textbox(label="Generated Social Media Post", show_copy_button=True)
|
122 |
+
|
123 |
+
examples = gr.Examples([["example1.mp4"], ["example2.mp4"]], inputs=[video_input])
|
124 |
+
|
125 |
+
generate_btn.click(fn=process_and_generate_post, inputs=[video_input, social_media_type], outputs=[output])
|
126 |
+
|
127 |
+
return demo
|
128 |
+
|
129 |
+
|
130 |
+
gradio_interface().launch(show_api=False)
|