إصلاح خطأ Rumble 403 في yt-dlp باستخدام بيانات المشغل
تاريخ النشر
تنزيل إضافة الإصلاح rumble_player.py
إذا ظهر الخطأ Unable to download JSON metadata: HTTP Error 403: Forbidden عند تنزيل فيديو من Rumble باستخدام yt-dlp، يمكنك تحميل إضافة التوافق الواردة في هذا المقال. عندما تعيد واجهة JSON المسماة embedJS/u3 في Rumble الخطأ 403، تجلب الإضافة تلقائيا صفحة المشغل المضمن الرسمي (/embed/) للفيديو نفسه، وتستخرج بيانات الوسائط الموجودة فيها، ثم تتابع التنزيل.
إذا كنت تفضل تجنب إعداد الإضافة محليا أو تحويل الروابط يدويا، يمكنك استخدام أداة تنزيل فيديوهات Rumble على موقعنا، فهي تتضمن هذا الإصلاح بالفعل.
حدد المرحلة التي يظهر فيها الخطأ 403
قد يظهر الخطأ 403 في ثلاث مراحل مختلفة أثناء تنزيل فيديو من Rumble. تعالج هذه الإضافة الحالة الثانية تحديدا:
| رسالة الخطأ | موضع الحظر | الإجراء المناسب |
|---|---|---|
Unable to download webpage: HTTP Error 403 |
حظر HTML الخاص بصفحة المشاهدة، كما في البلاغ #15089 | احصل على عنوان /embed/ من واجهة oEmbed الرسمية واستخدم --impersonate firefox |
Unable to download JSON metadata: HTTP Error 403 |
حظر واجهة البيانات الوصفية embedJS/u3، كما في البلاغ #17496 |
استخدم إضافة هذا المقال للانتقال تلقائيا إلى البيانات المضمنة في صفحة /embed/ |
| تظهر قائمة الصيغ، لكن تنزيل أجزاء الفيديو أو ملف MP4 يعيد الخطأ 403 | ترفض CDN طلب تدفق الوسائط | تحقق من الوكيل وترويسات الطلب أو اختر صيغة بجودة أخرى |
خطوات تطبيق الإصلاح
1. احفظ ملف الإضافة
أنشئ بنية المجلدات التالية داخل مجلد العمل، ثم احفظ كود الإضافة الكامل باسم rumble_player.py. لا تحتاج إلى تعديل الكود المصدري لـ yt-dlp:
plugins/
└── rumble/
└── yt_dlp_plugins/
└── extractor/
└── rumble_player.py
2. احصل على عنوان /embed/ الرسمي للفيديو
معرف الفيديو في عنوان صفحة المشاهدة على Rumble، مثل v6xxxx، يختلف عن معرف المشغل المضمن، مثل vb0ofn. لذلك لا يمكن تركيب العنوان يدويا باستخدام المعرف نفسه. إذا كان لديك رابط صفحة المشاهدة فقط، فاستدع واجهة oEmbed العامة والرسمية من Rumble للحصول على عنوان /embed/ الصحيح:
curl -fsSG --data-urlencode "url=https://rumble.com/your-video.html" "https://rumble.com/api/Media/oembed.json"
ابحث في الحقل html من استجابة JSON عن <iframe src="https://rumble.com/embed/xxxx/..."، ثم انسخ الجزء https://rumble.com/embed/xxxx/.
إذا أعاد oEmbed الخطأ 403، ثبّت curl_cffi وأعد المحاولة باستخدام بصمة Firefox. استبدل الرابط في الأمر أدناه بالرابط الكامل لصفحة المشاهدة.
python -m pip install curl_cffi
python -c "import sys; from curl_cffi import requests; r = requests.get('https://rumble.com/api/Media/oembed.json', params=dict(url=sys.argv[1]), impersonate='firefox', timeout=15); r.raise_for_status(); print(r.text)" "https://rumble.com/your-video.html"
إذا فشلت المحاولة مجددا، استخدم أداة التنزيل عبر الإنترنت لتحويل الرابط تلقائيا.
3. اعرض الصيغ وتحقق من المسار البديل
نفذ الأمر من المجلد الذي يحتوي على plugins، واستبدل العنوان بعنوان /embed/ للفيديو المطلوب:
yt-dlp --ignore-config --plugin-dirs ./plugins --no-cache-dir -v -F "https://rumble.com/embed/vb0ofn/"
ظهور [RumbleEmbed+PlayerFallback] في السجل يؤكد تحميل الإضافة:
- إذا أعادت واجهة JSON الخطأ 403، فسيظهر بعدها السطر
Downloading player webpage. يؤكد هذا السطر تشغيل المسار البديل فقط؛ ولا يمكن تأكيد نجاح تحليل البيانات إلا عندما تظهر قائمة الصيغ بعده. - إذا أعادت واجهة JSON الحالة 200 على اتصالك الحالي، يستمر المسار الأصلي دون إرسال طلب إضافي إلى صفحة المشغل.
4. نزل الفيديو وافحص فك الترميز
اختر معرف صيغة من القائمة التي يعرضها -F، مثل mp4-360p، ثم نفذ التنزيل:
yt-dlp --ignore-config --plugin-dirs ./plugins --no-cache-dir -v --no-playlist -f mp4-360p -o "rumble-test.%(ext)s" "https://rumble.com/embed/vb0ofn/"
فيما يلي سجل الطرفية من الاختبار الذي شغل المسار البديل:
[RumbleEmbed+PlayerFallback] vb0ofn: Downloading JSON metadata
[RumbleEmbed+PlayerFallback] vb0ofn: Downloading player webpage
[info] vb0ofn: Downloading 1 format(s): mp4-360p
[download] 100% of 7.85MiB in 00:01:20 at 99.48KiB/s
للتحقق من سلامة حاوية MP4 ومساري الصوت والصورة بعد التنزيل، استخدم ffprobe وffmpeg:
ffprobe -v error -show_entries stream=codec_name,codec_type,width,height:format=duration,size -of json "rumble-test.mp4"
ffmpeg -nostdin -v error -xerror -i "rumble-test.mp4" -map 0:v:0 -map "0:a:0?" -f null -
كيف تسمح صفحة المشغل بمتابعة التنزيل بعد خطأ JSON 403؟
1. إعادة استخدام البيانات المضمنة في الصفحة الرسمية
يطلب RumbleEmbedIE افتراضيا البيانات الوصفية بصيغة JSON مباشرة من https://rumble.com/embedJS/u3/?request=video&ver=2&v=.... إذا حظر Cloudflare أو نظام حماية الموقع هذه الواجهة تحديدا وأعاد HTTP 403، يتوقف الاستخراج.
لكن سكربتات الصفحة الرسمية https://rumble.com/embed/<video_id>/ تتضمن بالفعل كائن إعدادات للفيديو بالبنية نفسها. يحتوي هذا الكائن على الحقل ua بعناوين التدفقات لمختلف مستويات الجودة، بالإضافة إلى العنوان والمدة وغيرها من الحقول. يكفي استخراج هذا الكائن وإعادته من _download_json كي يستمر كود تحليل الصيغ في yt-dlp دون أي تعديل.
2. إزالة الحقل غير الصالح في JSON (loaded: h())
الكائن المضمن في الصفحة ليس قيمة JSON صالحة بالكامل. ففي نهايته استدعاء دالة وقت التشغيل، loaded: h()، كما في المثال التالي:
u.f["vb0ofn"] = {"ua": {"mp4": {"360": {"url": "https://..."}}}, "title": "...", loaded: h()};
إذا مررناه مباشرة إلى محلل JSON، فستسبب h() خطأ في الصياغة. لذلك تستخدم الإضافة خيار transform_source في _search_json لإزالة الجزء الأخير , loaded: xxx() فقط بتعبير نمطي قبل التحليل. تتم العملية كلها على النص في الذاكرة، دون تنفيذ أي JavaScript من الصفحة:
- مطابقة دقيقة: لا تستخرج الإضافة إلا الكائن الذي يساوي مفتاحه
video_idالحالي (\b[\w$]+\.f\[\s*["']{video_id}["']\s*\]\s*=)، ثم تتحقق من أن النتيجة قاموس يحتوي على حقل وسائطuaغير فارغ. - تدخل محدود: لا يعمل المسار البديل إلا عندما يلتقط
_download_jsonاستثناءHTTPErrorبالحالة403. أما الأخطاء 401 و404 و429 و500، أو غياب كائن صالح في الصفحة، فتؤدي إلى إعادة رفع الاستثناء الأصلي دون تغييره. - التكامل مع خدمتنا: إلى جانب تحميل الإضافة، تستدعي خدمتنا عبر الإنترنت واجهة oEmbed لتحويل روابط صفحات المشاهدة إلى عناوين
/embed/. وإذا لم يحدد المستخدم--impersonate، تستخدم الخدمة افتراضيا بصمة المتصفحfirefox-135.
كود الإضافة الكامل
احفظ الكود التالي في plugins/rumble/yt_dlp_plugins/extractor/rumble_player.py. تم التحقق منه باستخدام Python 3.12+ وyt-dlp 2026.10.10+:
"""Reuse official player media data when Rumble's JSON endpoint is blocked."""
import re
from yt_dlp.extractor.rumble import RumbleEmbedIE as BaseRumbleEmbedIE
from yt_dlp.networking.exceptions import HTTPError
from yt_dlp.utils import ExtractorError
class RumbleEmbedIE(BaseRumbleEmbedIE, plugin_name='PlayerFallback'):
def _real_extract(self, url):
self._player_url = url
return super()._real_extract(url)
def _download_json(self, url_or_request, video_id, *args, **kwargs):
try:
return super()._download_json(url_or_request, video_id, *args, **kwargs)
except ExtractorError as error:
if not isinstance(error.cause, HTTPError) or error.cause.status != 403:
raise
webpage = self._download_webpage(self._player_url, video_id, note='Downloading player webpage')
# Parse this video's object and strip the runtime call without executing page scripts.
data = self._search_json(
rf'''\b[\w$]+\.f\[\s*["']{re.escape(video_id)}["']\s*\]\s*=\s*''',
webpage, 'player data', video_id,
fatal=False,
transform_source=lambda source: re.sub(r',\s*loaded\s*:\s*[\w$]+\(\s*\)\s*(?=})', '', source))
if not isinstance(data, dict) or not data.get('ua'):
raise error
return data