Add Reddit video support
Reddit links now download and post like the other platforms. Two changes were needed, not just the URL pattern: - Regex: yt-dlp's Reddit extractor only matches /comments/ permalinks, so the app's /r/<sub>/s/<code> share links and redd.it / v.redd.it shortlinks are listed explicitly — they redirect to the canonical URL, which yt-dlp follows. Without them the link is silently dropped. - Format selector: Reddit publishes video and audio as separate DASH/HLS streams with no muxed rendition, so every `best...` term failed and yt-dlp aborted with "Requested format is not available". Added a bv*+ba merge tail (and a bare bv* for silent videos) to the normal and /force selectors. Muxed hosts still resolve at the earlier terms, so YouTube/IG/TikTok/X selection is unchanged. Posts with no video report "No media found", already in the silent list, so ordinary Reddit links shared in chat draw no reply.
This commit is contained in:
@@ -30,7 +30,19 @@ TWITTER_URL_PATTERN = r"https?://(?:www\.)?(?:twitter\.com|x\.com|fxtwitter\.com
|
||||
INSTAGRAM_URL_PATTERN = r"https?://(?:www\.)?instagram\.com/(?:share/)?(?:reels?|p|tv)/[\w-]+"
|
||||
YOUTUBE_URL_PATTERN = r"https?://(?:www\.)?(?:youtube\.com/(?:watch\?v=|shorts/)|youtu\.be/)[\w-]+"
|
||||
TIKTOK_URL_PATTERN = r"https?://(?:(?:www|m)\.tiktok\.com/(?:@[\w.-]+/video/\d+|t/\w+|v/\d+)|(?:vm|vt)\.tiktok\.com/\w+)"
|
||||
VIDEO_URL_PATTERN = rf"(?:{TWITTER_URL_PATTERN}|{INSTAGRAM_URL_PATTERN}|{YOUTUBE_URL_PATTERN}|{TIKTOK_URL_PATTERN})"
|
||||
# Reddit's canonical form is /r/<sub>/comments/<id>/<slug>, but the mobile share
|
||||
# sheet emits /r/<sub>/s/<code> and older shares use redd.it/<id>; both are plain
|
||||
# redirects to the canonical URL, which yt-dlp follows. v.redd.it/<id> is the bare
|
||||
# media host. Any subdomain (www/old/new/np/m) is valid. yt-dlp's own extractor
|
||||
# only matches the /comments/ form, so the redirecting shapes must be listed here
|
||||
# explicitly or the link is silently dropped (regex never matches -> no download,
|
||||
# no error reply). Most Reddit links carry no video at all; the extractor reports
|
||||
# "No media found" for those, which _NO_MEDIA_ERROR_PATTERNS already keeps quiet.
|
||||
REDDIT_URL_PATTERN = (
|
||||
r"https?://(?:(?:\w+\.)?reddit\.com/(?:(?:r|user|u)/[^/\s]+/)?(?:comments|s)/[\w-]+"
|
||||
r"|(?:v\.)?redd\.it/[\w-]+)"
|
||||
)
|
||||
VIDEO_URL_PATTERN = rf"(?:{TWITTER_URL_PATTERN}|{INSTAGRAM_URL_PATTERN}|{YOUTUBE_URL_PATTERN}|{TIKTOK_URL_PATTERN}|{REDDIT_URL_PATTERN})"
|
||||
MAX_FILE_SIZE = 100 * 1024 * 1024 # 100 MB
|
||||
CLIP_DURATION = 60 # default seconds to grab around a shared ?t= timestamp
|
||||
MAX_CLIP_DURATION = 600 # ceiling for a user-supplied /clip override
|
||||
@@ -543,8 +555,15 @@ def _run_ytdlp(url: str, outpath: str, tmpdir: str,
|
||||
# Prefer the largest mp4 that already fits under 95 MB, so we avoid
|
||||
# re-encoding when a smaller variant exists (e.g. a 4K rendition
|
||||
# >100 MB alongside a 1080p ~50 MB).
|
||||
# The bv*+ba tail is required for hosts that never publish a muxed
|
||||
# rendition — Reddit serves video and audio as separate DASH/HLS
|
||||
# streams, so every `best...` term above fails and yt-dlp aborts with
|
||||
# "Requested format is not available" unless we merge them ourselves.
|
||||
# The bare bv* last resort covers silent videos (no audio to merge).
|
||||
cmd += [
|
||||
"-f", "best[ext=mp4][filesize<95M]/best[ext=mp4][filesize_approx<95M]/best[ext=mp4]/best",
|
||||
"-f",
|
||||
"best[ext=mp4][filesize<95M]/best[ext=mp4][filesize_approx<95M]/best[ext=mp4]/best"
|
||||
"/bv*[filesize<95M]+ba/bv*[filesize_approx<95M]+ba/bv*+ba/bv*",
|
||||
]
|
||||
cmd += [
|
||||
"--merge-output-format", "mp4",
|
||||
@@ -704,7 +723,8 @@ def _force_download_and_publish(url: str, token: str) -> tuple[str | None, int |
|
||||
cmd = [
|
||||
*_NICE,
|
||||
YTDLP, "--no-playlist", "--no-warnings", "--js-runtimes", JS_RUNTIME,
|
||||
"-f", "best[ext=mp4]/best", "--merge-output-format", "mp4",
|
||||
# bv*+ba tail: split-stream hosts (Reddit) have no muxed rendition.
|
||||
"-f", "best[ext=mp4]/best/bv*+ba/bv*", "--merge-output-format", "mp4",
|
||||
"--max-filesize", FORCE_MAX_FILESIZE,
|
||||
*_cookie_args(url),
|
||||
"-o", os.path.join(tokdir, "video.%(ext)s"),
|
||||
@@ -1109,7 +1129,7 @@ class ForceCommand(Command):
|
||||
|
||||
HELP_TEXT = f"""🎬 Video bot — what I can do
|
||||
|
||||
Share a video link (X/Twitter, Instagram, YouTube, TikTok) and I'll post the video back to the group.
|
||||
Share a video link (X/Twitter, Instagram, YouTube, TikTok, Reddit) and I'll post the video back to the group.
|
||||
e.g. https://x.com/user/status/123456789
|
||||
|
||||
A YouTube link with a timestamp → I post a {CLIP_DURATION}s clip starting at that moment.
|
||||
|
||||
Reference in New Issue
Block a user