Skip to content

About

Automatically populate your YouTube channel with highly-rated Reddit videos.

Topics

Resources

Contributing

Security policy

Stars

6 stars

Watchers

1 watching

Forks

Repository files navigation

Reddit2Tube

CI

Reddit2Tube is a Python automation tool that finds highly-rated videos in a public subreddit, downloads them with yt-dlp, renders YouTube metadata from templates, and optionally uploads the videos through the YouTube Data API.

The project is designed as a small, testable automation pipeline rather than a hosted service. It is useful for learning and personal workflows, while still demonstrating configuration validation, dependency injection, SQLite idempotency, retries, logging, and offline testing.

Workflow

Reddit API
  -> filter video submissions
  -> render templates
  -> SQLite duplicate check
  -> yt-dlp download
  -> record pending upload (SQLite)
  -> YouTube upload (optional)
       -> success: record the upload
       -> failure: keep the pending row for --retry-failed

In upload mode the application records a submission in two stages. It writes a pending row before uploading and marks the submission as uploaded only once YouTube returns an upload ID. A failed or interrupted upload keeps its pending row, so it can be retried later with --retry-failed regardless of whether the submission is still in the listing window.

Download-only runs neither write pending rows nor mark submissions as uploaded. Re-uploading a download-only video later therefore still depends on the submission appearing in the top submissions again.

Requirements

  • Python 3.10 or newer
  • Reddit API credentials
  • YouTube Data API v3 credentials for upload mode
  • Permission to download and republish the selected content

Reddit2Tube does not bypass access controls. Respect Reddit, YouTube, and content-owner terms, copyright, rate limits, and community rules.

Quick start

Install uv using the instructions at https://docs.astral.sh/uv/getting-started/installation/ before running the commands below.

git clone https://github.com/roperi/Reddit2Tube.git
cd Reddit2Tube
make install
make install-hooks
cp .env.example .env
mkdir -p templates
cp examples/templates/* templates/

Edit .env with your Reddit credentials. The application creates the SQLite database, tables, log directory, and download directory automatically.

Run the test suite and inspect the CLI:

make check
python -m reddit2tube --help

Configuration

.env.example is the complete configuration reference. The most important values are:

Variable Purpose
DATABASE_FILE SQLite file used to prevent duplicate processing
DOWNLOAD_DIR Directory for downloaded media
REDDIT_CLIENT_ID / REDDIT_CLIENT_SECRET Reddit application credentials
REDDIT_USERNAME / REDDIT_PASSWORD Reddit account used by PRAW
REDDIT_USER_AGENT Descriptive Reddit API user agent
CLIENT_SECRETS_FILE Google OAuth desktop-client JSON file
SCOPES Comma-separated YouTube OAuth scopes

For Reddit anti-bot challenges, configure exactly one of REDDIT_COOKIES_FROM_BROWSER or REDDIT_COOKIES_FILE. Cookie contents are never logged. Keep .env, config/, and cookie files private.

Reddit-hosted videos are downloaded from the direct v.redd.it media URL returned by the Reddit API, so yt-dlp does not call Reddit's JSON metadata endpoint. This avoids the Your IP address is unable to access the Reddit API error that can occur even when browser cookies are valid. Cookies are only necessary when a submission has no direct media URL.

If yt-dlp reports Account authentication is required, log into Reddit in Firefox on the machine running Reddit2Tube and add this to .env:

REDDIT_COOKIES_FROM_BROWSER=firefox

Use chrome instead if that is your logged-in browser. To select a specific profile, use firefox:/absolute/path/to/profile. Chromium users should use chromium; for the Ubuntu Snap installation, use chromium:~/snap/chromium/common/chromium/Default. For a server without a local browser, export the logged-in Reddit cookies in Mozilla/Netscape format and set REDDIT_COOKIES_FILE=/absolute/path/to/reddit-cookies.txt instead. Set only one cookie option, then rerun your original command. If authentication still fails, refresh the browser login or export fresh cookies.

The REDDIT_USERNAME and REDDIT_PASSWORD settings authenticate PRAW's API requests; yt-dlp uses a separate session and needs these browser cookies. See the yt-dlp cookie FAQ for export instructions.

Reddit credentials

Create a script application at https://www.reddit.com/prefs/apps/ and copy its client ID and secret into .env. Use a descriptive user agent such as:

REDDIT_USER_AGENT=Reddit2Tube/1.0 by your-reddit-username

YouTube credentials

In Google Cloud:

  1. Create or select a project.
  2. Enable YouTube Data API v3.
  3. Create an OAuth client ID for a desktop application.
  4. Download the JSON file to config/client_secret.json.
  5. Add the YouTube upload scope to the OAuth consent configuration.

The first upload run opens a browser for authorization. The resulting token is stored under config/ and is ignored by Git.

Templates

Copy the examples into templates/ and customize them:

mkdir -p templates
cp examples/templates/* templates/

Both templates use Python str.format fields. Available fields include: title, id, author, selftext, url, score, num_comments, created_utc, subreddit, is_self, link_flair_text, and locked.

Deleted Reddit accounts render as [deleted]. Titles longer than 70 characters are shortened before template rendering.

Usage

The original script entrypoint remains supported:

uv run --locked python Reddit2Tube.py \
  --subreddit_name cats \
  --reddit_num_submissions 1 \
  --time_filter day \
  --privacy_status private

This runs the original script entrypoint inside the uv-managed project environment.

The installed command and module entrypoints are equivalent:

uv run --locked reddit2tube --subreddit_name cats --reddit_num_submissions 1
uv run --locked python -m reddit2tube --subreddit_name cats --just_download

Useful options:

Option Default Description
--subreddit_name — Subreddit to query
--reddit_num_submissions 2 Number of top submissions to inspect
--time_filter day Reddit period, such as day or week
--category 22 YouTube category ID
--privacy_status private private, unlisted, or public
--made_for_kids off Set YouTube’s self-declared kids flag
--just_download off Skip YouTube authentication and upload
--verbose off Enable debug logging
--troubleshooting-upload off Private, long-form-only uploads with a six-attempt UTC-day cap
--retry-failed off Re-upload videos recorded as pending after a failure

The troubleshooting upload profile is temporary and opt-in. It validates and fully decodes each candidate with ffprobe/ffmpeg, skips likely Shorts, and records upload-attempt reservations in SQLite before starting an upload. It requires both ffprobe and ffmpeg to be available on PATH.

The process exits non-zero for invalid configuration or failed submissions. Independent submissions continue to be attempted, and the final log includes a run summary.

Resuming failed uploads

Uploads that fail are recorded in the pending_uploads table in the SQLite database. Retry them with:

uv run --locked reddit2tube --retry-failed

A retry reuses the recorded local file when it still exists, otherwise it downloads the video again from the recorded URL. Pending rows written by older versions store a Reddit permalink; those are resolved to a direct v.redd.it media URL through the Reddit API when credentials are available. Because the source URL and the rendered title and description are stored, retrying does not need the submission to still be in the listing window. Retries use the current command-line options for category, privacy status, and made-for-kids.

Add --subreddit_name to retry failures first and then process new submissions in the same run:

uv run --locked reddit2tube --retry-failed --subreddit_name cats --time_filter day

Retry mode needs YouTube credentials, plus Reddit cookies only when a video has to be downloaded again. It cannot be combined with --just_download. When --troubleshooting-upload is also passed, retries respect the same six-attempt UTC-day cap.

Development

Install the project with its development tools:

make install

make install uses uv to create or update the project environment from the committed uv.lock file. The project environment lives in .venv/; activate it manually only when needed, or use uv run for individual commands.

Run the complete local quality gate:

make check

The repository also provides make format, make lint, make test, make coverage, and make hooks-check for individual checks. After make install-hooks, Ruff runs before commits and the complete offline test suite runs before pushes.

Tests are intentionally offline. Reddit, yt-dlp, and YouTube are isolated behind injectable boundaries and replaced with fakes in workflow tests. CI runs the quality gate on Python 3.10 through 3.13.

Operations

For scheduled personal automation, call the installed command from cron or a systemd timer with an absolute working directory and a private environment file. Keep the process single-instance if multiple schedules could overlap.

Example cron entry:

0 5 * * 1 cd /path/to/Reddit2Tube && uv run --locked reddit2tube --subreddit_name cats --reddit_num_submissions 3 --time_filter week --privacy_status private

Start with private or unlisted uploads while validating templates, quota, and content policy. YouTube upload quota is finite and can make a failed retry expensive.

A failed upload is recorded rather than lost when the listing moves on. To recover failures automatically, schedule a follow-up retry:

30 6 * * * cd /path/to/Reddit2Tube && uv run --locked reddit2tube --retry-failed

Security and repository hygiene

Never commit .env, OAuth client secrets, OAuth tokens, Reddit cookies, databases, downloaded media, or logs. The repository ignores these runtime artifacts and includes SECURITY.md with handling guidance.

Contributions should follow CONTRIBUTING.md. See the CHANGELOG for project evolution. The project is released under the MIT license; see LICENSE.

About

Automatically populate your YouTube channel with highly-rated Reddit videos.

Topics

Resources

Contributing

Security policy

Stars

6 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages