Spaces:
Running
Kick: منع سقوط الجودة من 1080p60 إلى 720p60 تحت الحمل
Browse filesقاعدة _too_heavy تُخفّض أي مرشّح >= 1.44 مليون بكسل متى عمل ناشران أو أكثر.
كُتبت لمصادر تيك توك العمودية (720x1280 = 921 ألف بكسل تمرّ، و1440p+ يُرفض)،
لكن Kick أفقي: 1920x1080 = 2.07 مليون ⇒ كان يسقط تحت القاعدة دائمًا.
القاعدة لا تشتري شيئًا هنا لأن مرشّح Kick يُنسخ بلا إعادة ترميز. مقيسٌ على
صورة الإنتاج (ffmpeg 7.1.5، @luchodku 1080p60): 4.9% من نواة = 2.4% من حصة
الـ2.0 CPU. فأُعفي مرشّح Kick القابل للنسخ حتى 1080p فقط؛ ما فوقها ومرشّح
HEVC (لو ظهر) يبقيان خاضعين للقاعدة.
كذلك: 1080p لا يحتاج تسجيل دخول. مقارنة مباشرة على absi وluchodku أظهرت
سلّم جودات متطابقًا حرفيًا بكوكيز وبدونها؛ قيد «crisp mode» في واجهة
موقع kick.com لا في البث.
سلوك تيك توك مُثبَّت بلا تغيير باختبارين صريحين. test_kick 50/50،
وبقية المجموعة مطابقة لخط الأساس (lifecycle 62 OK / 4 FAIL).
- README.md +22 -1
- test_kick.py +53 -0
- youtube_manager.py +15 -0
|
@@ -58,6 +58,27 @@ Kick يبثّ عبر Amazon IVS، وكل الجودات في الـmaster playli
|
|
| 58 |
خرج 9.2 Mbps = معدل المصدر بالضبط، **بلا أي خطأ ولا تحذير `Non-monotonous DTS`**،
|
| 59 |
والخرج المفحوص: `h264 1920x1080 @59fps + aac 48000 stereo`.
|
| 60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
### ضمانات ضد تجميد الصورة عند المشاهد
|
| 62 |
|
| 63 |
1. **رابط جودة ثابتة لا الـmaster.** نُسلّم FFmpeg رابط جودة واحدة بعينها، فلا يقفز
|
|
@@ -85,7 +106,7 @@ Kick يبثّ عبر Amazon IVS، وكل الجودات في الـmaster playli
|
|
| 85 |
| `KICK_MAX_HEIGHT` | `1080` | أعلى ارتفاع يُسمح به. اضبطه `720` لتخفيف النطاق الصادر. |
|
| 86 |
| `KICK_SEG_RETRY` | `2` | إعادات تنزيل المقطع عند عثرة CDN (افتراضي FFmpeg صفر). |
|
| 87 |
| `KICK_TIMEOUT` | `20` | مهلة طلبات Kick بالثواني. |
|
| 88 |
-
| `KICK_COOKIE` | — | اختياري
|
| 89 |
| `KICK_IMPERSONATE` | `chrome` | بصمة TLS المستعملة مع curl_cffi. |
|
| 90 |
|
| 91 |
### حجم الإضافة
|
|
|
|
| 58 |
خرج 9.2 Mbps = معدل المصدر بالضبط، **بلا أي خطأ ولا تحذير `Non-monotonous DTS`**،
|
| 59 |
والخرج المفحوص: `h264 1920x1080 @59fps + aac 48000 stereo`.
|
| 60 |
|
| 61 |
+
### الجودة القصوى: 1080p60 بلا تسجيل دخول
|
| 62 |
+
|
| 63 |
+
«Crisp mode — looks great, use more data» في مشغّل موقع kick.com يطلب تسجيل دخول،
|
| 64 |
+
لكن هذا قيد **في واجهة الموقع فقط**. مُقاس بمقارنة مباشرة على قناتين مباشرتين
|
| 65 |
+
(`absi` و`luchodku`): الـmaster playlist يُرجع السلّم نفسه حرفيًا بكوكيز وبدونها —
|
| 66 |
+
1080p60 أولًا. **فلا حاجة لتوكن Kick إطلاقًا**، ولا يُنصح بتخزين كوكيز جلسة شخصية
|
| 67 |
+
في أسرار السبيس واستعمالها من عنوان مركز بيانات.
|
| 68 |
+
|
| 69 |
+
(لو شدّد Cloudflare الحماية يومًا فمتغيّر `KICK_COOKIE` موجود ويُضاف إلى طلبات
|
| 70 |
+
واجهة Kick وحدها؛ روابط IVS موقّعة فلا تُرسل إليها أي كوكيز.)
|
| 71 |
+
|
| 72 |
+
**لماذا كان يمكن أن تصل 720p:** قاعدة `_too_heavy` في `video_sources` تُخفّض أي
|
| 73 |
+
مرشّح ≥ 1,440,000 بكسل متى عمل ناشران أو أكثر. كُتبت لمصادر تيك توك وهي **عمودية**
|
| 74 |
+
(720×1280 = 921 ألف بكسل ⇒ تمرّ، وأي ماستر 1440p+ يُرفض)، لكن Kick **أفقي**:
|
| 75 |
+
1920×1080 = 2.07 مليون ⇒ كان يسقط تحت القاعدة دائمًا. والقاعدة لا تشتري شيئًا هنا
|
| 76 |
+
لأن مرشّح Kick يُنسخ بلا إعادة ترميز — مقيسٌ على صورة الإنتاج نفسها
|
| 77 |
+
(ffmpeg 7.1.5، @luchodku 1080p60): **4.9% من نواة واحدة = 2.4% من حصة الـ2.0 CPU**.
|
| 78 |
+
فأُعفي مرشّح Kick القابل للنسخ حتى 1080p، وما فوقها يبقى خاضعًا للقاعدة،
|
| 79 |
+
ومرشّح Kick غير قابل للنسخ (HEVC لو ظهر) يبقى خاضعًا لها أيضًا.
|
| 80 |
+
سلوك تيك توك لم يتغيّر: مُثبَّت باختبارين صريحين قبل الحمل وبعده.
|
| 81 |
+
|
| 82 |
### ضمانات ضد تجميد الصورة عند المشاهد
|
| 83 |
|
| 84 |
1. **رابط جودة ثابتة لا الـmaster.** نُسلّم FFmpeg رابط جودة واحدة بعينها، فلا يقفز
|
|
|
|
| 106 |
| `KICK_MAX_HEIGHT` | `1080` | أعلى ارتفاع يُسمح به. اضبطه `720` لتخفيف النطاق الصادر. |
|
| 107 |
| `KICK_SEG_RETRY` | `2` | إعادات تنزيل المقطع عند عثرة CDN (افتراضي FFmpeg صفر). |
|
| 108 |
| `KICK_TIMEOUT` | `20` | مهلة طلبات Kick بالثواني. |
|
| 109 |
+
| `KICK_COOKIE` | — | اختياري وغير لازم للجودة: 1080p متاح بلا تسجيل دخول. |
|
| 110 |
| `KICK_IMPERSONATE` | `chrome` | بصمة TLS المستعملة مع curl_cffi. |
|
| 111 |
|
| 112 |
### حجم الإضافة
|
|
@@ -146,6 +146,59 @@ ia_tt = snd.input_args(tt)
|
|
| 146 |
check('تيك توك FLV ما زال على stdin', ia_tt['stdin'] is not None)
|
| 147 |
check('تيك توك لا يأخذ خيارات كيك', '-seg_max_retry' not in ia_tt['input'])
|
| 148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
# --------------------------------------------------------------------------- #
|
| 150 |
# 4. عقد الرصد مطابق لتيك توك
|
| 151 |
# --------------------------------------------------------------------------- #
|
|
|
|
| 146 |
check('تيك توك FLV ما زال على stdin', ia_tt['stdin'] is not None)
|
| 147 |
check('تيك توك لا يأخذ خيارات كيك', '-seg_max_retry' not in ia_tt['input'])
|
| 148 |
|
| 149 |
+
# --------------------------------------------------------------------------- #
|
| 150 |
+
# 3b. الجودة القصوى لا تسقط تحت الحمل (Kick أفقي كان يقع تحت قاعدة تيك توك العمودية)
|
| 151 |
+
# --------------------------------------------------------------------------- #
|
| 152 |
+
import youtube_manager as _ym
|
| 153 |
+
from youtube_manager import ManagedYouTube
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
class _Hub:
|
| 157 |
+
def __init__(self, busy):
|
| 158 |
+
self.b = busy
|
| 159 |
+
|
| 160 |
+
def active_count(self):
|
| 161 |
+
return self.b
|
| 162 |
+
|
| 163 |
+
def light_count(self, except_user=None):
|
| 164 |
+
return 0
|
| 165 |
+
|
| 166 |
+
def light_available(self, except_user=None):
|
| 167 |
+
return True
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
_orig_hub = _ym.hub
|
| 171 |
+
_kick_ladder = [dict(r) for r in rend]
|
| 172 |
+
try:
|
| 173 |
+
picks = {}
|
| 174 |
+
for _busy in (0, 1, 2, 3, 5):
|
| 175 |
+
_ym.hub = _Hub(_busy)
|
| 176 |
+
_sel = ManagedYouTube.video_sources(_kick_ladder)
|
| 177 |
+
picks[_busy] = _sel[0]['quality_name'] if _sel else None
|
| 178 |
+
check('Kick يبقى 1080p60 تحت أي عدد من البثوث',
|
| 179 |
+
all(v == '1080p60' for v in picks.values()), picks)
|
| 180 |
+
|
| 181 |
+
_tt = [{'codec': 'h264', 'width': 720, 'height': 1280, 'resolution': '720x1280',
|
| 182 |
+
'label': 'origin', 'brief': 'origin 1280p H264', 'media': 'flv'},
|
| 183 |
+
{'codec': 'h264', 'width': 1440, 'height': 2560, 'resolution': '1440x2560',
|
| 184 |
+
'label': 'uhd', 'brief': 'uhd 2560p H264', 'media': 'flv'},
|
| 185 |
+
{'codec': 'h264', 'width': 1920, 'height': 1080, 'resolution': '1920x1080',
|
| 186 |
+
'label': 'hd', 'brief': 'hd 1080p H264', 'media': 'flv'}]
|
| 187 |
+
_ym.hub = _Hub(0)
|
| 188 |
+
_free = [c['brief'] for c in ManagedYouTube.video_sources(_tt)]
|
| 189 |
+
_ym.hub = _Hub(2)
|
| 190 |
+
_busysel = [c['brief'] for c in ManagedYouTube.video_sources(_tt)]
|
| 191 |
+
check('تيك توك بلا حمل: كل المرشّحات كما كانت', len(_free) == 3, _free)
|
| 192 |
+
check('تيك توك تحت الحمل: 1440p و1080p الأفقي ما زالا يُخفَّضان',
|
| 193 |
+
_busysel == ['origin 1280p H264'], _busysel)
|
| 194 |
+
|
| 195 |
+
_hevc = {'codec': 'h265', 'width': 1920, 'height': 1080, 'platform': 'kick'}
|
| 196 |
+
_h264 = {'codec': 'h264', 'width': 1280, 'height': 720, 'platform': 'kick'}
|
| 197 |
+
check('الإعفاء مشروط بالنسخ (_copyable يفرّق H264 عن HEVC)',
|
| 198 |
+
ManagedYouTube._copyable(_h264) and not ManagedYouTube._copyable(_hevc))
|
| 199 |
+
finally:
|
| 200 |
+
_ym.hub = _orig_hub
|
| 201 |
+
|
| 202 |
# --------------------------------------------------------------------------- #
|
| 203 |
# 4. عقد الرصد مطابق لتيك توك
|
| 204 |
# --------------------------------------------------------------------------- #
|
|
@@ -139,6 +139,11 @@ class ManagedYouTube:
|
|
| 139 |
except Exception:return ''
|
| 140 |
return str(d['settings'].get('send_mode') or '')
|
| 141 |
@staticmethod
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
def video_sources(sources):
|
| 143 |
"""Renditions the relay may use, best first.
|
| 144 |
|
|
@@ -187,6 +192,16 @@ class ManagedYouTube:
|
|
| 187 |
try:w=int(c.get('width') or 0); h=int(c.get('height') or 0)
|
| 188 |
except (TypeError,ValueError):w=h=0
|
| 189 |
if w and h:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
# 720x1440 vertical is 720-class (~1 Mbps), not a 1440p master.
|
| 191 |
return min(w,h)>=1440 or (w*h)>=(1600*900)
|
| 192 |
text=str(c.get('label') or c.get('brief') or '')
|
|
|
|
| 139 |
except Exception:return ''
|
| 140 |
return str(d['settings'].get('send_mode') or '')
|
| 141 |
@staticmethod
|
| 142 |
+
def _copyable(candidate):
|
| 143 |
+
"""هل يُنسخ هذا المرشّح بلا إعادة ترميز؟ (H.264 مُعلَن) — نفس قاعدة Sender.copy_is_safe."""
|
| 144 |
+
codec=str((candidate or {}).get('codec') or '').strip().lower()
|
| 145 |
+
return any(k in codec for k in ('h264','avc','264'))
|
| 146 |
+
@staticmethod
|
| 147 |
def video_sources(sources):
|
| 148 |
"""Renditions the relay may use, best first.
|
| 149 |
|
|
|
|
| 192 |
try:w=int(c.get('width') or 0); h=int(c.get('height') or 0)
|
| 193 |
except (TypeError,ValueError):w=h=0
|
| 194 |
if w and h:
|
| 195 |
+
# قاعدة البكسلات أدناه كُتبت لمصادر تيك توك وهي **عمودية**: 720x1440 يمرّ
|
| 196 |
+
# (~1 مليون بكسل) بينما أي ماستر 1440p+ يُرفض. لكن Kick **أفقي**: 1920x1080
|
| 197 |
+
# = 2.07 مليون بكسل ⇒ كان يسقط تحت القاعدة دائمًا، فينزل البث من 1080p60
|
| 198 |
+
# إلى 720p60 بمجرد وجود ناشرَين — وهو ما لا يشتريه أحد شيئًا هنا:
|
| 199 |
+
# مرشّح Kick يُنسخ بلا إعادة ترميز، ومقيسٌ على نفس صورة الإنتاج
|
| 200 |
+
# (ffmpeg 7.1.5، @luchodku 1080p60): 4.9% من نواة واحدة = 2.4% من حصة
|
| 201 |
+
# الـ2.0 CPU. ما فوق 1080p يبقى خاضعًا للقاعدة.
|
| 202 |
+
if (str(c.get('platform') or '')=='kick'
|
| 203 |
+
and ManagedYouTube._copyable(c) and max(w,h)<=1920 and min(w,h)<=1080):
|
| 204 |
+
return False
|
| 205 |
# 720x1440 vertical is 720-class (~1 Mbps), not a 1440p master.
|
| 206 |
return min(w,h)>=1440 or (w*h)>=(1600*900)
|
| 207 |
text=str(c.get('label') or c.get('brief') or '')
|