File size: 18,186 Bytes
d4a34ee
1319fb5
 
 
231cbd8
1319fb5
 
231cbd8
a69988b
a3307cf
 
231cbd8
b6703e3
 
 
 
c362691
 
 
 
a3307cf
9e86500
a69988b
 
8094c6f
4d49fca
9e86500
4d49fca
8094c6f
 
 
 
 
 
 
4d49fca
8094c6f
 
 
 
 
4d49fca
8094c6f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b6703e3
c362691
 
 
b6703e3
 
 
a69988b
 
a3307cf
 
231cbd8
1319fb5
a3307cf
 
 
 
 
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
a3307cf
 
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
 
 
 
a3307cf
 
 
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
a3307cf
b6703e3
 
a3307cf
b6703e3
 
 
 
 
 
 
 
2338961
a3307cf
b6703e3
 
 
 
 
 
 
 
 
 
 
 
 
 
a3307cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2338961
a3307cf
231cbd8
a3307cf
 
 
b6703e3
a3307cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b6703e3
a3307cf
 
 
 
1319fb5
6da81fe
 
a3307cf
 
 
 
 
 
6da81fe
1319fb5
a3307cf
b6703e3
4d49fca
 
 
 
b6703e3
4d49fca
 
 
 
 
 
 
 
 
 
 
 
d4a34ee
a3307cf
 
 
 
 
 
 
1319fb5
4d49fca
1319fb5
4d49fca
6da81fe
 
a3307cf
 
 
6da81fe
a3307cf
6da81fe
a3307cf
6da81fe
 
a3307cf
6da81fe
 
a3307cf
 
6da81fe
 
a3307cf
 
9e86500
 
6da81fe
 
1319fb5
6da81fe
 
 
 
 
 
 
 
 
 
 
 
 
 
a3307cf
6da81fe
 
 
 
b6703e3
a3307cf
 
 
 
 
b6703e3
a3307cf
 
 
 
6da81fe
 
 
 
1319fb5
6da81fe
a3307cf
6da81fe
 
 
 
 
 
 
 
 
 
1319fb5
 
a3307cf
6da81fe
 
 
 
 
 
 
 
a3307cf
 
b6703e3
6da81fe
 
 
 
a3307cf
b6703e3
6da81fe
 
a3307cf
6da81fe
1319fb5
a3307cf
 
4d49fca
a3307cf
 
b6703e3
4d49fca
a3307cf
 
4d49fca
b6703e3
9e86500
 
a3307cf
231cbd8
6da81fe
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
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()