Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -6,13 +6,11 @@ from flask import Flask
|
|
| 6 |
import threading
|
| 7 |
|
| 8 |
# ==========================================
|
| 9 |
-
# الإعدادات
|
| 10 |
# ==========================================
|
| 11 |
TARGET_DATE = datetime(2026, 2, 20, 0, 0, 0)
|
| 12 |
STREAM_KEY = os.environ.get("STREAM_KEY")
|
| 13 |
STREAM_URL = "rtmp://a.rtmp.youtube.com/live2/"
|
| 14 |
-
|
| 15 |
-
# رابط صورة خلفية احترافية (رمضانية) - يمكنك وضع رابط مباشر لصورة أو فيديو
|
| 16 |
BG_IMAGE = "https://images.unsplash.com/photo-1542642832-d967f7a08151?q=80&w=1920&auto=format&fit=crop"
|
| 17 |
# ==========================================
|
| 18 |
|
|
@@ -20,83 +18,105 @@ app = Flask(__name__)
|
|
| 20 |
|
| 21 |
@app.route('/')
|
| 22 |
def home():
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
return f"""
|
| 25 |
<!DOCTYPE html>
|
| 26 |
<html lang="ar" dir="rtl">
|
| 27 |
<head>
|
| 28 |
<meta charset="UTF-8">
|
| 29 |
<meta http-equiv="refresh" content="1">
|
| 30 |
-
<title>
|
| 31 |
<style>
|
| 32 |
-
body {{ background: #0f0f0f; color: white; font-family:
|
| 33 |
-
.
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
.
|
| 37 |
-
.
|
| 38 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
</style>
|
| 40 |
</head>
|
| 41 |
<body>
|
| 42 |
-
<div class="
|
| 43 |
-
<div class="
|
| 44 |
-
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
</div>
|
| 47 |
</body>
|
| 48 |
</html>
|
| 49 |
"""
|
| 50 |
|
| 51 |
-
def generate_timer_html():
|
| 52 |
-
diff = TARGET_DATE - datetime.now()
|
| 53 |
-
if diff.total_seconds() <= 0: return "<h1>رمضان مبارك!</h1>"
|
| 54 |
-
days = diff.days
|
| 55 |
-
hours, rem = divmod(diff.seconds, 3600)
|
| 56 |
-
minutes, seconds = divmod(rem, 60)
|
| 57 |
-
html = ""
|
| 58 |
-
for val, label in [(days, "أيام"), (hours, "ساعات"), (minutes, "دقائق"), (seconds, "ثواني")]:
|
| 59 |
-
html += f'<div class="box"><span class="num">{val:02}</span><span class="lab">{label}</span></div>'
|
| 60 |
-
return html
|
| 61 |
-
|
| 62 |
def start_stream():
|
| 63 |
-
if not STREAM_KEY:
|
| 64 |
-
print("Error: STREAM_KEY is missing!")
|
| 65 |
-
return
|
| 66 |
-
|
| 67 |
-
# تحويل التاريخ إلى صيغة يفهمها FFmpeg للعد التنازلي
|
| 68 |
target_ts = int(TARGET_DATE.timestamp())
|
| 69 |
-
|
| 70 |
-
# أمر FFmpeg الاحترافي:
|
| 71 |
-
# 1. يستخدم صورة خلفية (BG_IMAGE)
|
| 72 |
-
# 2. يضيف نص "رمضان 2026" بخط كبير
|
| 73 |
-
# 3. يضيف العداد التنازلي الحي
|
| 74 |
ffmpeg_cmd = [
|
| 75 |
-
'ffmpeg',
|
| 76 |
-
'-
|
| 77 |
-
'-loop', '1', '-i', BG_IMAGE, # تكرار الخلفية
|
| 78 |
-
'-f', 'lavfi', '-i', 'anullsrc', # صوت صامت (ضروري لليوتيوب)
|
| 79 |
'-vf', (
|
| 80 |
-
f"scale=1280:720,"
|
| 81 |
-
f"drawtext=text='رمضان 2026':x=(w-text_w)/2:y=200:fontsize=80:fontcolor=white:shadowcolor=black:shadowx=5:shadowy=5,"
|
| 82 |
-
f"drawtext=text='%{{pts\\:localtime\\:{target_ts}\\:%d يوم %H\\:%M\\:%S}}':"
|
| 83 |
f"x=(w-text_w)/2:y=350:fontsize=110:fontcolor=yellow:shadowcolor=black:shadowx=7:shadowy=7"
|
| 84 |
),
|
| 85 |
-
'-vcodec', 'libx264', '-preset', 'veryfast', '-
|
| 86 |
-
'-pix_fmt', 'yuv420p', '-g', '60', '-c:a', 'aac', '-f', 'flv',
|
| 87 |
f"{STREAM_URL}{STREAM_KEY}"
|
| 88 |
]
|
| 89 |
-
|
| 90 |
subprocess.run(ffmpeg_cmd)
|
| 91 |
|
| 92 |
if __name__ == "__main__":
|
| 93 |
-
# تشغيل واجهة المراقبة
|
| 94 |
threading.Thread(target=lambda: app.run(host='0.0.0.0', port=7860), daemon=True).start()
|
| 95 |
-
|
| 96 |
-
print("🚀 البث الاحترافي بدأ...")
|
| 97 |
while True:
|
| 98 |
-
try:
|
| 99 |
-
|
| 100 |
-
except Exception as e:
|
| 101 |
-
print(f"حدث خطأ: {e}")
|
| 102 |
-
time.sleep(10)
|
|
|
|
| 6 |
import threading
|
| 7 |
|
| 8 |
# ==========================================
|
| 9 |
+
# الإعدادات
|
| 10 |
# ==========================================
|
| 11 |
TARGET_DATE = datetime(2026, 2, 20, 0, 0, 0)
|
| 12 |
STREAM_KEY = os.environ.get("STREAM_KEY")
|
| 13 |
STREAM_URL = "rtmp://a.rtmp.youtube.com/live2/"
|
|
|
|
|
|
|
| 14 |
BG_IMAGE = "https://images.unsplash.com/photo-1542642832-d967f7a08151?q=80&w=1920&auto=format&fit=crop"
|
| 15 |
# ==========================================
|
| 16 |
|
|
|
|
| 18 |
|
| 19 |
@app.route('/')
|
| 20 |
def home():
|
| 21 |
+
diff = TARGET_DATE - datetime.now()
|
| 22 |
+
days = diff.days
|
| 23 |
+
hours, rem = divmod(diff.seconds, 3600)
|
| 24 |
+
minutes, seconds = divmod(rem, 60)
|
| 25 |
+
time_str = f"{days} يوم و {hours:02}:{minutes:02}:{seconds:02}"
|
| 26 |
+
|
| 27 |
+
# تصميم محاكاة يوتيوب (Mockup)
|
| 28 |
return f"""
|
| 29 |
<!DOCTYPE html>
|
| 30 |
<html lang="ar" dir="rtl">
|
| 31 |
<head>
|
| 32 |
<meta charset="UTF-8">
|
| 33 |
<meta http-equiv="refresh" content="1">
|
| 34 |
+
<title>يوتيوب - بث مباشر</title>
|
| 35 |
<style>
|
| 36 |
+
body {{ background-color: #0f0f0f; color: white; font-family: Roboto, Arial, sans-serif; margin: 0; padding: 20px; display: flex; justify-content: center; }}
|
| 37 |
+
.youtube-container {{ width: 90%; max-width: 1200px; display: grid; grid-template-columns: 3fr 1fr; gap: 20px; }}
|
| 38 |
+
|
| 39 |
+
/* شاشة الفيديو */
|
| 40 |
+
.video-player {{ background: url('{BG_IMAGE}') no-repeat center; background-size: cover; aspect-ratio: 16/9; border-radius: 12px; position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; border: 1px solid #333; }}
|
| 41 |
+
.video-overlay {{ position: absolute; background: rgba(0,0,0,0.4); width: 100%; height: 100%; border-radius: 12px; }}
|
| 42 |
+
.counter-text {{ z-index: 1; text-align: center; text-shadow: 2px 2px 10px rgba(0,0,0,0.8); }}
|
| 43 |
+
.counter-text h1 {{ font-size: 3.5vw; color: white; margin: 0; }}
|
| 44 |
+
.counter-text p {{ font-size: 5vw; color: #ffeb3b; margin: 10px 0; font-weight: bold; }}
|
| 45 |
+
|
| 46 |
+
/* تفاصيل القناة */
|
| 47 |
+
.video-info {{ margin-top: 15px; }}
|
| 48 |
+
.video-title {{ font-size: 1.2rem; font-weight: bold; margin-bottom: 10px; }}
|
| 49 |
+
.channel-row {{ display: flex; align-items: center; justify-content: space-between; }}
|
| 50 |
+
.channel-meta {{ display: flex; align-items: center; gap: 10px; }}
|
| 51 |
+
.channel-icon {{ width: 40px; height: 40px; background: #4CAF50; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; }}
|
| 52 |
+
.subscribe-btn {{ background: white; color: black; padding: 8px 16px; border-radius: 20px; font-weight: bold; cursor: pointer; }}
|
| 53 |
+
|
| 54 |
+
/* الشات الجانبي */
|
| 55 |
+
.live-chat {{ background: #1a1a1a; border: 1px solid #333; border-radius: 12px; height: 500px; display: flex; flex-direction: column; }}
|
| 56 |
+
.chat-header {{ padding: 15px; border-bottom: 1px solid #333; font-weight: bold; }}
|
| 57 |
+
.chat-messages {{ flex: 1; padding: 10px; font-size: 0.9rem; color: #aaa; overflow: hidden; }}
|
| 58 |
+
.chat-input {{ padding: 10px; border-top: 1px solid #333; color: #666; font-size: 0.8rem; }}
|
| 59 |
</style>
|
| 60 |
</head>
|
| 61 |
<body>
|
| 62 |
+
<div class="youtube-container">
|
| 63 |
+
<div class="main-content">
|
| 64 |
+
<div class="video-player">
|
| 65 |
+
<div class="video-overlay"></div>
|
| 66 |
+
<div class="counter-text">
|
| 67 |
+
<h1>رمضان 2026</h1>
|
| 68 |
+
<p>{time_str}</p>
|
| 69 |
+
</div>
|
| 70 |
+
</div>
|
| 71 |
+
<div class="video-info">
|
| 72 |
+
<div class="video-title">بث مباشر: العد التنازلي لرمضان 2026 🌙 كم باقي؟</div>
|
| 73 |
+
<div class="channel-row">
|
| 74 |
+
<div class="channel-meta">
|
| 75 |
+
<div class="channel-icon">ص</div>
|
| 76 |
+
<div>
|
| 77 |
+
<div style="font-weight: bold;">من كل صوب</div>
|
| 78 |
+
<div style="font-size: 0.8rem; color: #aaa;">1.2M مشترك</div>
|
| 79 |
+
</div>
|
| 80 |
+
</div>
|
| 81 |
+
<div class="subscribe-btn">اشتراك</div>
|
| 82 |
+
</div>
|
| 83 |
+
</div>
|
| 84 |
+
</div>
|
| 85 |
+
|
| 86 |
+
<div class="live-chat">
|
| 87 |
+
<div class="chat-header">المحادثة المباشرة</div>
|
| 88 |
+
<div class="chat-messages">
|
| 89 |
+
<p><b>أحمد:</b> اللهم بلغنا رمضان</p>
|
| 90 |
+
<p><b>سارة:</b> ما شاء الله التصميم جميل</p>
|
| 91 |
+
<p><b>مستخدم:</b> الله يبارك فيكم</p>
|
| 92 |
+
<p style="color: #4CAF50;"><b>نظام:</b> أهلاً بك في البث المباشر!</p>
|
| 93 |
+
</div>
|
| 94 |
+
<div class="chat-input">إرسال رسالة...</div>
|
| 95 |
+
</div>
|
| 96 |
</div>
|
| 97 |
</body>
|
| 98 |
</html>
|
| 99 |
"""
|
| 100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
def start_stream():
|
| 102 |
+
if not STREAM_KEY: return
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
target_ts = int(TARGET_DATE.timestamp())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
ffmpeg_cmd = [
|
| 105 |
+
'ffmpeg', '-re', '-loop', '1', '-i', BG_IMAGE,
|
| 106 |
+
'-f', 'lavfi', '-i', 'anullsrc',
|
|
|
|
|
|
|
| 107 |
'-vf', (
|
| 108 |
+
f"scale=1280:720,"
|
| 109 |
+
f"drawtext=text='رمضان 2026':x=(w-text_w)/2:y=200:fontsize=80:fontcolor=white:shadowcolor=black:shadowx=5:shadowy=5,"
|
| 110 |
+
f"drawtext=text='%{{pts\\:localtime\\:{target_ts}\\:%d يوم %H\\:%M\\:%S}}':"
|
| 111 |
f"x=(w-text_w)/2:y=350:fontsize=110:fontcolor=yellow:shadowcolor=black:shadowx=7:shadowy=7"
|
| 112 |
),
|
| 113 |
+
'-vcodec', 'libx264', '-preset', 'veryfast', '-b:v', '2500k', '-pix_fmt', 'yuv420p', '-f', 'flv',
|
|
|
|
| 114 |
f"{STREAM_URL}{STREAM_KEY}"
|
| 115 |
]
|
|
|
|
| 116 |
subprocess.run(ffmpeg_cmd)
|
| 117 |
|
| 118 |
if __name__ == "__main__":
|
|
|
|
| 119 |
threading.Thread(target=lambda: app.run(host='0.0.0.0', port=7860), daemon=True).start()
|
|
|
|
|
|
|
| 120 |
while True:
|
| 121 |
+
try: start_stream()
|
| 122 |
+
except: time.sleep(10)
|
|
|
|
|
|
|
|
|