import os import time import logging import gradio as gr logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Modal setup with proper secret handling MODAL_AVAILABLE = False generate_content_with_llm = None try: import modal logger.info(f"Modal version: {modal.__version__}") # Check for Modal tokens - HuggingFace should have both ID and SECRET modal_token_id = os.environ.get("MODAL_TOKEN_ID") modal_token_secret = os.environ.get("MODAL_TOKEN_SECRET") if modal_token_id and modal_token_secret: try: # Try to connect to your deployed Modal functions using the new API logger.info("šŸ”„ Attempting to connect to Modal functions...") # First try the main AI function try: generate_content_with_llm = modal.Function.from_name( "content-creation-agent", "generate_content_with_llm" ) # Test connection with health check health_check_func = modal.Function.from_name( "content-creation-agent", "health_check" ) # Test if Modal is working test_result = health_check_func.remote() logger.info(f"āœ… Modal health check passed: {test_result}") MODAL_AVAILABLE = True logger.info("āœ… Modal successfully connected to main AI function") except Exception as e: logger.warning(f"āš ļø Modal main function connection failed: {e}") # Try fallback function instead (this one we know works) try: generate_content_with_llm = modal.Function.from_name( "content-creation-agent", "generate_fallback_content" ) # Still test health check health_check_func = modal.Function.from_name( "content-creation-agent", "health_check" ) test_result = health_check_func.remote() logger.info(f"āœ… Modal health check passed: {test_result}") MODAL_AVAILABLE = True logger.info("āœ… Modal connected using fallback function (still high quality!)") except Exception as e2: logger.warning(f"āš ļø Modal fallback also failed: {e2}") MODAL_AVAILABLE = False except Exception as main_e: logger.warning(f"āš ļø Modal connection failed: {main_e}") MODAL_AVAILABLE = False else: logger.warning("āš ļø MODAL_TOKEN_ID and MODAL_TOKEN_SECRET not found in environment variables") logger.info("šŸ’” To fix this, add MODAL_TOKEN_ID and MODAL_TOKEN_SECRET to your HuggingFace Space environment variables") except ImportError: logger.warning("āš ļø Modal package not available") except Exception as e: logger.warning(f"āš ļø Modal setup failed: {e}") logger.info(f"Modal Status: {'āœ… Available' if MODAL_AVAILABLE else 'āŒ Unavailable'}") def generate_fallback_content(lyrics, artist, title): """High-quality local content generation""" # Analyze lyrics for themes and mood lyrics_lower = lyrics.lower() # Advanced mood detection mood = "uplifting" if any(word in lyrics_lower for word in ['cry', 'tear', 'pain', 'hurt', 'lost', 'broken', 'sad', 'lonely', 'dark']): mood = "emotional" elif any(word in lyrics_lower for word in ['energy', 'power', 'fire', 'strong', 'fight', 'drive', 'force', 'intense']): mood = "energetic" elif any(word in lyrics_lower for word in ['love', 'happy', 'joy', 'hope', 'dream', 'light', 'beautiful', 'amazing']): mood = "inspiring" # Extract themes with better detection theme_words = [] if any(word in lyrics_lower for word in ['love', 'heart', 'romance', 'kiss', 'together']): theme_words.append('love') if any(word in lyrics_lower for word in ['dream', 'hope', 'future', 'tomorrow', 'vision']): theme_words.append('dreams') if any(word in lyrics_lower for word in ['night', 'dark', 'star', 'moon', 'midnight']): theme_words.append('night') if any(word in lyrics_lower for word in ['life', 'living', 'journey', 'path', 'way']): theme_words.append('life') if any(word in lyrics_lower for word in ['freedom', 'free', 'escape', 'break', 'liberation']): theme_words.append('freedom') if any(word in lyrics_lower for word in ['time', 'moment', 'forever', 'always', 'memory']): theme_words.append('time') themes_text = ', '.join(theme_words[:3]) if theme_words else 'deep emotions' # Advanced genre detection genre = 'indie' if any(word in lyrics_lower for word in ['rock', 'guitar', 'band', 'drums', 'electric', 'amp']): genre = 'rock' elif any(word in lyrics_lower for word in ['pop', 'radio', 'catchy', 'dance', 'party', 'club']): genre = 'pop' elif any(word in lyrics_lower for word in ['rap', 'flow', 'beats', 'hip', 'street', 'rhyme']): genre = 'hiphop' elif any(word in lyrics_lower for word in ['electronic', 'synth', 'edm', 'techno', 'digital']): genre = 'electronic' elif any(word in lyrics_lower for word in ['acoustic', 'folk', 'country', 'traditional']): genre = 'acoustic' # Premium hashtag generation base_hashtags = { 'youtube': [f'{genre}music', 'newmusic', 'musicvideo', f'{mood}music', 'originalmusic', 'independentartist', 'songwriter', 'musicdiscovery', 'viral', 'subscribe', 'newrelease', 'musicproducer', 'instamusic', 'unsignedartist', 'emergingartist'], 'twitter': [f'{genre}', 'newmusic', 'nowplaying', f'{mood}', 'musicvideo', 'viral'], 'instagram': [f'{genre}vibes', 'newmusic', 'instamusic', f'{mood}', 'musicpost', 'originalmusic', 'artist', 'viral', 'trending', 'musiclover', 'songwriter', 'independentartist', 'newrelease', 'musicdiscovery', 'vibes'], 'facebook': [f'{genre}music', 'newmusic', 'originalmusic', f'{mood}', 'musicvideo', 'viral'], 'minds': ['independentmusic', 'originalmusic', 'newmusic', 'creative', 'authentic'], 'gab': ['originalmusic', 'independent', 'authentic', 'realmusic', 'newmusic'] } # Add theme-based hashtags for platform in base_hashtags: for theme in theme_words[:2]: # Add top 2 themes base_hashtags[platform].append(f'{theme}music') # Format hashtags with proper limits hashtags = {} limits = {'youtube': 15, 'instagram': 15, 'twitter': 6, 'facebook': 6, 'minds': 5, 'gab': 5} for platform, tags in base_hashtags.items(): limit = limits.get(platform, 10) formatted_tags = ' '.join(f'#{tag}' for tag in tags[:limit]) hashtags[platform] = formatted_tags artist_display = artist if artist.strip() else "Anonymous Artist" by_artist = f" - {artist_display}" if artist.strip() else "" if artist.strip(): # Content with artist name return { 'youtube': f"""šŸŽµ {title}{by_artist} šŸŽµ Experience this latest music video! This {mood} track explores themes of {themes_text}. šŸŽ¬ Watch the full music video above šŸ’æ Stream on all platforms šŸ”” Subscribe for more music videos šŸ‘ Like if you enjoyed this track šŸ“ LYRICS: {lyrics} {hashtags['youtube']}""", 'twitter': f"šŸŽµ NEW MUSIC VIDEO: '{title}'{by_artist} is here! This {mood} track will give you all the feels šŸ’«\n\nšŸŽ¬ Watch: [Link]\n\n{hashtags['twitter']}", 'instagram': f"""šŸŽµāœØ '{title}' Official Music Video is LIVE! āœØšŸŽµ {artist_display} delivers another {mood} masterpiece that speaks to the soul šŸ’« šŸŽ¬ Full video in bio šŸ’­ What's your favorite lyric? Comment below! {hashtags['instagram']}""", 'facebook': f"""šŸŽµ MUSIC VIDEO PREMIERE šŸŽµ New music video for '{title}'{by_artist} just dropped! This {mood} track captures the essence of {themes_text} in a beautiful way. The visuals perfectly complement the powerful lyrics. šŸŽ¬ Watch the full video now! šŸ’¬ Let us know what you think in the comments šŸ”„ Share with friends who love good music {hashtags['facebook']}""", 'minds': f"""šŸŽµ New Music Alert! {artist_display} - '{title}' Official Music Video This {mood} track showcases incredible artistry and meaningful lyrics. Independent artists like {artist_display} are creating the future of music. Support independent music and check out this latest release! {hashtags['minds']}""", 'gab': f"""New Music Video Drop! '{title}'{by_artist} Real music with real meaning. This {mood} track reminds us why authentic artistry matters in today's world. Give it a listen and support independent creators! {hashtags['gab']}""" } else: # Anonymous content return { 'youtube': f"""šŸŽµ {title} šŸŽµ Experience this captivating music video! This {mood} track explores themes of {themes_text}. šŸŽ¬ Watch the full music video above šŸ’æ Available on all streaming platforms šŸ”” Subscribe for more amazing music videos šŸ‘ Like if this track moved you šŸ“ LYRICS: {lyrics} {hashtags['youtube']}""", 'twitter': f"šŸŽµ NEW MUSIC VIDEO: '{title}' is here! This {mood} track will give you all the feels šŸ’«\n\nšŸŽ¬ Watch: [Link]\n\n{hashtags['twitter']}", 'instagram': f"""šŸŽµāœØ '{title}' Official Music Video is LIVE! āœØšŸŽµ Another {mood} masterpiece that speaks to the soul šŸ’« šŸŽ¬ Full video in bio šŸ’­ What's your favorite lyric? Comment below! {hashtags['instagram']}""", 'facebook': f"""šŸŽµ MUSIC VIDEO PREMIERE šŸŽµ '{title}' official music video just dropped! This {mood} track captures the essence of {themes_text} in a beautiful way. The visuals perfectly complement the powerful lyrics. šŸŽ¬ Watch the full video now! šŸ’¬ Let us know what you think in the comments šŸ”„ Share with friends who love good music {hashtags['facebook']}""", 'minds': f"""šŸŽµ New Music Alert! '{title}' Official Music Video This {mood} track showcases incredible artistry and meaningful lyrics. Independent music continues to push creative boundaries. Support independent music and check out this latest release! {hashtags['minds']}""", 'gab': f"""New Music Video Drop! '{title}' Real music with real meaning. This {mood} track reminds us why authentic artistry matters in today's world. Give it a listen and support independent creators! {hashtags['gab']}""" } def generate_all_content(lyrics, artist, title, use_modal): """Generate content with Modal toggle""" if not lyrics.strip() or not title.strip(): error_msg = "āŒ Please provide both lyrics and song title" return [""] * 6 + [error_msg] start_time = time.time() # Initial yield - empty outputs and loading status empty_outputs = [""] * 6 if use_modal and MODAL_AVAILABLE: status_msg = "ā³ Generating content with Modal AI..." else: status_msg = "ā³ Generating content with local templates..." yield empty_outputs + [status_msg] try: if use_modal and MODAL_AVAILABLE and generate_content_with_llm: # Try Modal AI generation try: logger.info("šŸ”„ Attempting Modal AI generation...") result = generate_content_with_llm.remote(lyrics, artist, title) # Validate result if isinstance(result, dict) and len(result) > 0: content = result status_msg = f"āœ… Generated with Modal AI in {time.time() - start_time:.2f}s" logger.info("āœ… Modal AI generation successful") else: raise ValueError("Invalid result from Modal function") except Exception as modal_error: logger.warning(f"āš ļø Modal AI generation failed: {modal_error}") # Fall back to local generation content = generate_fallback_content(lyrics, artist, title) status_msg = f"āš ļø Modal failed, used local fallback in {time.time() - start_time:.2f}s" else: # Use local fallback if use_modal and not MODAL_AVAILABLE: status_msg = "āš ļø Modal unavailable, using local generation..." content = generate_fallback_content(lyrics, artist, title) if not (use_modal and not MODAL_AVAILABLE): status_msg = f"āœ… Generated with local templates in {time.time() - start_time:.2f}s" except Exception as e: logger.error(f"āŒ Unexpected error: {e}") content = generate_fallback_content(lyrics, artist, title) status_msg = f"āŒ Error occurred, used local fallback in {time.time() - start_time:.2f}s" # Final yield - actual content for each platform + status platforms = ['youtube', 'twitter', 'instagram', 'facebook', 'minds', 'gab'] platform_outputs = [content.get(platform, f"Error generating {platform} content") for platform in platforms] yield platform_outputs + [status_msg] # Create Gradio interface with gr.Blocks(theme=gr.themes.Soft(), title="šŸŽµ Music Content Creator") as demo: gr.Markdown(f""" # šŸŽµ AI Content Generator for Musicians šŸŽ¬ Transform your song lyrics into compelling social media content! **✨ Features:** - šŸ¤– AI-powered content generation (when Modal is available) - šŸ“± Platform-optimized content for YouTube, Twitter, Instagram, Facebook, Minds, and Gab - šŸŽÆ Smart hashtag generation based on lyrics analysis - šŸŽ¤ Support for both named artists and anonymous releases **šŸ”§ Backend Status:** {"🟢 Modal Available" if MODAL_AVAILABLE else "🟔 Local Mode Only"} {"" if MODAL_AVAILABLE else "šŸ’” **To enable AI generation:** Add your Modal token to the HuggingFace Space environment variables"} """) with gr.Row(): with gr.Column(scale=2): lyrics_input = gr.Textbox( lines=8, label="šŸŽµ Song Lyrics", placeholder="Enter your complete song lyrics here...", info="Paste the full lyrics of your song" ) with gr.Column(scale=1): artist_input = gr.Textbox( label="šŸŽ¤ Artist Name", placeholder="Artist Name (Optional)", info="Leave blank for anonymous releases" ) title_input = gr.Textbox( label="šŸŽµ Song Title", placeholder="Song Title", info="The title of your song" ) # Modal toggle modal_toggle = gr.Radio( choices=[ ("šŸ¤– AI Generation (Modal)", True), ("šŸ“ Local Templates", False) ], value=MODAL_AVAILABLE, # Default to Modal if available, otherwise local label="Generation Method", info="Choose between AI-powered generation or local templates" ) run_button = gr.Button("šŸš€ Generate Content", variant="primary", size="lg") gr.Markdown("## šŸ“± Generated Social Media Content") with gr.Row(): with gr.Column(): youtube_output = gr.Textbox(label="šŸ“ŗ YouTube Description", lines=12) twitter_output = gr.Textbox(label="🐦 Twitter/X Post", lines=4) instagram_output = gr.Textbox(label="šŸ“ø Instagram Caption", lines=6) with gr.Column(): facebook_output = gr.Textbox(label="šŸ“˜ Facebook Post", lines=6) minds_output = gr.Textbox(label="🧠 Minds Post", lines=4) gab_output = gr.Textbox(label="šŸ’¬ Gab Post", lines=4) status = gr.Markdown("Ready to generate content!") # Connect the function with proper outputs run_button.click( fn=generate_all_content, inputs=[lyrics_input, artist_input, title_input, modal_toggle], outputs=[youtube_output, twitter_output, instagram_output, facebook_output, minds_output, gab_output, status] ) # Add examples gr.Examples( examples=[ [ "Here's an example with some sample lyrics\nAbout dreams and aspirations\nReaching for the stars tonight\nNothing's gonna stop this fight\nWe'll keep on climbing higher\nUntil we touch the sky", "", # Empty artist name "Dreams Tonight", MODAL_AVAILABLE # Use Modal if available ], [ "Love is in the air tonight\nHearts beating as one\nDancing under moonlight\nUntil the morning sun\nThis feeling never ends\nLove conquers all", "Romantic Vibes", "Moonlight Dance", False # Use local generation ] ], inputs=[lyrics_input, artist_input, title_input, modal_toggle], label="šŸ’” Try these examples" ) # Add footer with info gr.Markdown(f""" --- **šŸ’” Tips:** - **AI Generation:** Uses GPT-2 on Modal for creative, context-aware content - **Local Templates:** Fast, rule-based generation that always works - **Modal Credits:** Can be used for LLM inference and GPU-intensive functions ([Modal Docs](https://modal.com/docs)) - **Best Results:** Include rich, descriptive lyrics for better theme detection **šŸ”§ Status:** {"āœ… Modal Working" if MODAL_AVAILABLE else "🟔 Local Mode Only"} {"" if MODAL_AVAILABLE else "**To enable Modal AI:** Add MODAL_TOKEN to your HuggingFace Space environment variables"} """) if __name__ == "__main__": demo.launch()