Spaces:
Paused
Paused
Update streamlit_app.py
Browse files- streamlit_app.py +34 -34
streamlit_app.py
CHANGED
|
@@ -61,51 +61,56 @@ def get_tiktok_stream_url():
|
|
| 61 |
pass
|
| 62 |
return None
|
| 63 |
|
| 64 |
-
def
|
| 65 |
"""
|
| 66 |
-
إعدادات م
|
| 67 |
"""
|
| 68 |
if not stream_key or not stream_url:
|
| 69 |
return None
|
| 70 |
-
log("🎬 بدء البث (
|
| 71 |
rtmp_url = f"rtmp://a.rtmp.youtube.com/live2/{stream_key}"
|
| 72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
cmd = [
|
| 74 |
"nice", "-n", "19", "ffmpeg",
|
| 75 |
-
"-hide_banner", "-loglevel", "
|
| 76 |
"-re",
|
| 77 |
-
"-analyzeduration", "
|
| 78 |
-
"-probesize", "
|
| 79 |
-
"-thread_queue_size", "
|
| 80 |
-
"-rtbufsize", "
|
| 81 |
|
| 82 |
-
# صمود
|
| 83 |
"-reconnect", "1",
|
| 84 |
"-reconnect_streamed", "1",
|
| 85 |
"-reconnect_delay_max", "30",
|
| 86 |
-
"-timeout", "
|
| 87 |
-
"-rw_timeout", "
|
| 88 |
|
| 89 |
"-i", stream_url,
|
| 90 |
"-err_detect", "ignore_err",
|
| 91 |
|
| 92 |
-
# فلتر
|
| 93 |
-
"-vf", "scale=1080:1920:force_original_aspect_ratio=increase
|
| 94 |
|
| 95 |
-
# ترميز
|
| 96 |
"-c:v", "libx264",
|
| 97 |
-
"-preset", "
|
| 98 |
-
"-crf", "
|
| 99 |
-
"-maxrate", "
|
| 100 |
-
"-bufsize", "
|
| 101 |
"-g", "60",
|
| 102 |
"-vsync", "2",
|
| 103 |
"-pix_fmt", "yuv420p",
|
| 104 |
|
| 105 |
-
# نسخ الصوت مباشرة بدون إعادة ترميز
|
| 106 |
"-c:a", "copy",
|
| 107 |
-
"-max_muxing_queue_size", "
|
| 108 |
-
"-max_delay", "
|
| 109 |
"-flvflags", "no_duration_filesize+add_keyframe_index",
|
| 110 |
"-f", "flv", rtmp_url
|
| 111 |
]
|
|
@@ -117,14 +122,12 @@ def start_stream_light(stream_key, stream_url):
|
|
| 117 |
return {"ffmpeg": proc}
|
| 118 |
|
| 119 |
def log_system_stats():
|
| 120 |
-
"""تسجيل حالة المعالج والذاكرة"""
|
| 121 |
try:
|
| 122 |
load1, load5, load15 = os.getloadavg()
|
| 123 |
mem = psutil.virtual_memory()
|
| 124 |
-
|
| 125 |
-
log(f"📊 تحميل المعالج: 1min={load1:.2f}, 5min={load5:.2f}, 15min={load15:.2f} | ذاكرة مستخدمة: {mem_used_percent:.1f}%")
|
| 126 |
except Exception as e:
|
| 127 |
-
log(f"⚠️
|
| 128 |
|
| 129 |
def run_monitor():
|
| 130 |
if os.path.exists(LOCK_FILE):
|
|
@@ -144,8 +147,8 @@ def run_monitor():
|
|
| 144 |
was_streaming = False
|
| 145 |
consecutive_fails = 0
|
| 146 |
|
| 147 |
-
log("🚀 محرك ال
|
| 148 |
-
log_system_stats()
|
| 149 |
|
| 150 |
while True:
|
| 151 |
try:
|
|
@@ -156,20 +159,19 @@ def run_monitor():
|
|
| 156 |
log("🟢 بدء بث جديد...")
|
| 157 |
if processes:
|
| 158 |
kill_process_tree(processes["ffmpeg"].pid)
|
| 159 |
-
processes =
|
| 160 |
if processes:
|
| 161 |
is_streaming = True
|
| 162 |
was_streaming = True
|
| 163 |
consecutive_fails = 0
|
| 164 |
-
log_system_stats()
|
| 165 |
else:
|
| 166 |
if is_streaming and processes and processes["ffmpeg"].poll() is not None:
|
| 167 |
exit_code = processes["ffmpeg"].poll()
|
| 168 |
log(f"⚠️ ffmpeg مات! exit code: {exit_code}")
|
| 169 |
if os.path.exists(FFMPEG_LOG):
|
| 170 |
with open(FFMPEG_LOG) as f:
|
| 171 |
-
|
| 172 |
-
log("📋 آخر سجلات ffmpeg:\n" + "".join(lines[-20:]))
|
| 173 |
is_streaming = False
|
| 174 |
processes = None
|
| 175 |
was_streaming = False
|
|
@@ -184,9 +186,7 @@ def run_monitor():
|
|
| 184 |
was_streaming = False
|
| 185 |
consecutive_fails = 0
|
| 186 |
|
| 187 |
-
# تسجيل إحصائيات النظام كل دورة (10 ثوانٍ)
|
| 188 |
log_system_stats()
|
| 189 |
-
|
| 190 |
time.sleep(10)
|
| 191 |
|
| 192 |
except Exception as e:
|
|
@@ -194,7 +194,7 @@ def run_monitor():
|
|
| 194 |
time.sleep(10)
|
| 195 |
|
| 196 |
if __name__ == "__main__":
|
| 197 |
-
log("✅ بدء
|
| 198 |
t = threading.Thread(target=run_monitor, daemon=True)
|
| 199 |
t.start()
|
| 200 |
while True:
|
|
|
|
| 61 |
pass
|
| 62 |
return None
|
| 63 |
|
| 64 |
+
def start_stream_emergency(stream_key, stream_url):
|
| 65 |
"""
|
| 66 |
+
إعدادات طوارئ منخفضة الاستهلاك جداً لتخفيف الضغط العالي.
|
| 67 |
"""
|
| 68 |
if not stream_key or not stream_url:
|
| 69 |
return None
|
| 70 |
+
log("🎬 بدء البث (وضع الطوارئ – خفيف جداً)...")
|
| 71 |
rtmp_url = f"rtmp://a.rtmp.youtube.com/live2/{stream_key}"
|
| 72 |
|
| 73 |
+
# قتل أي عمليات عالقة من محاولات سابقة
|
| 74 |
+
try:
|
| 75 |
+
subprocess.run(["killall", "-9", "ffmpeg", "yt-dlp"], stderr=subprocess.DEVNULL)
|
| 76 |
+
except:
|
| 77 |
+
pass
|
| 78 |
+
|
| 79 |
cmd = [
|
| 80 |
"nice", "-n", "19", "ffmpeg",
|
| 81 |
+
"-hide_banner", "-loglevel", "warning",
|
| 82 |
"-re",
|
| 83 |
+
"-analyzeduration", "15M", # تقليل التحليل
|
| 84 |
+
"-probesize", "15M",
|
| 85 |
+
"-thread_queue_size", "2048", # أقل استهلاكاً
|
| 86 |
+
"-rtbufsize", "128M", # تقليل البفر
|
| 87 |
|
| 88 |
+
# صمود مخفف (لا داعي لقيم ضخمة تثقل النظام)
|
| 89 |
"-reconnect", "1",
|
| 90 |
"-reconnect_streamed", "1",
|
| 91 |
"-reconnect_delay_max", "30",
|
| 92 |
+
"-timeout", "10000000",
|
| 93 |
+
"-rw_timeout", "20000000",
|
| 94 |
|
| 95 |
"-i", stream_url,
|
| 96 |
"-err_detect", "ignore_err",
|
| 97 |
|
| 98 |
+
# فلتر بسيط سريع (bicubic الافتراضي) دون تحميل lanczos
|
| 99 |
+
"-vf", "scale=1080:1920:force_original_aspect_ratio=increase,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black:eval=frame",
|
| 100 |
|
| 101 |
+
# ترميز ultrafast (الأسرع والأخف)
|
| 102 |
"-c:v", "libx264",
|
| 103 |
+
"-preset", "ultrafast",
|
| 104 |
+
"-crf", "22", # أعلى رقم = أقل جودة لكن أقل معالج
|
| 105 |
+
"-maxrate", "6000k", # أقل لتخفيف الضغط
|
| 106 |
+
"-bufsize", "12000k",
|
| 107 |
"-g", "60",
|
| 108 |
"-vsync", "2",
|
| 109 |
"-pix_fmt", "yuv420p",
|
| 110 |
|
|
|
|
| 111 |
"-c:a", "copy",
|
| 112 |
+
"-max_muxing_queue_size", "2048",
|
| 113 |
+
"-max_delay", "2000000",
|
| 114 |
"-flvflags", "no_duration_filesize+add_keyframe_index",
|
| 115 |
"-f", "flv", rtmp_url
|
| 116 |
]
|
|
|
|
| 122 |
return {"ffmpeg": proc}
|
| 123 |
|
| 124 |
def log_system_stats():
|
|
|
|
| 125 |
try:
|
| 126 |
load1, load5, load15 = os.getloadavg()
|
| 127 |
mem = psutil.virtual_memory()
|
| 128 |
+
log(f"📊 CPU Load: {load1:.2f} / {load5:.2f} / {load15:.2f} | RAM: {mem.percent:.1f}%")
|
|
|
|
| 129 |
except Exception as e:
|
| 130 |
+
log(f"⚠️ إحصائيات: {e}")
|
| 131 |
|
| 132 |
def run_monitor():
|
| 133 |
if os.path.exists(LOCK_FILE):
|
|
|
|
| 147 |
was_streaming = False
|
| 148 |
consecutive_fails = 0
|
| 149 |
|
| 150 |
+
log("🚀 محرك الطوارئ الخفيف جداً")
|
| 151 |
+
log_system_stats()
|
| 152 |
|
| 153 |
while True:
|
| 154 |
try:
|
|
|
|
| 159 |
log("🟢 بدء بث جديد...")
|
| 160 |
if processes:
|
| 161 |
kill_process_tree(processes["ffmpeg"].pid)
|
| 162 |
+
processes = start_stream_emergency(STREAM_KEY, stream_url)
|
| 163 |
if processes:
|
| 164 |
is_streaming = True
|
| 165 |
was_streaming = True
|
| 166 |
consecutive_fails = 0
|
| 167 |
+
log_system_stats()
|
| 168 |
else:
|
| 169 |
if is_streaming and processes and processes["ffmpeg"].poll() is not None:
|
| 170 |
exit_code = processes["ffmpeg"].poll()
|
| 171 |
log(f"⚠️ ffmpeg مات! exit code: {exit_code}")
|
| 172 |
if os.path.exists(FFMPEG_LOG):
|
| 173 |
with open(FFMPEG_LOG) as f:
|
| 174 |
+
log("📋 آخر سجلات ffmpeg:\n" + "".join(f.readlines()[-10:]))
|
|
|
|
| 175 |
is_streaming = False
|
| 176 |
processes = None
|
| 177 |
was_streaming = False
|
|
|
|
| 186 |
was_streaming = False
|
| 187 |
consecutive_fails = 0
|
| 188 |
|
|
|
|
| 189 |
log_system_stats()
|
|
|
|
| 190 |
time.sleep(10)
|
| 191 |
|
| 192 |
except Exception as e:
|
|
|
|
| 194 |
time.sleep(10)
|
| 195 |
|
| 196 |
if __name__ == "__main__":
|
| 197 |
+
log("✅ بدء محرك الطوارئ الخفيف")
|
| 198 |
t = threading.Thread(target=run_monitor, daemon=True)
|
| 199 |
t.start()
|
| 200 |
while True:
|