Extract recipes from social media videos (TikTok, YouTube, Instagram, etc.) and automatically import them into your self-hosted recipe manager.
Pick-a-Recipe is a Python application that:
- Downloads videos from TikTok, YouTube, Instagram, and other platforms using
yt-dlp - Transcribes audio using Whisper AI (via
faster-whisper) - Extracts on-screen text (ingredients, instructions) using vision-capable LLMs
- Generates structured recipes using AI (OpenAI GPT or Google Gemini)
- Uploads to recipe managers - supports Tandoor and Mealie
- ๐ฅ Multi-platform video support (TikTok, YouTube, Instagram, etc.)
- ๐๏ธ Audio transcription with language detection
- ๐๏ธ Visual text extraction from video frames
- ๐ค AI-powered recipe generation with structured ingredients
- ๐ฝ๏ธ Automatic nutrition and serving size estimation
- ๐ผ๏ธ Dish image extraction with manual selection option
- ๐ Web UI with real-time progress updates
- ๐ User authentication and settings management
- ๐ณ Docker support for easy deployment
- ๐ฑ PWA Support - Install as app on mobile, share URLs directly from Android/iOS
- Python 3.11+
- FFmpeg (for video/audio processing)
- API key for OpenAI or Google Gemini
- Self-hosted Tandoor or Mealie instance (optional)
Option 1: Pull from Docker Hub (Easiest)
docker run -d \
--name pick-a-recipe \
-p 5006:5006 \
-e FLASK_SECRET_KEY="your-secure-secret-key" \
-v pick-a-recipe-data:/app/data \
pickeld/pick-a-recipe:latestAccess the web UI at http://localhost:5006
Option 2: Using Docker Compose
Create a docker-compose.yml file:
version: "3.8"
services:
pick-a-recipe:
image: pickeld/pick-a-recipe:latest
container_name: pick-a-recipe
restart: unless-stopped
ports:
- "5006:5006"
environment:
- FLASK_SECRET_KEY=your-secure-secret-key
volumes:
- pick-a-recipe-data:/app/data
volumes:
pick-a-recipe-data:Then run:
docker-compose up -dAccess the web UI at http://localhost:5006
-
Clone the repository:
git clone https://github.com/pickeld/pick-a-recipe.git cd pick-a-recipe -
Install system dependencies:
# macOS brew install ffmpeg # Ubuntu/Debian sudo apt-get install ffmpeg
-
Create a virtual environment and install Python dependencies:
python3 -m venv venv source venv/bin/activate pip install -r requirements.txt -
Run the application:
python ui/app.py
-
Access the web UI at
http://localhost:5006
All configuration is managed through the web UI settings page (/settings). On first run, use the default credentials:
- Username:
admin - Password:
admin123
โ ๏ธ Important: Change the default password immediately after first login!
| Setting | Description |
|---|---|
| LLM Provider | Choose between OpenAI or Google Gemini |
| OpenAI API Key | Your OpenAI API key (required if using OpenAI) |
| OpenAI Model | Model to use (default: gpt-5-mini-2025-08-07) |
| Gemini API Key | Your Google Gemini API key (required if using Gemini) |
| Gemini Model | Model to use (default: gemini-2.5-flash) |
| Recipe Language | Target language for recipe output (e.g., hebrew, english) |
| Target Language Code | ISO language code for transcription (e.g., he, en) |
| Whisper Model | Whisper model size (tiny, small, medium, large) |
| Output Target | Recipe manager: tandoor or mealie |
| Tandoor Host | URL of your Tandoor instance |
| Tandoor API Key | API token from Tandoor |
| Mealie Host | URL of your Mealie instance |
| Mealie API Key | API token from Mealie |
| Confirm Before Upload | Show recipe preview before uploading |
- Navigate to
http://localhost:5006 - Log in with your credentials
- Paste a video URL (TikTok, YouTube, Instagram, etc.)
- Click "Extract Recipe"
- Watch the real-time progress as the video is processed
- If "Confirm Before Upload" is enabled, review and optionally edit the recipe
- The recipe is automatically uploaded to your configured recipe manager
Pick-a-Recipe supports PWA (Progressive Web App) installation, allowing you to share video links directly from your phone:
- Open
https://your-server:5006in Chrome - Tap the menu (โฎ) โ "Add to Home screen"
- Now when sharing any video link, choose "Pick-a-Recipe" from the share sheet
- Open
https://your-server:5006in Safari - Tap the Share button โ "Add to Home Screen"
- Open the app from your home screen
- Share video links from TikTok/Instagram/YouTube using the Share button โ "Pick-a-Recipe"
Note: PWA features require HTTPS in production. For local testing,
localhostworks without HTTPS.
For testing or batch processing, you can use the CLI:
# Basic usage
python main.py "https://www.tiktok.com/@user/video/1234567890"
# Skip upload (just generate recipe JSON)
python main.py --no-upload "https://www.youtube.com/watch?v=VIDEO_ID"pick-a-recipe/
โโโ main.py # CLI entry point
โโโ chef.py # AI recipe generation
โโโ config.py # Configuration management
โโโ video_downloader.py # Video downloading (yt-dlp)
โโโ transcriber.py # Audio transcription (Whisper)
โโโ image_extractor.py # Dish image extraction
โโโ mealie.py # Mealie API integration
โโโ tandoor.py # Tandoor API integration
โโโ recipe_exporter.py # Recipe export utilities
โโโ helpers.py # Utility functions and prompts
โโโ llm_providers/ # LLM provider implementations
โ โโโ base.py
โ โโโ openai.py
โ โโโ gemini.py
โโโ ui/ # Flask web UI
โ โโโ app.py # Flask application
โ โโโ database.py # SQLite database management
โ โโโ templates/ # HTML templates
โ โโโ static/ # CSS and JavaScript
โโโ Dockerfile
โโโ docker-compose.yml
โโโ docker-compose.srv2.yml # srv2 reference (see portainer/ for production)
โโโ build-and-push.sh # Publish pickeld/pick-a-recipe to Docker Hub
โโโ portainer/
โ โโโ stack.yml # Portainer / srv2 production stack
โ โโโ stack.env # Stack env template (copy to stack.env.local)
โโโ scripts/
โ โโโ portainer-migrate.sh # srv2 deploy: pull image + restart stack
โ โโโ portainer-deploy.sh # Deploy via Portainer API
โโโ requirements.txt
The official image is available on Docker Hub: pickeld/pick-a-recipe
# Pull the latest image
docker pull pickeld/pick-a-recipe:latest
# Or pull a specific version
docker pull pickeld/pick-a-recipe:v1.0.0| Variable | Description | Default |
|---|---|---|
HOST |
Host to bind to | 0.0.0.0 |
PORT |
Port to listen on | 5006 |
FLASK_SECRET_KEY |
Secret key for session cookies | Auto-generated |
FLASK_DEBUG |
Enable debug mode | false |
MAX_CONCURRENT_JOBS |
Parallel extraction workers (1โ16) | 3 (or Settings value) |
GOOGLE_CLIENT_ID |
Google OAuth client ID (enables SSO) | โ |
GOOGLE_CLIENT_SECRET |
Google OAuth client secret | โ |
SESSION_COOKIE_SECURE |
Set secure cookie flag (use with HTTPS) | false |
version: "3.8"
services:
pick-a-recipe:
image: pickeld/pick-a-recipe:latest
container_name: pick-a-recipe
restart: unless-stopped
ports:
- "5006:5006"
environment:
- HOST=0.0.0.0
- PORT=5006
- FLASK_SECRET_KEY=your-secure-secret-key
volumes:
- pick-a-recipe-data:/app/data
volumes:
pick-a-recipe-data:Multi-arch image (linux/amd64, linux/arm64):
docker logout && docker login -u pickeld # or pickeld@gmail.com
./build-and-push.sh latestPublished as pickeld/pick-a-recipe on Docker Hub.
Production on srv2 is managed by Portainer. Add credentials to portainer/stack.env.local, then deploy:
cd /opt/pick-a-recipe
cp portainer/stack.env portainer/stack.env.local
# Edit stack.env.local: FLASK_SECRET_KEY, PORTAINER_URL, PORTAINER_USER, PORTAINER_PASSWORD
./scripts/portainer-migrate.shOr deploy/update directly:
./scripts/portainer-deploy.sh --pull --force-recreateImportant: Do not use
docker compose updirectly โ Portainer will show "created outside of Portainer" and limit control. Always deploy via the scripts above or the Portainer UI.
Note: Existing srv2 installs may still use the legacy Docker volume
social_recipe_social-recipesfor data; the stack preserves it automatically.
If you prefer to build the image yourself:
git clone https://github.com/pickeld/pick-a-recipe.git
cd pick-a-recipe
docker build -t pick-a-recipe .
docker run -p 5006:5006 -e FLASK_SECRET_KEY="your-secret" pick-a-recipePick-a-Recipe uses yt-dlp for video downloading, which supports:
- TikTok
- YouTube
- Instagram Reels
- Facebook Videos
- Twitter/X Videos
- And many more
Instagram frequently blocks automated downloads. Pick-a-Recipe installs yt-dlp[curl-cffi] for browser impersonation, which is required for most public reels.
If you still see "Instagram sent an empty media response":
- Update to the latest Docker image or reinstall:
pip install "yt-dlp[curl-cffi]" - Confirm the reel opens in a private/incognito browser window (not logged in). If it does not, the post is private โ upload a
cookies.txtin Settings while logged into Instagram. - Upload cookies in Settings โ Video Downloads (export from your browser while logged into
instagram.com).
This is an upstream Instagram/yt-dlp limitation, not a bug in the recipe extraction itself. See yt-dlp issue #17074 for background.
MIT License - see LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.