End-to-end instructions for Lightroom Vision — from API key to first photo analysis.
Lightroom Vision consists of two components:
| Component | Purpose | Location |
|---|---|---|
| Vision Service | HTTP server, API integration, caching | lightroom-vision-service |
| Vision Plugin | Lightroom UI, photo processing | lightroom-vision-plugin |
Why two components? Security. The plugin has no API key — the service holds it securely.
- Go to Alibaba Cloud
- Sign up (requires email, phone verification)
- Complete identity verification
- Go to Model Studio Console
- Click Subscription Plans in left sidebar
- Select Coding Plan Lite
- Complete purchase ($3 first month, $5/month after)
Why Coding Plan?
- Compliant with Alibaba's terms (this service qualifies as a "coding tool")
- Predictable pricing (no surprise bills)
- Access to Qwen-VL, Kimi-K2.5 vision models
- Go to Coding Plan Page
- Copy your API key (format:
sk-sp-xxxxx) - Save it securely — you'll need it in Step 2
cd ~/AZ-Projects
git clone https://github.com/mizoz/lightroom-vision-service.git
cd lightroom-vision-service
npm installcp .env.example .env
nano .envEdit .env:
# Your API key from Step 1
ALIBABA_API_KEY=sk-sp-xxxxx
# Coding Plan endpoint (don't change)
ALIBABA_BASE_URL=https://coding-intl.dashscope.aliyuncs.com/apps/anthropic
# Vision model (qwen3.5-plus or kimi-k2.5)
VISION_MODEL=qwen3.5-plus
# Service port (default: 3456)
PORT=3456
# Debug logging (true/false)
DEBUG=false.env to git. It's in .gitignore by default.
npm startYou should see:
╔════════════════════════════════════════════════════════╗
║ Lightroom Vision Service ║
║ Running on http://localhost:3456 ║
║ ║
║ Endpoints: ║
║ GET /health - Health check ║
║ POST /api/v1/analyze - Single image analysis ║
║ POST /api/v1/analyze/batch - Batch analysis ║
║ GET /api/v1/stats - Usage statistics ║
║ DELETE /api/v1/cache - Clear cache ║
╚════════════════════════════════════════════════════════╝
curl http://localhost:3456/healthExpected response:
{
"status": "healthy",
"timestamp": "2026-03-02T20:30:00.000Z",
"version": "1.0.0"
}Leave this terminal running. The service must be active for the plugin to work.
cd ~/AZ-Projects
git clone https://github.com/mizoz/lightroom-vision-plugin.git- Open Lightroom Classic
- Go to File → Plug-in Manager
- Click Add button (bottom left)
- Navigate to
~/AZ-Projects/lightroom-vision-plugin/ - Select the
lightroomvisionplugin.lrpluginfolder - Click Choose
Plugin appears in "Installed Plug-ins" list.
In Plug-in Manager, with "Vision Analyzer" selected:
| Setting | Value | Why |
|---|---|---|
| Save results to | Caption | Standard field for descriptions |
| Analysis type | Alt Text | Accessibility focus |
| Skip existing | Yes | Saves API quota |
Click Done.
- Go to Library module
- Select any photo
- Library → Plug-in Extras → Generate Alt Text
- Wait 3-5 seconds
- Progress bar completes
- Open Metadata panel (right sidebar)
- Look for Caption field
- You should see AI-generated alt text
Example output:
"A person hiking on a rocky mountain trail with snow-capped peaks in the background, blue sky with scattered clouds."
# Terminal 1: Start service
cd ~/AZ-Projects/lightroom-vision-service
npm startLeave running. Then open Lightroom normally.
| Task | Steps |
|---|---|
| Single photo | Select → Library → Plug-in Extras → Generate Alt Text |
| Batch (collection) | Select all → Same menu → Wait for progress |
| Keywords only | Select → Extract Keywords |
| Full metadata | Select → Full Analysis |
When done:
# In service terminal
Ctrl+COr leave running — minimal resource usage when idle.
curl http://localhost:3456/api/v1/statsResponse:
{
"today": {
"requests": 47,
"cache_hits": 35,
"cache_hit_rate": "74.5%",
"avg_processing_time_ms": 2890
},
"cache": {
"total_cached": 312
}
}# Remove entries older than 7 days
curl -X DELETE "http://localhost:3456/api/v1/cache?olderThanDays=7"# Service
cd ~/AZ-Projects/lightroom-vision-service
git pull
npm install # if new dependencies
npm start
# Plugin
cd ~/AZ-Projects/lightroom-vision-plugin
git pull
# Restart Lightroom# Check Node version (need 18+)
node --version
# Check port availability
netstat -tlnp | grep 3456
# Check .env exists
ls -la .env- Verify service is running:
curl http://localhost:3456/health
- Check firewall isn't blocking localhost
- Restart service
- Check plugin logs:
- File → Plug-in Manager → [Vision Analyzer] → Logs
- Check service logs for API errors
- Verify API key is valid (Coding Plan, not pay-as-you-go)
| Error | Cause | Fix |
|---|---|---|
| Invalid API key | Wrong format | Verify sk-sp-xxxxx |
| Wrong endpoint | Using pay-as-you-go URL | Use Coding Plan URL |
| Quota exceeded | Monthly limit reached | Wait or upgrade plan |
| Model unavailable | Model not in your plan | Use qwen3.5-plus or kimi-k2.5 |
- Keep
.envfile secure (chmod 600) - Rotate API key periodically
- Run service on localhost only
- Monitor usage via
/api/v1/stats
- Never commit
.envto git - Never share API key
- Never expose service to network
- Never log sensitive data
| Period | Requests | Cost |
|---|---|---|
| First month | 18,000 | $3 |
| Renewal | 18,000 | $5/month |
| User Type | Photos/Month | Quota Used | Cost/Month |
|---|---|---|---|
| Light | 500 | ~5% | $5 |
| Moderate | 2,000 | ~20% | $5 |
| Heavy | 5,000 | ~50% | $5 |
| Pro | 10,000+ | 100%+ | Upgrade needed |
With caching: 80-90% reduction in API calls for similar photos (bursts, duplicates).
1. User selects photo in Lightroom
2. Plugin exports photo to temp (1024x1024 JPEG)
3. Plugin base64-encodes image
4. Plugin POSTs to localhost:3456/api/v1/analyze
5. Service hashes image, checks cache
6. If cache miss: Service calls Alibaba API
7. Service stores result in SQLite cache
8. Service returns alt text + keywords
9. Plugin saves to Lightroom metadata
10. Temp file deleted
| Component | What's Cached | Key |
|---|---|---|
| Image hash | SHA256 of base64 | image_hash |
| Result | Alt text, keywords | image_hash + prompt_type |
| Usage | Request count, duration | Timestamp |
Cache location: ~/AZ-Projects/lightroom-vision-service/data/vision-cache.db
┌────────────────────────────────────────────────┐
│ Lightroom Plugin (Untrusted) │
│ - No API key │
│ - Localhost-only communication │
└───────────────────┬────────────────────────────┘
│ (localhost:3456)
▼
┌────────────────────────────────────────────────┐
│ Vision Service (Trusted) │
│ - Holds API key (.env) │
│ - Validates all input │
│ - Sanitizes all logs │
└───────────────────┬────────────────────────────┘
│ (HTTPS)
▼
┌────────────────────────────────────────────────┐
│ Alibaba Cloud API (External) │
│ - Coding Plan endpoint │
│ - Rate limited │
│ - Quota tracked │
└────────────────────────────────────────────────┘
- ✅ Process your first batch of photos
- ✅ Configure your preferred metadata fields
- ✅ Set up monitoring (check stats weekly)
- ✅ Share feedback or issues on GitHub
- Issues: Vision Service or Plugin
- Docs: README files in each repo
- Alibaba Docs: Model Studio
MIT — Both components are open source.