|
import gradio as gr |
|
import asyncio |
|
from pathlib import Path |
|
from utils.content_generator import ContentGenerator, ContentRequest |
|
from utils.youtube_utils import get_transcript, extract_video_id |
|
|
|
class TranscriptProcessor: |
|
def __init__(self): |
|
self.generator = ContentGenerator() |
|
|
|
def _get_youtube_transcript(self, url: str) -> str: |
|
"""Get transcript from YouTube URL.""" |
|
try: |
|
if video_id := extract_video_id(url): |
|
return get_transcript(video_id) |
|
raise Exception("Invalid YouTube URL") |
|
except Exception as e: |
|
raise Exception(f"Error fetching YouTube transcript: {str(e)}") |
|
|
|
async def process_transcript(self, input_text: str): |
|
"""Process input and generate all content.""" |
|
try: |
|
|
|
transcript = ( |
|
self._get_youtube_transcript(input_text) |
|
if any(x in input_text for x in ["youtube.com", "youtu.be"]) |
|
else input_text |
|
) |
|
|
|
|
|
requests = [ |
|
ContentRequest("previews", max_tokens=8192), |
|
ContentRequest("clips", max_tokens=8192), |
|
ContentRequest("description"), |
|
ContentRequest("timestamps"), |
|
ContentRequest("titles_and_thumbnails"), |
|
] |
|
|
|
|
|
results = await asyncio.gather( |
|
*[self.generator.generate_content(req, transcript) for req in requests] |
|
) |
|
return tuple(results) |
|
|
|
except Exception as e: |
|
return (f"Error processing input: {str(e)}",) * 5 |
|
|
|
def update_prompts(self, *values) -> str: |
|
"""Update the current session's prompts.""" |
|
self.generator.current_prompts.update(zip( |
|
["previews", "clips", "description", "timestamps", "titles_and_thumbnails"], |
|
values |
|
)) |
|
return "Prompts updated for this session!" |
|
|
|
def create_interface(): |
|
"""Create the Gradio interface.""" |
|
processor = TranscriptProcessor() |
|
|
|
with gr.Blocks(title="Podcast Transcript Analyzer") as app: |
|
with gr.Tab("Generate Content"): |
|
gr.Markdown("# Podcast Content Generator") |
|
input_text = gr.Textbox(label="Input", placeholder="YouTube URL or transcript...", lines=10) |
|
submit_btn = gr.Button("Generate Content") |
|
outputs = [ |
|
gr.Textbox(label=label, lines=10, interactive=False) |
|
for label in ["Preview Clips", "Twitter Clips", "Twitter Description", "Timestamps", "Title & Thumbnail Suggestions"] |
|
] |
|
|
|
async def process_wrapper(text): |
|
return await processor.process_transcript(text) |
|
|
|
submit_btn.click(fn=process_wrapper, inputs=[input_text], outputs=outputs) |
|
|
|
with gr.Tab("Experiment with Prompts"): |
|
gr.Markdown("# Experiment with Prompts") |
|
gr.Markdown( |
|
""" |
|
Here you can experiment with different prompts during your session. |
|
Changes will remain active until you reload the page. |
|
|
|
Tip: Copy your preferred prompts somewhere safe if you want to reuse them later! |
|
""" |
|
) |
|
|
|
prompt_inputs = [ |
|
gr.Textbox( |
|
label="Preview Clips Prompt", lines=10, value=processor.generator.current_prompts["previews"] |
|
), |
|
gr.Textbox( |
|
label="Clips Prompt", lines=10, value=processor.generator.current_prompts["clips"] |
|
), |
|
gr.Textbox( |
|
label="Description Prompt", |
|
lines=10, |
|
value=processor.generator.current_prompts["description"], |
|
), |
|
gr.Textbox( |
|
label="Timestamps Prompt", |
|
lines=10, |
|
value=processor.generator.current_prompts["timestamps"], |
|
), |
|
gr.Textbox( |
|
label="Titles & Thumbnails Prompt", |
|
lines=10, |
|
value=processor.generator.current_prompts["titles_and_thumbnails"], |
|
), |
|
] |
|
status = gr.Textbox(label="Status", interactive=False) |
|
|
|
|
|
for prompt in prompt_inputs: |
|
prompt.change(fn=processor.update_prompts, inputs=prompt_inputs, outputs=[status]) |
|
|
|
|
|
reset_btn = gr.Button("Reset to Default Prompts") |
|
reset_btn.click( |
|
fn=lambda: ( |
|
processor.update_prompts(*processor.generator.current_prompts.values()), |
|
*processor.generator.current_prompts.values(), |
|
), |
|
outputs=[status] + prompt_inputs, |
|
) |
|
|
|
return app |
|
|
|
if __name__ == "__main__": |
|
create_interface().launch() |
|
|