Spaces:
Running
Running
# Keep all existing imports and add any new ones needed | |
import gradio as gr | |
import random | |
from datetime import datetime | |
import tempfile | |
import os | |
import edge_tts | |
import asyncio | |
import warnings | |
import pytz | |
import re | |
import json | |
import pandas as pd | |
from pathlib import Path | |
from gradio_client import Client | |
warnings.filterwarnings('ignore') | |
# Add constants for community generations | |
PAGE_SIZE = 10 | |
FILE_DIR_PATH = "gallery" # Using existing gallery directory | |
# Keep existing STORY_STARTERS array | |
# Keep all existing functions through play_gallery_audio() | |
def list_all_outputs(generation_history): | |
"""Load all story generations for community view""" | |
try: | |
directory_path = FILE_DIR_PATH | |
if not os.path.exists(directory_path): | |
return "", gr.update(visible=True) | |
# Get all matched pairs of story/audio files | |
file_pairs = [] | |
for story_file in Path(directory_path).glob("story_*.md"): | |
timestamp = story_file.stem.split('_')[1] | |
audio_pattern = f"audio_{timestamp}_*.mp3" | |
audio_files = list(Path(directory_path).glob(audio_pattern)) | |
if audio_files: # Only include if we have both story and audio | |
file_pairs.append((story_file, audio_files[0])) | |
# Sort by modification time, newest first | |
file_pairs.sort(key=lambda x: os.path.getmtime(x[0]), reverse=True) | |
history_list = generation_history.split(',') if generation_history else [] | |
updated_files = [str(audio) for _, audio in file_pairs if str(audio) not in history_list] | |
updated_history = updated_files + history_list | |
return ','.join(updated_history), gr.update(visible=True) | |
except Exception as e: | |
print(f"Error loading community generations: {str(e)}") | |
return "", gr.update(visible=True) | |
def increase_list_size(list_size): | |
"""Increase the number of visible community generations""" | |
return list_size + PAGE_SIZE | |
# Add CSS for community generations | |
css = ''' | |
#live_gen:before { | |
content: ''; | |
animation: svelte-z7cif2-pulseStart 1s cubic-bezier(.4,0,.6,1), svelte-z7cif2-pulse 2s cubic-bezier(.4,0,.6,1) 1s infinite; | |
border: 2px solid var(--color-accent); | |
background: transparent; | |
z-index: var(--layer-1); | |
pointer-events: none; | |
position: absolute; | |
height: 100%; | |
width: 100%; | |
border-radius: 7px; | |
} | |
#live_gen_items{ | |
max-height: 570px; | |
overflow-y: scroll; | |
} | |
''' | |
# Modified Gradio interface | |
with gr.Blocks(title="AI Story Generator", css=css) as demo: | |
gr.Markdown(""" | |
# π AI Story Generator & Narrator | |
Generate creative stories, listen to them, and build your gallery! | |
""") | |
# Add hidden state for community generations | |
generation_history = gr.Textbox(visible=False) | |
list_size = gr.Number(value=PAGE_SIZE, visible=False) | |
with gr.Row(): | |
# Keep existing left column | |
with gr.Column(scale=3): | |
with gr.Row(): | |
prompt_input = gr.Textbox( | |
label="Story Concept", | |
placeholder="Enter your story idea...", | |
lines=3 | |
) | |
with gr.Row(): | |
model_choice = gr.Dropdown( | |
label="Model", | |
choices=[ | |
"mistralai/Mixtral-8x7B-Instruct-v0.1", | |
"mistralai/Mistral-7B-Instruct-v0.2" | |
], | |
value="mistralai/Mixtral-8x7B-Instruct-v0.1" | |
) | |
generate_btn = gr.Button("Generate Story") | |
with gr.Row(): | |
story_output = gr.Textbox( | |
label="Generated Story", | |
lines=10, | |
interactive=False | |
) | |
with gr.Row(): | |
audio_output = gr.Audio( | |
label="Story Narration", | |
type="filepath" | |
) | |
# Modify right column to include community generations | |
with gr.Column(scale=1): | |
gr.Markdown("### π Story Starters") | |
story_starters = gr.Dataframe( | |
value=STORY_STARTERS, | |
headers=["Category", "Starter"], | |
interactive=False | |
) | |
# Add Community Generations section | |
with gr.Column(elem_id="live_gen") as community_list: | |
gr.Markdown("### π¬ Community Stories") | |
with gr.Column(elem_id="live_gen_items"): | |
def show_output_list(generation_history, list_size): | |
history_list = generation_history.split(',') if generation_history else [] | |
history_list_latest = history_list[:list_size] | |
for audio_path in history_list_latest: | |
if not audio_path: | |
continue | |
try: | |
# Get corresponding story file | |
story_path = audio_path.replace('audio_', 'story_').replace('.mp3', '.md') | |
if not os.path.exists(story_path): | |
continue | |
# Read story content | |
with open(story_path, 'r') as file: | |
story_content = file.read() | |
# Extract title from markdown | |
title = story_content.split('\n')[0].replace('# ', '') | |
with gr.Group(): | |
gr.Markdown(value=f"### {title}") | |
gr.Audio(value=audio_path) | |
except Exception as e: | |
print(f"Error showing generation: {str(e)}") | |
continue | |
load_more = gr.Button("Load More Stories") | |
load_more.click(fn=increase_list_size, inputs=list_size, outputs=list_size) | |
# Keep existing event handlers | |
def update_prompt(evt: gr.SelectData): | |
return STORY_STARTERS[evt.index[0]][1] | |
story_starters.select(update_prompt, None, prompt_input) | |
generate_btn.click( | |
fn=process_story_and_audio, | |
inputs=[prompt_input, model_choice], | |
outputs=[story_output, audio_output, gallery] | |
) | |
# Add auto-refresh for community generations | |
demo.load(fn=list_all_outputs, inputs=generation_history, outputs=[generation_history, community_list], every=2) | |
if __name__ == "__main__": | |
demo.launch() |