ytdlp.online
หน้าแรก Tampermonkey

วิธีแก้ปัญหาทั้งหมด

สารบัญ

แก้ yt-dlp Rumble 403: อ่านข้อมูลจากตัวเล่นเมื่อคำขอ JSON ล้มเหลว

วันที่เผยแพร่

ดาวน์โหลดปลั๊กอินแก้ไขข้อผิดพลาด rumble_player.py

หากใช้ yt-dlp ดาวน์โหลดวิดีโอ Rumble แล้วพบ Unable to download JSON metadata: HTTP Error 403: Forbidden สามารถโหลดปลั๊กอินแก้ปัญหาความเข้ากันได้ที่ให้ไว้ในบทความนี้ได้ เมื่อ JSON API embedJS/u3 ของ Rumble ส่งกลับ 403 ปลั๊กอินจะเปลี่ยนไปดึงหน้าตัวเล่นแบบฝังทางการ (/embed/) ของวิดีโอเดียวกันโดยอัตโนมัติ แล้วแยกข้อมูลสื่อที่ฝังอยู่ในหน้าเพื่อดาวน์โหลดต่อ

หากไม่ต้องการตั้งค่าปลั๊กอินบนเครื่องหรือแปลงลิงก์ด้วยตนเอง สามารถใช้เครื่องมือดาวน์โหลดวิดีโอ Rumble ของเว็บไซต์นี้ ซึ่งรวมวิธีแก้ดังกล่าวไว้แล้ว

ตรวจสอบก่อนว่า 403 เกิดขึ้นในขั้นตอนไหน

ข้อผิดพลาด 403 ระหว่างดาวน์โหลด Rumble อาจเกิดได้ในสามขั้นตอน ปลั๊กอินในบทความนี้แก้เฉพาะกรณีที่สอง:

ข้อผิดพลาดหรืออาการ คำขอที่ถูกบล็อก วิธีจัดการ
Unable to download webpage: HTTP Error 403 HTML ของหน้ารับชมถูกบล็อก (ดู issue #15089) ใช้ oEmbed API ทางการเพื่อแปลงเป็น URL /embed/ พร้อมใช้ --impersonate firefox
Unable to download JSON metadata: HTTP Error 403 API เมทาดาทา embedJS/u3 ถูกบล็อก (ดู issue #17496) ใช้ปลั๊กอินในบทความนี้ เพื่อเปลี่ยนไปอ่านข้อมูลที่ฝังอยู่ในหน้า /embed/ โดยอัตโนมัติ
แสดงรายการรูปแบบได้ แต่เกิด 403 ขณะดาวน์โหลดส่วนย่อยหรือ MP4 คำขอสตรีมสื่อไปยัง CDN ถูกปฏิเสธ ตรวจสอบพร็อกซีและเฮดเดอร์ของคำขอ หรือเลือกรูปแบบที่มีความละเอียดอื่น

ขั้นตอนแก้ไขอย่างรวดเร็ว

1. บันทึกไฟล์ปลั๊กอิน

สร้างโฟลเดอร์ตามโครงสร้างต่อไปนี้ในไดเรกทอรีทำงาน แล้วบันทึกโค้ดปลั๊กอินฉบับเต็มท้ายบทความ เป็น rumble_player.py โดยไม่ต้องแก้ซอร์สโค้ดของ yt-dlp:

plugins/
└── rumble/
    └── yt_dlp_plugins/
        └── extractor/
            └── rumble_player.py

2. ดึง URL /embed/ ทางการของวิดีโอ

ID ใน URL หน้ารับชมของ Rumble เช่น v6xxxx ไม่ใช่ ID เดียวกัน กับ ID ของตัวเล่นแบบฝัง เช่น vb0ofn จึงนำ ID จากหน้ารับชมมาประกอบเป็น URL แบบฝังโดยตรงไม่ได้ หากมีเพียงลิงก์หน้ารับชมทั่วไป ให้เรียก oEmbed API สาธารณะของ Rumble เพื่อรับ URL /embed/ ที่ถูกต้อง:

curl -fsSG --data-urlencode "url=https://rumble.com/your-video.html" "https://rumble.com/api/Media/oembed.json"

ค้นหา <iframe src="https://rumble.com/embed/xxxx/..." ในฟิลด์ html ของ JSON ที่ส่งกลับ แล้วนำส่วน https://rumble.com/embed/xxxx/ มาใช้

หาก oEmbed ตอบกลับด้วยรหัส 403 ให้ติดตั้ง curl_cffi แล้วลองใหม่โดยใช้ลายนิ้วมือของ Firefox เปลี่ยน URL ตัวอย่างด้านล่างเป็น URL แบบเต็มของหน้าวิดีโอ

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 โดยเปลี่ยน URL เป็นที่อยู่ /embed/ ของวิดีโอเป้าหมาย:

yt-dlp --ignore-config --plugin-dirs ./plugins --no-cache-dir -v -F "https://rumble.com/embed/vb0ofn/"

หากบันทึกการทำงานแสดง [RumbleEmbed+PlayerFallback] แสดงว่าปลั๊กอินถูกโหลดแล้ว:

  • หาก JSON API ส่งกลับ 403 จะมีข้อความ Downloading player webpage ตามมา ซึ่งยืนยันเพียงว่าเส้นทางสำรองเริ่มทำงานแล้ว ต้องมีรายการรูปแบบแสดงตามมาจึงจะยืนยันได้ว่าแยกวิเคราะห์ข้อมูลสำเร็จ
  • หาก JSON API ส่งกลับ 200 ในสภาพแวดล้อมเครือข่ายปัจจุบัน yt-dlp จะใช้กระบวนการเดิมต่อ โดยไม่ส่งคำขอเพิ่มไปยังหน้าตัวเล่น

4. ดาวน์โหลดวิดีโอและตรวจสอบการถอดรหัส

เลือก ID รูปแบบจากรายการที่ได้ด้วย -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 จะส่งคำขอไปยัง https://rumble.com/embedJS/u3/?request=video&ver=2&v=... โดยตรงเพื่อรับเมทาดาทา JSON หาก Cloudflare หรือระบบควบคุมการเข้าถึงของเว็บไซต์บล็อกเฉพาะ API นี้และส่งกลับ HTTP 403 การดึงข้อมูลจะหยุดลง

แต่เมื่อเปิดหน้าฝังทางการ https://rumble.com/embed/<video_id>/ สคริปต์ของหน้าได้ฝังออบเจ็กต์การตั้งค่าวิดีโอที่มีโครงสร้างเหมือนกันไว้แล้ว ออบเจ็กต์นี้มี ua ซึ่งเก็บ URL สตรีมแต่ละระดับความละเอียด รวมถึงชื่อวิดีโอ ระยะเวลา และฟิลด์อื่น ๆ เพียงแยกออบเจ็กต์นี้ออกมาแล้วคืนค่าให้ _download_json yt-dlp ก็ทำงานต่อได้โดยไม่ต้องเปลี่ยนโค้ดแยกวิเคราะห์รูปแบบในขั้นตอนถัดไปแม้แต่บรรทัดเดียว

2. ลบฟิลด์ที่ไม่ใช่ JSON มาตรฐาน (loaded: h())

ออบเจ็กต์ข้อมูลที่ฝังในหน้าไม่ได้เป็น JSON literal ที่ถูกต้องทั้งหมด ส่วนท้ายมีการเรียกฟังก์ชันขณะรัน loaded: h() ดังนี้:

u.f["vb0ofn"] = {"ua": {"mp4": {"360": {"url": "https://..."}}}, "title": "...", loaded: h()};

หากส่งเข้า JSON parser โดยตรง 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 API อัตโนมัติเพื่อแปลง URL หน้ารับชมที่ผู้ใช้ป้อนเป็น /embed/ และใช้ลายนิ้วมือ firefox-135 เป็นค่าเริ่มต้นเมื่อไม่ได้ระบุ --impersonate

โค้ดปลั๊กอินฉบับเต็ม

บันทึกโค้ดต่อไปนี้เป็น 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
เครื่องมือ yt-dlp
ดูเครื่องมือ yt-dlp ทั้งหมด
ความช่วยเหลือและเอกสาร yt-dlp