MPEG-TS أم HLS: ما الذي يرسله بث IPTV المباشر فعلًا، وكيف يفشل كل منهما

عنوان البث المباشر من البوابة هو طلب HTTP GET واحد لا ينتهي أبدًا. وعنوان HLS ملف نصي يسرد الثواني القليلة القادمة. وكل شيء آخر تقريبًا ينبع من ذلك.

var sourceKind = uri.Contains(".m3u8", StringComparison.OrdinalIgnoreCase) ? "hls" : "ts";

سطر واحد، وهو كل ما لدينا من اكتشاف النقل على مسار التشغيل. يعمل عند كل تطبيق لوسيط مباشر، في أربعة مواقع استدعاء: التنقل بين القنوات، وإعادة بناء المحرّك، ومسارَي تسليم عند التحويل الاحتياطي. اختبار سلسلة فرعية على كامل العنوان، وكل ما ليس HLS يسقط إلى ts. شغّله على المُدخَلات الـ 2,203 في قائمتَي التشغيل اللتين نحتفظ بهما لعمل المحلِّل فيسِم 1,930 منها hls و273 ts. و7 بالضبط من تلك العناوين الـ 2,203 تنتهي بـ .ts.

الوسم والحقيقة شيئان مختلفان، وكذلك النقلان اللذان يحاول تسميتهما. أحدهما طلب HTTP GET واحد لا ينتهي أبدًا. والآخر ملف نصي يسرد الثواني القليلة القادمة، ويتوقع منك أن تعود لطلب المزيد.

ما الذي تخطئ فيه السلسلة الفرعية، بالأرقام

قائمتا التشغيل هاتان هما مجموعة العيّنات التي يقف عليها عمل المحلِّل لدينا، ملفان مُنتقيان على نمط الدليل، وحصة HLS الغالبة فيهما لا تقول شيئًا عما تقدّمه البوابة. فمسار البوابة يجري في الاتجاه المعاكس، وهذا هو الجزء الذي تقلبه معظم المقالات: عنوان البث المباشر الذي يبنيه عميلنا يطلب دائمًا .ts. وما يعود هو شأن البوابة، ونحن لا نتحقق منه أبدًا.

ما تنفع فيه المجموعة هو إظهار مدى سوء وصف لاحقة العنوان للبث. والجواب: سوء بالغ. على مستوى المجموعة كلها، 1,924 مسارًا تنتهي بـ .m3u8 و7 تنتهي بـ .ts. ومن بين الصفوف الـ 273 التي تسميها القاعدة ts، تتوزع اللواحق كما يلي:

  • 147 بلا امتداد مقروء، 16 منها لأن ip ومنفذًا يقعان في المسار حيث ينبغي أن يكون اسم الملف
  • 75 تنتهي بـ .php
  • 17 تنتهي بـ .mpd، وهو ملف بيان DASH وتكيّفي على النحو الذي ينفيه وسم ts تمامًا
  • 14 تنتهي بـ .htm
  • 7 تنتهي بـ .ts، و6 بـ .m3u، و3 بـ .2ts، وواحد من كل من .smil و.dash و.mp4 و.wmv

ستة صفوف تذهب في الاتجاه الآخر، فتُصنَّف HLS لأن .m3u8 يقع في سلسلة الاستعلام لا في نهاية المسار. وكون القاعدة تقرأ الاستعلام أصلًا هو الموضع الوحيد الذي يمكنها فيه أن تختلف مع فحص امتداد بسيط، إذ لا يحمل أي صف في المجموعة الرمز في وسط المسار. تلك الاختلافات، والمصنِّف الثاني المستخرج من العنوان في حوار معلومات البث الذي ينتجها، مغطاة في مقالة خاصة بها إلى جانب امتداد ملف قائمة التشغيل نفسه، وهو سؤال منفصل عن امتداد أي عنوان بداخله.

ما يشفع له أن الوسم لا يفعل شيئًا يُذكر. فهو يمرّ إلى سطر Debug حين تتسلّح الجلسة وإلى حدث Serilog wd.fault عند كل حكم، ولا يقرأه أي حد أو مهلة أو تفريع في أي مكان من آلية الاسترداد. والسجل المنمَّط الذي كان يُفترض أن يحمله إلى خادم خلفي مُصرَّح به ولا يُبنى أبدًا. وتعليق التوثيق على الحقل نفسه يقول ما هو لأجله: القياس عن بُعد، إضافة إلى حدود لكل نوع لم يكتبها أحد. مصنِّف يخطئ في وسم 17 صفًا على الأقل من 2,203 ولا يستشيره شيء أمرٌ غريب أن يُشحن، وسبب احتماله هو تحديدًا ذلك النصف الثاني.

ولا يوجد مصدر أفضل متاح أيضًا. فسجل القناة المباشرة يحمل معرّف بث، وقاعدة بوابة، وعنوانًا مباشرًا اختياريًا، وحقول جودة، وعلم إعادة بث، ولا شيء يسمّي حاوية أو نقلًا أو نوع MIME. النقل ليس خاصية للقناة في نموذج بياناتنا، فلا يبقى ما يُقرأ سوى العنوان.

ستة عناوين، وما يسمّي به المصنِّف كل واحد منها

كل مضيف أدناه نطاق مثال محجوز وكل مسار مُختلَق، لكن كل صف مجمَّع من أشكال تشهد بها المجموعة.

1  https://example.com/live/user/pass/1234.ts
2  https://example.com/live/user/pass/1234.m3u8
3  https://example.net/hls/channel.mpd
4  https://example.org/live/9001/?file=chan.m3u8&output=playlist.m3u8
5  https://example.net/watch.htm?cont=1&output=7&forceUserAgent=1
6  https://example.net/play/9001

الصف 1 هو ما يُصدره باني البوابة لدينا، وهو الحالة الوحيدة التي يكون فيها الوسم صحيحًا ومستحقًّا. والصف 2 هو القناة نفسها مطلوبة بصيغة HLS، مع السلسلة الفرعية حيث تتوقعها.

الصف 3 ملف بيان DASH. لا يحتوي .m3u8، فيُوسَم ts، وهو خطأ في أكثر الاتجاهات إثارة للاهتمام: البث تكيّفي، وله مقاطع، وله ملف بيان، وكل ما يوحي به الوسم عنه باطل. سبعة عشر صفًا في قائمة التشغيل الأكبر تنتهي على هذا النحو.

الصف 4 هو العكس. ينتهي المسار بشرطة مائلة ولا يحمل امتدادًا إطلاقًا، لكن .m3u8 يقع داخل الاستعلام مرتين، مرة كتلميح إلى المصدر ومرة كقيمة لمعامل يسمى output. وقاعدة السلسلة الفرعية تبلّغ HLS. صفان حقيقيان بهذا الشكل بالضبط، وplaylist.m3u8 اسم ملف لا اسم حاوية، فحتى الحقل الذي يبدو موثوقًا لا يجيب عن السؤال.

الصف 5 هو الشكل الذي جعلني أكفّ عن الثقة بمعامل output. أربعة عشر صفًا تحمل output=7، وكلها الأربعة عشر تقع على مسار ينتهي بـ .htm إلى جانب مفاتيح تسمى cont وforceUserAgent. حقل اسمه output مضبوط على 7 لا يقول للعميل شيئًا، ولا سبيل لنا لمعرفة ما يعنيه الـ 7: فالمفاتيح المصاحبة ليست شكل تصدير Xtream، فلا يمكننا حتى أن نفترض أنه يحمل معنى output=ts أو output=m3u8 الذي يوثّقه محلِّل الاستيراد لدينا. وفي الوقت نفسه، الامتداد الذي كان حوار معلومات البث سيقرأه من ذلك المسار هو HTM.

الصف 6 لا يحمل شيئًا مقروءًا إطلاقًا، وهو أغلبية كل ما تسميه القاعدة ts: 147 من تلك الصفوف الـ 273. يحصل على ts لأن ts هو الافتراضي، لا لأن شيئًا اكتُشف، وهذا ما يجعل المصنِّف كله اصطلاح تسمية لا قياسًا.

مسار البوابة يطلب .ts ولا يطلب شيئًا آخر أبدًا

هذا هو بناء عنوان البث المباشر كاملًا لمصدر بوابة، بلا التهريب:

return string.Format(CultureInfo.InvariantCulture, "{0}/live/{1}/{2}/{3}.ts", baseText, user, pass, streamId);

لا معامل، ولا تفريع، ولا كائن خيارات. والمنطق الوحيد في ذلك الملف خارج سلسلة التنسيق هو تهريب اسم المستخدم وكلمة المرور. والتفريع الوحيد على مسار الحل هو ما إذا كان الصف قد جاء من قائمة تشغيل تحمل عنوانًا كاملًا بداخلها، فنستخدم ذلك العنوان كما هو، أو من بوابة، فنبني السطر أعلاه.

تُبنى إعادة البث بدالة ثانية من الشكل نفسه، تُدرج مدة بالدقائق الكاملة وطابع بداية بتنسيق yyyy-MM-dd:HH-mm، وتعليق توثيقها يحمل التحذير الوحيد الذي احتاجه أي من البانيَين: ذلك الطابع هو الوقت المحلي لخادم البوابة، الساعة نفسها التي يعمل عليها دليل البوابة، لا ساعة الجهاز. وهو ينتهي أيضًا بـ .ts.

شيئان يقيّدان ذلك. كل مصدر Xtream يحمل إعدادًا محفوظًا «تنسيق البث» بخيارَي MPEG-TS وHLS (m3u8)، ولا يقرأه شيء: القيمة تدور في الإعدادات ويواصل الجهاز طلب .ts. ذلك العنصر الميت، والباني الثاني في جانب الكتالوج الذي كان سيُلحق .m3u8 لو استدعاه شيء، موثَّقان حيث ينبغي. أما القيد الآخر فأهم هنا. كل هذا يتعلق بالطلب. والبوابة حرة في إعادة توجيه عنوان .ts إلى مكان آخر أو في تقديم HLS منه، ونحن لا ننظر أبدًا، فلا شيء في هذه المقالة دليل على ما ترسله البوابات فعلًا.

لتدفق النقل إيقاع؛ وما يعوزه هو حدٌّ يسلّمه لنا المشغّل

التأطير في العنوان خطأ تصنيفي. فلنُذِبْه أولًا. يدرج القسم 3.2 من RFC 8216 تدفقات النقل MPEG-2 بين صيغ المقاطع المدعومة، ويشترط أن يحتوي كل مقطع منها برنامجًا واحدًا مع PAT وPMT، فيمكن أن يكون مقطع HLS هو ذات الحزم ذات 188 بايت مقطَّعة في ملف. وكم مرة يكون كذلك، لم نقسه، والصناعة تتجه إلى fMP4 منذ سنوات. أما ما يختلف بموثوقية فهو التسليم، والتسليم هو منبع كل فرق سلوكي أدناه.

يمنح ملف البيان العميل أربعة أشياء لا يمنحها مقبس مفتوح:

  • طلب يمكن أن يفشل. فكل مقطع معاملة HTTP خاصة به، فيصبح 404 أو مهلة أو جسم مبتور حدثًا له لحظة مقترنة به.
  • إيقاع يستطيع العميل فرضه. يشترط RFC 8216 على العميل المباشر أن يعيد تحميل قائمة التشغيل ويحدد الانتظار من مدة الهدف، فيمكن قياس الصمت على شيء تعلنه الصيغة نفسها.
  • انقطاع مُعلن، فيصل الوصل كعلامة لا كقفزة ساعة يجب استنتاجها.
  • موضع. فقائمة مقاطع ومدة هدف معًا تقولان كم يبعد العميل عن حافة البث المباشر.

يمنحك MPEG-TS التدرّجي عبر HTTP طلب GET واحدًا لا ينتهي، مع كل البنية داخل البايتات: حزم بحجم 188، وجدول ارتباط البرامج، وجدول خريطة البرنامج، وتدفقات أولية على PIDs خاصة بها، ومرجع ساعة برنامج لضبط إيقاعها، وحزم فارغة على PID 0x1FFF للحشو.

الجملة التي كتبتها هنا أول مرة كانت أن تدفق البايتات لا حدّ فيه تُعلَّق عليه مهلة. كنت مخطئًا، وكان مهندس بث سيصحّحها من أول نظرة: فعلى مستوى الصيغة، لتدفق النقل إيقاع وفير. يقيّد ISO/IEC 13818-1 المسافة الفاصلة بين مراجع ساعة البرنامج، ومعيار المراقبة لدى DVB، أي ETSI TR 101 290، يبني مجموعة الأولوية 1 كلها من تلك الحدود بالذات: فقدان التزامن، وPAT لا يتكرر خلال 500 ms، وعدّاد استمرارية يتخطى، وPMT يختفي. ورفوف من المجسّات تقرأ تلك الحدود طوال اليوم. ومرحِّلنا نفسه يفترضها مسبقًا: فعطله nulls يواصل إرسال PAT وPMT لأن التدفق الذي يفقدهما فشل مختلف.

ما لا يملكه التدفق التدرّجي هو حدٌّ يُظهره المشغّل لنا. فما يسلّمه libvlc هو لقطة من عدّادات تراكمية: البايتات المقروءة في طبقة الوصول، والبايتات التي استهلكها المفكّك، والصور المفكوكة والصور المعروضة، ولا حقل واحد فيها توقيت جداول. فلا يبقى للمهلة موضع مبدئي تُعلَّق عليه ويُستنتج التوقف من فرق صار صفرًا. وكيف تُقرأ تلك الفروق، ولماذا يواصل المحرّك الإبلاغ عن تشغيل سليم بينما الصورة متجمدة، مقالة منفصلة.

مرحِّل حقن الأعطال لدينا يجعل الفجوة ملموسة. فهو أداة محلية للمطوّر، لا تُنشر أبدًا ولا تدخل في أي خدمة، تولّد تدفق نقل اصطناعيًا ببرنامج واحد على واجهة الاسترجاع بنحو 4.6 Mbit/s وتكسره عند الطلب. وضعه freeze يوقف الكتابة ويترك المقبس قائمًا، والنتيجة المقاسة هي أنقى تعبير عن المشكلة لدينا: فرق البايتات المقروءة عند العميل يصير صفرًا، ولا يوجد، بعبارة المرحِّل نفسه، «أي حدث إطلاقًا». المحرّك لا يرفع خطأ ولا يبلّغ عن نهاية البث. والسبب أن لا شيء خاطئ في طبقة HTTP، لأن الاستجابة ما زالت مفتوحة وما زالت تُسلَّم. والكلفة أن كل اكتشاف توقف لدينا لهذا النقل يستند إلى عدّاد واحد ونافذة أربع ثوانٍ، وإن كذب ذلك العدّاد يومًا يصمت المنتج معه.

عند بناء المرحِّل، كان أول ما وجب هزيمته خادم الويب الخاص بنا. فـ Kestrel يفرض افتراضيًا حدًّا أدنى لمعدل بيانات الاستجابة، 240 بايت في الثانية مع سماح خمس ثوانٍ، فالمقبس المفتوح الصامت هو بالضبط ما صُمّم لقتله. وكان عطل freeze سيظهر عند العميل كإغلاق مقبس: اختبار توقف وصول F1 يعمل بهدوء كاختبار نهاية بث F2، والمصفوفة كلها باطلة وكل حالة ما زالت تنجح. تُزال ثلاثة حدود قبل أن يقدّم المرحِّل بايتًا واحدًا.

زمن الاستجابة هو ذاكرتك المؤقتة على أحد النقلَين وأرضية على الآخر

يقول RFC 8216 إن العميل ينبغي ألا (SHOULD NOT) يبدأ من مقطع يبعد أقل من ثلاث مدد هدف عن نهاية قائمة التشغيل. ومع مدة هدف ست ثوانٍ، وهي اختيار شائع لا قيمة مقاسة، يكون ذلك ثماني عشرة ثانية خلف البث المباشر قبل أن يخزّن العميل إطارًا واحدًا من عنده، والمصدر هو من اختار ذلك الرقم حين قطّع البث. وتحتفظ مسودة الطبعة الثانية بثلاث مدد هدف كافتراضي وتضيف تأخيرًا منفصلًا لوضع زمن الاستجابة المنخفض حده الأدنى ضِعف مدة هدف الجزء، فلا تتحرك الأرضية إلا حين يقطّع المصدر البث إلى أجزاء. وهو قرار المصدر في الحالتين، لا المشغّل.

أما MPEG-TS التدرّجي فليس له أرضية من هذا القبيل. زمن الاستجابة هو ما يقرر العميل أن يحتفظ به، وضبطنا الحالي يحتفظ بالقليل جدًّا. يُبنى المحرّك بذاكرة شبكة مؤقتة قدرها 400 ms، ويطبّق مسار البث المباشر 1200 ms من تخزين الشبكة المؤقت فوق 800 ms من التخزين المؤقت المباشر. وتنخفض بلاطات العرض المتعدد إلى 350 و200 عند الكتم، و500 و350 مع الصوت. ويحصل تشغيل الطلب عند البعد على 1500 ms، لأن التمرير يحتاج ذاكرة مؤقتة أعمق مما تحتاجه قناة مباشرة. تلك قيم ضبط. والشخص التالي الذي يقيس زمن التنقل بين القنوات سيحرّك بعضها.

الذواكر المؤقتة الصغيرة ليست بلا ثمن. تلك هي المقايضة التي يفرضها عليك النقل، لا تفضيل. تدفق بايتات بوسادة 1200 ms يقع قريبًا من البث المباشر وله 1200 ms من التسامح مع تعثر. أما عميل HLS الجالس ثلاثة مقاطع إلى الخلف فله تسامح كبير ولا يستطيع إنفاقه. وحين يعلن كاشف إعادة التخزين المؤقت لدينا حلقة، ترفع معالجته أرضية التخزين المؤقت بمقدار 1000 ms عند إعادة التشغيل التالية، بسقف 5000 ms، وهي المقايضة نفسها تُجرى في وقت التشغيل بدل الإعدادات.

التقديم يأتي من الطول، لا من النقل

لا يقبل أي من النقلَين التقديم في البث المباشر في عميلنا، والعلم الذي يقرر ذلك لا يستشير النقل أبدًا.

// A live stream with no known length is not seekable in any way the scrubber could honour,
// whatever the demuxer claims; both position and live edge stay unknown then.
var seekAvailable = isSeekable && durationMs > 0;

شرطان، كلاهما مقروء من المشغّل. والاختبار الذي يثبّت هذا يسمّي النقل في تعليقه حيث لا تسمّيه الشيفرة: «TS مباشر نموذجي: قد يزعم المفكّك أنه قابل للتقديم لكن لا طول للتمرير عليه». يمرّر علم قابلية تقديم قيمته true مع طول صفر ويؤكد أن لا تقديم يُعرض. وذلك هو قاعدة الشيفرة تصرّح، في اختبار، بأن مفكّكًا تدرّجيًّا سيزعم بلا تردد قدرة لا يستطيع الوفاء بها، وأن الطول هو الحقل الذي يقول الحقيقة.

وما يبلّغ عنه libvlc لطول نافذة HLS مباشرة، لم نقسه، والقاعدة أعلاه مكتوبة بحيث لا يهم ذلك. فلو أنتجت نافذة منزلقة يومًا طولًا موجبًا لأضاء شريط التمرير ولعرضت طبقة النقل تقديمًا عبرها. وهل كان ذلك سيعمل، سؤال مفتوح من جانبنا، لا ادعاء.

إعادة البث هي النسخة الصادقة من التقديم إلى الخلف على مصدر بوابة، وهي ليست تقديمًا أصلًا: عنوان ثانٍ من بانٍ ثانٍ، يحمل مدة بالدقائق وطابع بداية على ساعة البوابة، وينتهي بـ .ts كأي شيء آخر. وللتسجيل القيد نفسه من السبب نفسه، إذ لا يمكن أن يكون تقدّم الالتقاط نسبة مئوية من مدة لا يعلنها المُدخل أبدًا.

حدٌّ واحد في آلية الاسترداد على شكل HLS، وهو الوحيد

كل نافذة حكم لا تعبأ بالنقل. أربع ثوانٍ من صفر بايتات في طبقة الوصول، وست ثوانٍ من بايتات تصل بينما المفكّك لا ينتج شيئًا، وأربع ثوانٍ من فيديو متوقف مقابل صوت مباشر، وأربع للاثنين متوقفَين معًا، وخمس عشرة على قناة مقاسة بمعدل إطارات منخفض. ليس لأي منها قيمة ثانية لـ HLS، ولا يُختار أي منها بنوع المصدر.

الاستثناء هو عدّ إعادة التخزين المؤقت، وملف الخيارات يذكر السبب في موضعه: تُحسب النوبات فقط حين تهبط الذاكرة المؤقتة تحت أرضية لا عند أي تقرير دون 100، لأن «ذاكرة HLS المباشرة المؤقتة تتذبذب عبر حدود المقاطع والعدّ الخام لما دون 100 كان سيَسِم تدفقات سليمة». يعمل التباطؤ من 62 بالمئة لبدء نوبة إلى 88 لإنهائها، وأربع نوبات في 60 ثانية متحركة تعلن حلقة. ويحمل ستار التخزين المؤقت تباطؤًا خاصًا به للتذبذب نفسه، وتعليقه يضع الأثر عند نحو ثانيتين قبل الإطارات المفتاحية. وكلاهما موجود لأن مستوى الذاكرة المؤقتة في تدفق يقوده ملف بيان يتأرجح بالتصميم، والحد الخام يقرأ ذلك التأرجح مرضًا.

الاعتراف الذي ينتمي إلى هنا أكبر من حد واحد. فنموذج العدّادات كله خلف اكتشاف الأعطال عُيِّر على MPEG-TS خام، حيث تقع طبقة الوصول والمفكّك في علاقة تسلسلية نظيفة والفجوة بينهما تعني شيئًا محددًا. أما ما يفعله مفكّك تكيّفي بتلك العلاقة حين يُصدر جلباته الخاصة، فلم نقسه، فلن أقول لك إن التقسيم خاطئ على HLS، بل فقط إنه لم يُفحص قط. نحمل وسمًا كان سيتيح لنا التفريع. ولم نكتب قط حدًّا واحدًا خاصًّا بـ HLS، ومن دون قياس عن بُعد من الأسطول لا نستطيع أن نقول ما كلفة ذلك. وثمة تباين واحد نعالجه من غير قصد: أولية إعادة التشغيل تتخلص من الوسيط وتعيد تطبيق العنوان من الصفر، وهو ما تلاحظ الخطة أنه يجدّد الرموز في جلسات HLS المضمَّنة في العنوان.

القدرة الوحيدة التي يشتريها لنا ملف البيان حقًّا في الشيفرة المشحونة أصغر من كل هذا. سقوف الجودة، المطبَّقة على بلاطات العرض المتعدد فقط، 640 في 360 للبلاطة المكتومة و1280 في 720 لتلك التي معها صوت، إضافة إلى طلب أدنى جودة في الملف المكتوم. وعلى MPEG-TS التدرّجي تلك الخيارات خاملة، لأنه لا جودات لتُسقَف، والمشغّل يقبلها بصمت بدل أن يشتكي. ولهذا تُقيَّد بملف البلاطة لا بنوع المصدر: فخيار لا يكلّف شيئًا حين لا يفعل شيئًا أرخص أن يُطبَّق بلا شرط من أن يُحرس بمصنِّف أثبتنا بالفعل أنه يخطئ في وسم 17 صفًا على الأقل من 2,203. أما تشغيل البث المباشر بملء الشاشة فلا يستخدمها إطلاقًا.

الحد الصادق: قائمتا التشغيل المقاستان هنا هما كل الدليل، ولا نملك أي مجموعة من عناوين البث المباشر للبوابات إطلاقًا. كل ما سبق يصف الطلب الذي يقدّمه عميلنا والشيفرة التي تتفاعل مع ما يعود، لا ما ترسله البوابات أبدًا. وتبقى قراءة العنوان الذي يسلّمك إياه مصدرك أسرع طريقة لمعرفة أيّ الشكلَين أنت فيه. وعلى تطبيقَي Windows وXbox تبقى تلك عملية محلية: فهما يفتحان العنوان الذي توجّههما إليه ويحلّلانه على الجهاز، ولا يحملان قنوات خاصة بهما ولا يجلبان شيئًا نيابةً عنك من أي مكان آخر. وسيعرض لك حوار معلومات البث ما يزعمه العنوان عن نفسه، مع التحفظ المبيَّن سابقًا حول ما يعنيه ذلك الصف حقًّا، وحساب مجاني يكفي للذهاب والنظر.

ما قياس هذه المادة35 ادعاءات، كل منها مزود بالأدلة التي تقف خلفه
المطالبةالأدلةعد
مصنِّف النقل الوحيد على مسار التشغيل هو اختبار سلسلة فرعية غير حساس لحالة الأحرف عن ".m3u8" على كامل العنوان، يُقيَّم عند كل تطبيق لوسيط مباشر. وكل ما عداه يقع افتراضيًا على "ts".n = 123‏/08‏/2026
لا يقرأ أي حد أو مهلة أو تفريع في أي مكان من الرقيب نوع المصدر. وكل ظهور له إما تصريح أو إسناد أو نسخة أو حقل سجل.n = 123‏/08‏/2026
يصل نوع المصدر إلى سطر Debug عند تسليح الجلسة وإلى حدث Serilog من مستوى Information باسم wd.fault عند كل حكم بعطل. أما السجل المنمَّط الذي كان يُفترض أن يحمله إلى خادم خلفي فمُصرَّح به ولا يُبنى أبدًا.n = 123‏/08‏/2026
بتشغيله على قائمتَي التشغيل اللتين نحتفظ بهما لعمل المحلِّل، يسِم المصنِّف المشحون 1,930 من 2,203 صفوف بـ "hls" و273 بـ "ts". و7 بالضبط من العناوين الـ 2,203 تنتهي بـ ".ts".n = 220323‏/08‏/2026
لواحق المسارات على مستوى المجموعة كلها: 1,924 .m3u8، و137 بلا امتداد، و16 بلا امتداد لأن ip:port يقع في المسار، و75 .php، و17 .mpd، و14 .htm، و7 .ts، و6 .m3u، و3 .2ts، وواحد من كل من .smil و.dash و.mp4 و.wmv. ومن الصفوف الـ 273 التي يسميها المصنِّف "ts"، 147 بلا امتداد مقروء.n = 220323‏/08‏/2026
ستة صفوف تُصنَّف HLS لأن ".m3u8" يظهر في سلسلة الاستعلام لا في نهاية المسار. ولكل واحد من هذه الستة مسار بلا امتداد. ولا يحمل أي صف في المجموعة الرمز في وسط المسار، ولا يحمل أي صف في أي مكان مفتاح استعلام "out".n = 220323‏/08‏/2026
أربعة عشر صفًا تحمل معامل استعلام output قيمته 7، وكلها الأربعة عشر تقع على مسارات تنتهي بـ .htm إلى جانب مفتاحَي cont وforceUserAgent. وصفان يضبطان output على playlist.m3u8. وستون صفًا مقطعها الأخير في المسار get.php ولا يحمل واحد منها معامل output إطلاقًا.n = 220323‏/08‏/2026
امتداد ملف قائمة التشغيل نفسه لا يتنبأ بلواحق العناوين داخله. فملف .m3u في مجموعتنا يشير إلى 303 عناوين تنتهي بـ .m3u8 ولا واحد ينتهي بـ .ts.n = 30823‏/08‏/2026
قائمتا التشغيل المقاستان هنا ملفان مُنتقيان على نمط الدليل، لا صادرات بوابات، وغلبة HLS فيهما لا تقول شيئًا عما تقدّمه البوابة.n = 223‏/08‏/2026
باني عنوان البث المباشر لـ Xtream في العميل يثبّت لاحقة .ts في الشيفرة بلا معامل ولا تفريع، وباني إعادة البث يفعل الشيء نفسه. هذا ما نطلبه؛ ولا شيء هنا يرصد ما تعيده البوابة.n = 123‏/08‏/2026
عنصر التحكم «تنسيق البث» المعروض على مصادر Xtream يطبِّع القيمة ويحفظها ويعيد تحميلها، ولا يقرأه أي بانٍ للعناوين ولا أي شيفرة تشغيل. ومهما ضُبط عليه، يطلب عميل سطح المكتب .ts.n = 123‏/08‏/2026
حوار معلومات البث يستخرج Protocol من مخطط URI وContainer من امتداد الملف في المسار، مرتدًّا إلى "N/A" حين لا يحمل المسار امتدادًا. وهو مصنِّف ثانٍ مستخرج من العنوان ولا يتفق مع مصنِّف الرقيب.n = 123‏/08‏/2026
سجل القناة المباشرة لا يحمل حقل حاوية ولا نقل ولا MIME، فالنقل ليس أبدًا صفة للقناة ولا يمكن قراءته إلا من العنوان.n = 123‏/08‏/2026
يقدّم HLS قائمة تشغيل وسائط تسرد مقاطع وسائط تحت مدة هدف مُعلنة، والعميل الذي يتابع عرضًا مباشرًا يجب (MUST) أن يعيد تحميل تلك القائمة دوريًا ليعرف ما الوسائط المتاحة.RFC 8216 section 4.3.3.1 (EXT-X-TARGETDURATION, REQUIRED) and section 6.3.4 (Reloading the Media Playlist File), verbatim: "The client MUST periodically reload a Media Playlist file to learn what media is currently available", and must wait at least the target duration between reloads that found a change.المواصفاتلا ينطبق
يدرج RFC 8216 تدفقات النقل MPEG-2 بين صيغ مقاطع الوسائط المدعومة، فيمكن أن يكون مقطع HLS هو ذات الحزم ذات 188 بايت مقطَّعة في ملف. أما كم مرة يكون كذلك، فلم نقسه.RFC 8216 section 3.1 (Supported Media Segment Formats) and section 3.2 (MPEG-2 Transport Streams), which requires a single MPEG-2 Program per segment and a PAT plus PMT in each segment absent an EXT-X-MAP tag. Sections 3.3 through 3.5 cover fragmented MPEG-4, packed audio and WebVTT.المواصفاتلا ينطبق
العميل الذي يشغّل عرض HLS مباشرًا ينبغي ألا (SHOULD NOT) يختار مقطع بداية يبدأ قبل أقل من ثلاث مدد هدف من نهاية قائمة التشغيل.RFC 8216 section 6.3.3 (Playing the Media Playlist File), verbatim: "If the EXT-X-ENDLIST tag is not present and the client intends to play the media normally, the client SHOULD NOT choose a segment that starts less than three target durations from the end of the Playlist file. Doing so can trigger playback stalls."المواصفاتلا ينطبق
تحتفظ مسودة الطبعة الثانية من HLS بثلاث مدد هدف كمسافة افتراضية عن حافة البث المباشر وتضيف PART-HOLD-BACK لوضع زمن الاستجابة المنخفض، وحدها الأدنى ضِعف مدة هدف الجزء. والأجزاء أقصر بكثير من المقاطع، وهكذا يدخل HLS منخفض زمن الاستجابة إلى ما دون مقطع واحد من الحافة.draft-pantos-hls-rfc8216bis section 4.4.3.8 (EXT-X-SERVER-CONTROL). HOLD-BACK: "Its value MUST be at least three times the Target Duration ... Its absence implies a value of three times the Target Duration." PART-HOLD-BACK: "Its value MUST be at least twice the Part Target Duration." The draft header reads "Obsoletes: 8216 (if approved)".المواصفاتلا ينطبق
تدفق النقل ليس بلا بنية في الزمن. فالمعيار ISO/IEC 13818-1 يقيّد المسافة الفاصلة بين مراجع ساعة البرنامج، ومعيار المراقبة لدى DVB يحوّل تكرار الجداول والاستمرارية إلى فحوص نجاح أو فشل.ISO/IEC 13818-1 (transport stream system layer, PCR interval constraint); ETSI TR 101 290 V1.4.1 (2020-06) Priority 1 measurements, which include TS_sync_loss, Sync_byte_error, PAT_error and PAT_error_2 on a 500 ms PAT repetition limit, Continuity_count_error, PMT_error and PMT_error_2, and PID_error.المواصفاتلا ينطبق
ما يسلّمه لنا المشغّل هو لقطة من عدّادات خط المعالجة التراكمية، وآلة الحالة تعمل حصرًا على الفروق بين عيّنتين متعاقبتين. ولا حقل فيها هو توقيت جداول.n = 123‏/08‏/2026
تدفق النقل MPEG-2 هو سلسلة حزم بحجم 188 بايت تحمل جدول ارتباط البرامج، وجدول خريطة البرنامج، والتدفقات الأولية على PIDs خاصة بها، ومرجع ساعة البرنامج، وحزمًا فارغة على PID 0x1FFF للحشو.ISO/IEC 13818-1, transport stream packet syntax; mirrored in our own synthetic muxer at clients/windows/tools/FaultRelay/Media/TsMuxer.cs:15-20, which declares PacketSize 188, PatPid 0x0000, PmtPid 0x1000, VideoPid 0x0100, AudioPid 0x0101 and NullPid 0x1FFF.المواصفاتلا ينطبق
مرحِّل حقن الأعطال أداة اختبار محلية للمطوّر تولّد فيديو اصطناعيًا على واجهة الاسترجاع. ولا يُنشر أبدًا، ولا يُضاف إلى أي مخطط أو ملف compose، ولا تشير إليه أي خدمة خلفية.n = 116‏/08‏/2026
يولّد المرحِّل تدفق نقل ببرنامج واحد بنحو 4.6 Mbit/s بإعداداته الافتراضية، مع PCR على PID الفيديو وعدّادات استمرارية لكل PID.n = 116‏/08‏/2026
عطل في المرحِّل يوقف الكتابة ويترك المقبس قائمًا ينتج فرق بايتات مقروءة قدره صفر عند العميل ولا يصدر أي حدث من المحرّك إطلاقًا.n = 116‏/08‏/2026
تدفق مختزَل إلى جداول البرنامج زائد حزم فارغة يحافظ على معدل بايتاته بينما يتضوّر المفكّك جوعًا. وشكل الفشل هذا يخص الحاوية لا التسليم التدرّجي: فعرض HLS بمقاطع تدفق نقل يمكن أن ينتجه، وعرض بمقاطع fMP4 ليس له حشو مكافئ.n = 116‏/08‏/2026
يزيل المرحِّل ثلاثة حدود من Kestrel قبل أن يقدّم بايتًا واحدًا، لأن الحد الأدنى الافتراضي لمعدل بيانات الاستجابة كان سيقطع عطل تجميد البايتات ويحوّل كل اختبار توقف وصول F1 إلى اختبار إغلاق مقبس F2.n = 116‏/08‏/2026
الحد الأدنى الافتراضي لمعدل بيانات الاستجابة في Kestrel هو 240 بايت في الثانية مع فترة سماح خمس ثوانٍ.Microsoft ASP.NET Core Kestrel options documentation, MinResponseDataRate default.المواصفاتلا ينطبق
علم التقديم في البث المباشر هو اقتران علم قابلية التقديم لدى المشغّل مع طول موجب. والنقل ليس مُدخلًا، ويبقى الموضع وحافة البث المباشر كلاهما null حين يفشل الاقتران.n = 123‏/08‏/2026
لا يمكن الإبلاغ عن تقدّم التسجيل كنسبة مئوية في التقاط مباشر لأن مدة المُدخل غير معروفة.n = 123‏/08‏/2026
خيارات النقل الوحيدة التي نشحنها هي سقوف الجودة، وتُطبَّق على بلاطات العرض المتعدد فقط: 640 في 360 مكتومًا، و1280 في 720 مع صوت، إضافة إلى اختيار أدنى جودة في الملف المكتوم. أما البث المباشر بملء الشاشة فلا يحصل على أي منها.n = 123‏/08‏/2026
الضبط الحالي: يُبنى المحرّك بذاكرة شبكة مؤقتة قدرها 400 ms، ويطبّق مسار البث المباشر 1200 ms للشبكة و800 ms للتخزين المؤقت المباشر، وتنخفض بلاطات العرض المتعدد إلى 350/200 مكتومة و500/350 مع صوت، ويستخدم الطلب عند البعد 1500 ms.n = 123‏/08‏/2026
كل نافذة حكم لا تعبأ بالنقل: 4 s من صفر بايتات، و6 s من مفكّك متضوّر، و4 s من فيديو متوقف، و4 s من تجميد كلي، و15 s على قناة منخفضة معدل الإطارات.n = 523‏/08‏/2026
الحد الوحيد الذي شكّله HLS هو عدّ إعادة التخزين المؤقت: تُحسب النوبة فقط تحت 62 بالمئة من الذاكرة المؤقتة وتنتهي عند 88، وأربع نوبات في نافذة 60 s تعلن حلقة، والمعالجة ترفع أرضية التخزين المؤقت بمقدار 1000 ms لكل حكم حتى سقف 5000 ms.n = 123‏/08‏/2026
يحمل ستار التخزين المؤقت تباطؤًا خاصًا به للسبب نفسه، وتعليق الشيفرة ينسب التذبذب إلى حدود مقاطع HLS عند نحو ثانيتين قبل الإطارات المفتاحية.n = 123‏/08‏/2026
نموذج العدّادات الذي يقف خلف اكتشاف الأعطال عُيِّر على MPEG-TS خام، ولا حد نشحنه خاص بـ HLS.n = 123‏/08‏/2026
أولية إعادة التشغيل تتخلص من الوسيط وتعيد تطبيق العنوان من الصفر، وهو ما تلاحظ الخطة أنه يجدّد الرموز في جلسات HLS المضمَّنة في العنوان.n = 123‏/08‏/2026