A Python application that reads images from a WebDAV server or local folder, processes them with OpenAI-compatible vision models, and saves the results to another WebDAV folder.
This has been developed with help OpenCodeCI
The Webdav support is intended to be used with Nextcloud and the Nextcloud Recipe Application.
This has been tested with the model qwen3-vl-4b-instruct running in a LocalAI instance.
- WebDAV Integration: Connect to source and destination WebDAV servers
- AI Vision Processing: Uses OpenAI GPT-4 Vision or compatible models to analyze images
- Recipe Extraction: Optimized prompts for extracting recipe information from food images
- Batch Processing: Process multiple images in a directory
- Error Handling: Robust retry logic and error recovery
- Flexible Configuration: Environment-based configuration management
- Multiple Output Formats: Saves results as both JSON and text files
- Self-hosted AI: Can be used with self-hosted AI platform like LocalAI or Open WebUI
- Clone the repository:
git clone <repository-url>
cd ScanToCookbook- Install dependencies:
pip install -r requirements.txt- Copy and configure environment variables:
cp .env.example .envEdit the .env file with your configuration:
WEBDAV_SOURCE_HOST=https://your-source-server.com/webdav
WEBDAV_SOURCE_USERNAME=your-username
WEBDAV_SOURCE_PASSWORD=your-passwordWEBDAV_DEST_HOST=https://your-destination-server.com/webdav
WEBDAV_DEST_USERNAME=your-username
WEBDAV_DEST_PASSWORD=your-passwordOPENAI_API_KEY=your-openai-api-key
OPENAI_BASE_URL=https://api.openai.com/v1 # or custom endpoint
LLM_MODEL=gpt-4-vision-preview
VISION_PROMPT=Analyze this image and extract recipe information...MAX_IMAGE_SIZE=10485760 # 10MB
SUPPORTED_FORMATS=jpg,jpeg,png
TEMP_DIR=/tmp/scan_to_cookbook
MAX_RETRIES=3
RETRY_DELAY=2Process all images in a directory:
python src/main.py --source-dir /recipes --dest-dir /processedpython src/main.py --single "/recipes/pasta.jpg" --dest-dir /processedpython src/main.py --testpython src/main.py --source-dir /recipes --dest-dir /processed --verboseSingle File:
python src/main.py --local-test --local-input ./test_image.jpgDirectory with Progress Bar:
python src/main.py --local-test --local-input ./recipes --local-output ./processed --progressCustom Configuration:
# Using .env file
python src/main.py --local-test --local-config ./my_local.env --local-input ./images
# Using YAML file
python src/main.py --local-test --local-config ./local.yaml --local-input ./photosDefault Local Configuration:
# Uses local.env or local.yaml (or environment variables)
python src/main.py --local-test --local-input ./test_images--source-dir: Source WebDAV directory (default: "/")--dest-dir: Destination WebDAV directory (default: "/processed")--test: Test connections only--single: Process a single image file--verbose, -v: Enable verbose logging
--local-test: Enable local file processing mode--local-input: Local input file or directory path--local-output: Local output directory (default: "./output")--local-config: Local config file (.env or .yaml)--progress: Show progress bar for batch operations (default: True)--help: Show help message
The application automatically detects the mode:
- WebDAV Mode: Default (no
--local-testflag) - Local Mode: When
--local-testflag is used
For each processed image, the application creates:
-
JSON Analysis:
{filename}_analysis.json- Contains structured analysis results
- Includes metadata (timestamp, model, prompt)
- Machine-readable format
-
Text Recipe:
recipe-name/recipe.json- Json format using schema.org recipe standard
The application logs to:
- Console output
logs/scan_to_cookbook.logfile
Log levels:
- INFO: General operation information
- WARNING: Non-critical issues
- ERROR: Critical errors
- DEBUG: Detailed debugging information (use
--verbose)
- Connection Failures: Automatic retry with configurable delays
- Invalid Images: Skips corrupted or unsupported files
- Large Images: Automatically resizes images over the size limit
- API Errors: Handles rate limits and API failures gracefully
- JPEG (.jpg, .jpeg)
- PNG (.png)
- GIF (.gif)
- WebP (.webp)
- BMP (.bmp)
- Upload recipe images to
/incomingon your WebDAV server - Run the processor:
python src/main.py --source-dir /incoming --dest-dir /recipes- Results appear in
/recipeswith:pasta_analysis.json- Structured datapasta_recipe.txt- Human-readable recipe
Set a custom vision prompt in .env:
VISION_PROMPT=Extract detailed cooking instructions, ingredients with measurements, cooking time, temperature, and serving size from this recipe image.Edit the .env file with your configuration:
Configure the source folder of the images to scan
WEBDAV_SOURCE_HOST=https://<your-nextcloud-server>/remote.php/dav/files/<username>/Bilder
WEBDAV_SOURCE_USERNAME=your-username
WEBDAV_SOURCE_PASSWORD=your-app-apsswordWEBDAV_DEST_HOST=https://<your-nextcloud-server>/remote.php/dav/files/<username>/Rezepte
WEBDAV_DEST_USERNAME=your-username
WEBDAV_DEST_PASSWORD=your-app-passwordAlso you can use the local test mode and copy or upload the data manually into to the recipe folder.
Edit the .env file for WebDAV settings:
# WebDAV Source
WEBDAV_SOURCE_HOST=https://your-source-server.com/webdav
WEBDAV_SOURCE_USERNAME=your-username
WEBDAV_SOURCE_PASSWORD=your-password
# WebDAV Destination
WEBDAV_DEST_HOST=https://your-destination-server.com/webdav
WEBDAV_DEST_USERNAME=your-username
WEBDAV_DEST_PASSWORD=your-password
# OpenAI Configuration
OPENAI_API_KEY=your-openai-api-key
LLM_MODEL=gpt-4-vision-previewFor local testing, copy and configure:
# Copy template
cp local.env.example local.env
# Edit with your settings
nano local.envOr use YAML format:
cp local.yaml.example local.yaml
# Edit with your settings
nano local.yamlRequired Local Settings:
OPENAI_API_KEY: Your OpenAI API keyLOCAL_INPUT_DIR: Directory containing test imagesLOCAL_OUTPUT_DIR: Directory for processed results
Optional Local Settings:
MAX_IMAGE_SIZE: Maximum image size before resizing (default: 10MB)SUPPORTED_FORMATS: Image formats to process (default: jpg,jpeg,png)LOG_LEVEL: Logging level (default: INFO)
-
WebDAV Connection Failed
- Verify server URL and credentials
- Check network connectivity
- Ensure WebDAV is enabled on server
-
OpenAI API Error
- Verify API key is valid
- Check API quota and rate limits
- Ensure model supports vision (gpt-4-vision-preview)
-
Local Mode Issues
- Verify OpenAI API key is set in local config
- Check input directory exists and contains images
- Ensure output directory is writable
-
Image Processing Errors
- Check image file format is supported
- Verify image isn't corrupted
- Check file size limits
Run with verbose logging to diagnose issues:
# WebDAV mode
python src/main.py --test --verbose
# Local mode
python src/main.py --local-test --local-input ./test --verboseScanToCookbook/
├── src/
│ ├── __init__.py
│ ├── config.py # WebDAV configuration management
│ ├── local_config.py # Local configuration management
│ ├── webdav_handler.py # WebDAV operations
│ ├── local_processor.py # Local file processing
│ ├── llm_processor.py # OpenAI API client
│ ├── image_utils.py # Image processing utilities
│ ├── file_utils.py # File handling utils
│ └── main.py # Main application logic
├── logs/ # Log files
├── temp/ # Temporary files (WebDAV mode only)
├── output/ # Local output directory
├── requirements.txt
├── .env.example # WebDAV configuration template
├── local.env.example # Local configuration template (.env)
├── local.yaml.example # Local configuration template (YAML)
└── README.md
webdavclient3: WebDAV client libraryopenai: OpenAI API clientpython-dotenv: Environment variable managementPyYAML: YAML configuration file supportPillow: Image processingrequests: HTTP requeststqdm: Progress bar for batch operations (included with OpenAI)
- Install LocalAI, see LocalAI Docker Installation
- Install the model qwen3-vl-4b-instruct fromthe model gallery of your local ai installation.
- Use your local ai platform (e.g http://localhost:8080/v1) as OpenAI url.
- Use qwen3-vl-4b-instruct as model nale in your configuration.
Apache License