Spaces:
Sleeping
Sleeping
| import os | |
| import logging | |
| import requests | |
| import random | |
| from PIL import Image, ImageDraw | |
| from io import BytesIO | |
| from pytrends.request import TrendReq | |
| from moviepy.editor import ImageClip, AudioFileClip | |
| from gtts import gTTS | |
| import gradio as gr | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
| ASSETS_DIR = "assets" | |
| os.makedirs(ASSETS_DIR, exist_ok=True) | |
| def fetch_trending_topic(): | |
| try: | |
| logging.info("Fetching trending topics from Google...") | |
| pytrends = TrendReq(hl='en-US', tz=360) | |
| pytrends.build_payload(kw_list=[""]) | |
| trending = pytrends.trending_searches(pn='united_states') | |
| topic = random.choice(trending[0].tolist()) | |
| logging.info(f"Trending Topic Fetched: {topic}") | |
| return topic | |
| except Exception as e: | |
| logging.error(f"Failed to fetch trends: {e}") | |
| fallback_topics = ["Global News", "AI Breakthrough", "SpaceX Launch", "Stock Market Update"] | |
| fallback = random.choice(fallback_topics) | |
| logging.info(f"Using fallback trending topic: {fallback}") | |
| return fallback | |
| def summarize_news(news_text): | |
| logging.info(f"Summarizing news: {news_text}") | |
| summary = news_text + " Follow us on Facebook and Twitter to see what's trending." | |
| logging.info(f"Summary generated: {summary}") | |
| return summary | |
| def generate_tts(summary_text): | |
| try: | |
| logging.info("Generating TTS audio...") | |
| tts = gTTS(summary_text) | |
| audio_path = os.path.join(ASSETS_DIR, "news_audio.wav") | |
| tts.save(audio_path) | |
| logging.info(f"TTS audio saved to {audio_path}") | |
| return audio_path | |
| except Exception as e: | |
| logging.error(f"TTS generation failed: {e}") | |
| return None | |
| def fetch_image(): | |
| try: | |
| img_url = "https://picsum.photos/800/600" | |
| logging.info(f"Fetching image from {img_url}") | |
| response = requests.get(img_url) | |
| if response.status_code == 200: | |
| img = Image.open(BytesIO(response.content)) | |
| img_path = os.path.join(ASSETS_DIR, "news_img.jpg") | |
| img.save(img_path) | |
| logging.info("Image fetched and saved.") | |
| return img_path | |
| else: | |
| raise ValueError("Image fetch returned non-200") | |
| except Exception as e: | |
| logging.error(f"Image fetch failed: {e}") | |
| return None | |
| def create_video(image_path, audio_path): | |
| try: | |
| logging.info("Creating video...") | |
| audio_clip = AudioFileClip(audio_path) | |
| image_clip = ImageClip(image_path).set_duration(audio_clip.duration).set_audio(audio_clip) | |
| image_clip = image_clip.set_fps(24) | |
| video_path = os.path.join(ASSETS_DIR, "news_video.mp4") | |
| image_clip.write_videofile(video_path, codec="libx264", audio_codec="aac") | |
| logging.info(f"Video created successfully at {video_path}") | |
| return video_path | |
| except Exception as e: | |
| logging.error(f"Video creation failed: {e}") | |
| return None | |
| def create_dummy_video(): | |
| logging.info("Creating fallback dummy video (red screen)...") | |
| dummy_img = Image.new('RGB', (800, 600), color='red') | |
| draw = ImageDraw.Draw(dummy_img) | |
| draw.text((250, 280), "No Image Available", fill='white') | |
| dummy_img_path = os.path.join(ASSETS_DIR, "dummy_img.jpg") | |
| dummy_img.save(dummy_img_path) | |
| audio_clip = AudioFileClip(os.path.join(ASSETS_DIR, "news_audio.wav")) | |
| image_clip = ImageClip(dummy_img_path).set_duration(audio_clip.duration).set_audio(audio_clip) | |
| image_clip = image_clip.set_fps(24) | |
| video_path = os.path.join(ASSETS_DIR, "news_video.mp4") | |
| image_clip.write_videofile(video_path, codec="libx264", audio_codec="aac") | |
| logging.info(f"Dummy video created at {video_path}") | |
| return video_path | |
| def generate_news_video(): | |
| topic = fetch_trending_topic() | |
| summary = summarize_news(topic) | |
| audio_path = generate_tts(summary) | |
| image_path = fetch_image() | |
| if audio_path and image_path: | |
| video_path = create_video(image_path, audio_path) | |
| if video_path: | |
| logging.info(f"News video ready: {video_path}") | |
| return video_path | |
| else: | |
| logging.error("Video generation failed, triggering fallback...") | |
| return create_dummy_video() | |
| else: | |
| logging.error("Generation failed: Audio or Image generation failed") | |
| return create_dummy_video() | |
| # ✅ Gradio Interface | |
| iface = gr.Interface( | |
| fn=generate_news_video, | |
| inputs=[], | |
| outputs=gr.Video(label="Generated News Video"), | |
| title="Trending News Video Generator", | |
| description="Click to generate a news video from trending topics." | |
| ) | |
| if __name__ == "__main__": | |
| iface.launch(server_name="0.0.0.0", server_port=7860) | |