📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -0,0 +1,786 @@
|
||||
---
|
||||
name: 2slides-ppt-generator
|
||||
description: "AI-powered presentation generation via the 2slides API — create slides from text, match a reference image style, summarize documents into decks, add AI voice narration, and export pages/audio. Use for any \"make slides\", \"create a deck\", or \"slides from this document\" request."
|
||||
category: api-integration
|
||||
risk: safe
|
||||
source: community
|
||||
source_repo: 2slides/slides-generation-2slides-skills
|
||||
source_type: community
|
||||
date_added: "2026-06-05"
|
||||
author: 2slides
|
||||
tags: [presentations, slides, powerpoint, ai, api-integration, pdf, narration, document-summarization]
|
||||
tools: [claude, cursor, gemini, codex, antigravity]
|
||||
---
|
||||
|
||||
# 2slides Presentation Generation
|
||||
|
||||
## Overview
|
||||
|
||||
Generate professional presentations using the 2slides AI API. The skill supports content-based generation (theme-driven Fast PPT), style matching from a reference image, custom PDF design, document summarization, AI voice narration, and exporting pages/audio. It returns both an interactive slide URL and a downloadable PDF.
|
||||
|
||||
This skill is adapted from the official 2slides skill repository ([`2slides/slides-generation-2slides-skills`](https://github.com/2slides/slides-generation-2slides-skills)). It calls the hosted 2slides API and requires the user's own API key and credits.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
- Use when the user asks to "create a presentation", "make slides", or "generate a deck" from text or an outline.
|
||||
- Use when the user wants slides that match the style of a reference image ("create slides like this image").
|
||||
- Use when the user wants custom-designed PDF slides without a reference image.
|
||||
- Use when the user uploads a document and asks to "create slides from this document".
|
||||
- Use when the user wants to add AI voice narration to generated slides, or export slides as PNG images and narration as WAV audio.
|
||||
- Use when the user asks "what themes are available?" or wants to browse/select a theme.
|
||||
|
||||
## Setup Requirements
|
||||
|
||||
Users must have a 2slides API key and credits:
|
||||
|
||||
1. **Get API Key:** Visit https://2slides.com/api to create an account and API key
|
||||
- New users receive **500 free credits** (~50 Fast PPT pages)
|
||||
2. **Purchase Credits (Optional):** Visit https://2slides.com/pricing to buy additional credits
|
||||
- Pay-as-you-go, no subscriptions
|
||||
- Credits never expire
|
||||
- Up to 20% off on larger packages
|
||||
3. **Set API Key:** Store the key in environment variable: `SLIDES_2SLIDES_API_KEY`
|
||||
|
||||
```bash
|
||||
export SLIDES_2SLIDES_API_KEY="your_api_key_here"
|
||||
```
|
||||
|
||||
**Credit Costs:**
|
||||
- Fast PPT: 10 credits/page
|
||||
- Nano Banana 1K/2K: 100 credits/page
|
||||
- Nano Banana 4K: 200 credits/page
|
||||
- Voice Narration: 210 credits/page
|
||||
- Download Export: FREE
|
||||
|
||||
See [references/pricing.md](references/pricing.md) for detailed pricing information.
|
||||
|
||||
## Workflow Decision Tree
|
||||
|
||||
Choose the appropriate approach based on the user's request:
|
||||
|
||||
```
|
||||
User Request
|
||||
│
|
||||
├─ "Create slides from this content/text"
|
||||
│ └─> Use Content-Based Generation (Section 1)
|
||||
│
|
||||
├─ "Create slides like this image"
|
||||
│ └─> Use Reference Image Generation (Section 2)
|
||||
│
|
||||
├─ "Create custom designed slides" or "Create PDF slides"
|
||||
│ └─> Use Custom PDF Generation (Section 3)
|
||||
│
|
||||
├─ "Create slides from this document"
|
||||
│ └─> Use Document Summarization (Section 4)
|
||||
│
|
||||
├─ "Add voice narration" or "Generate audio for slides"
|
||||
│ └─> Use Voice Narration (Section 5)
|
||||
│
|
||||
├─ "Download slides as images" or "Export slides and voices"
|
||||
│ └─> Use Download Export (Section 6)
|
||||
│
|
||||
└─ "Search for themes" or "What themes are available?"
|
||||
└─> Use Theme Search (Section 7)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Content-Based Generation
|
||||
|
||||
Generate slides from user-provided text content.
|
||||
|
||||
### When to Use
|
||||
- User provides content directly in their message
|
||||
- User says "create a presentation about X"
|
||||
- User provides structured outline or bullet points
|
||||
|
||||
### Workflow
|
||||
|
||||
**Step 1: Prepare Content**
|
||||
|
||||
Structure the content clearly for best results:
|
||||
|
||||
```
|
||||
Title: [Main Topic]
|
||||
|
||||
Section 1: [Subtopic]
|
||||
- Key point 1
|
||||
- Key point 2
|
||||
- Key point 3
|
||||
|
||||
Section 2: [Subtopic]
|
||||
- Key point 1
|
||||
- Key point 2
|
||||
```
|
||||
|
||||
**Step 2: Choose Theme (Required)**
|
||||
|
||||
Search for an appropriate theme (themeId is required):
|
||||
|
||||
```bash
|
||||
python scripts/search_themes.py --query "business"
|
||||
python scripts/search_themes.py --query "professional"
|
||||
python scripts/search_themes.py --query "creative"
|
||||
```
|
||||
|
||||
Pick a theme ID from the results.
|
||||
|
||||
**Step 3: Generate Slides**
|
||||
|
||||
Use the `generate_slides.py` script with the theme ID:
|
||||
|
||||
```bash
|
||||
# Basic generation (theme ID required)
|
||||
python scripts/generate_slides.py --content "Your content here" --theme-id "theme123"
|
||||
|
||||
# In different language
|
||||
python scripts/generate_slides.py --content "Your content" --theme-id "theme123" --language "Spanish"
|
||||
|
||||
# Async mode for longer presentations
|
||||
python scripts/generate_slides.py --content "Your content" --theme-id "theme123" --mode async
|
||||
```
|
||||
|
||||
**Step 4: Handle Results**
|
||||
|
||||
**Sync mode response:**
|
||||
```json
|
||||
{
|
||||
"slideUrl": "https://2slides.com/slides/abc123",
|
||||
"pdfUrl": "https://2slides.com/slides/abc123/download",
|
||||
"status": "completed"
|
||||
}
|
||||
```
|
||||
|
||||
Provide both URLs to the user:
|
||||
- `slideUrl`: Interactive online slides
|
||||
- `pdfUrl`: Downloadable PDF version
|
||||
|
||||
**Async mode response:**
|
||||
```json
|
||||
{
|
||||
"jobId": "job123",
|
||||
"status": "pending"
|
||||
}
|
||||
```
|
||||
|
||||
Poll for results:
|
||||
```bash
|
||||
python scripts/get_job_status.py --job-id "job123"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Reference Image Generation
|
||||
|
||||
Generate slides that match the style of a reference image.
|
||||
|
||||
### When to Use
|
||||
- User provides an image URL and says "create slides like this"
|
||||
- User wants to match existing brand/design style
|
||||
- User has a template image they want to emulate
|
||||
|
||||
### Workflow
|
||||
|
||||
**Step 1: Verify Image URL**
|
||||
|
||||
Ensure the reference image is:
|
||||
- Publicly accessible URL
|
||||
- Valid image format (PNG, JPG, etc.)
|
||||
- Represents the desired slide style
|
||||
|
||||
**Step 2: Generate Slides**
|
||||
|
||||
Use the `generate_slides.py` script with `--reference-image`:
|
||||
|
||||
```bash
|
||||
python scripts/generate_slides.py \
|
||||
--content "Your presentation content" \
|
||||
--reference-image "https://example.com/template.jpg" \
|
||||
--language "Auto"
|
||||
```
|
||||
|
||||
**Optional parameters (all values from [2slides API](https://2slides.com/api.md)):**
|
||||
```bash
|
||||
--language LANG # Auto, English, Spanish, Arabic, Portuguese, Indonesian,
|
||||
# Japanese, Russian, Hindi, French, German, Greek, Vietnamese,
|
||||
# Turkish, Polish, Italian, Korean, Simplified Chinese,
|
||||
# Traditional Chinese, Thai (default: Auto)
|
||||
--mode sync|async # default: sync for theme, async for reference-image
|
||||
--aspect-ratio RATIO # 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9 (default: 16:9)
|
||||
--resolution 1K|2K|4K # default: 2K
|
||||
--page N # 0=auto, 1-100 (default: 1)
|
||||
--content-detail concise|standard # default: standard
|
||||
```
|
||||
|
||||
**Note:** This uses Nano Banana Pro mode with credit costs:
|
||||
- 1K/2K: 100 credits per page
|
||||
- 4K: 200 credits per page
|
||||
|
||||
**Step 3: Handle Results**
|
||||
|
||||
This mode always runs synchronously and returns:
|
||||
```json
|
||||
{
|
||||
"slideUrl": "https://2slides.com/workspace?jobId=...",
|
||||
"pdfUrl": "https://...pdf...",
|
||||
"status": "completed",
|
||||
"message": "Successfully generated N slides",
|
||||
"slidePageCount": N
|
||||
}
|
||||
```
|
||||
|
||||
Provide both URLs to the user:
|
||||
- `slideUrl`: View slides in 2slides workspace
|
||||
- `pdfUrl`: Direct PDF download (expires in 1 hour)
|
||||
|
||||
**Processing time:** ~30 seconds per page (30-60 seconds typical for 1-2 pages)
|
||||
|
||||
---
|
||||
|
||||
## 3. Custom PDF Generation
|
||||
|
||||
Generate custom-designed slides from text without needing a reference image.
|
||||
|
||||
### When to Use
|
||||
- User wants custom design without providing a reference image
|
||||
- User requests "create PDF slides"
|
||||
- User wants to specify design characteristics
|
||||
- Alternative to theme-based generation with more design flexibility
|
||||
|
||||
### Workflow
|
||||
|
||||
**Step 1: Prepare Content**
|
||||
|
||||
Structure the content clearly:
|
||||
|
||||
```
|
||||
Title: [Main Topic]
|
||||
|
||||
Section 1: [Subtopic]
|
||||
- Key point 1
|
||||
- Key point 2
|
||||
|
||||
Section 2: [Subtopic]
|
||||
- Key point 1
|
||||
- Key point 2
|
||||
```
|
||||
|
||||
**Step 2: Generate Slides**
|
||||
|
||||
Use the `create_pdf_slides.py` script:
|
||||
|
||||
```bash
|
||||
# Basic generation
|
||||
python scripts/create_pdf_slides.py --content "Your content here"
|
||||
|
||||
# With design style (API: designStyle)
|
||||
python scripts/create_pdf_slides.py \
|
||||
--content "Sales Report Q4 2025" \
|
||||
--design-style "modern minimalist, blue color scheme"
|
||||
|
||||
# High resolution with auto page detection
|
||||
python scripts/create_pdf_slides.py \
|
||||
--content "Marketing Plan" \
|
||||
--resolution 4K \
|
||||
--page 0 \
|
||||
--content-detail standard
|
||||
```
|
||||
|
||||
**Optional parameters:**
|
||||
```bash
|
||||
--design-style "text" # Design instructions (API: designStyle)
|
||||
--language LANG # Same as generate_slides (default: Auto)
|
||||
--aspect-ratio RATIO # 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9 (default: 16:9)
|
||||
--resolution 1K|2K|4K # default: 2K
|
||||
--page N # 0=auto, 1-100 (default: 1)
|
||||
--content-detail concise|standard # default: standard
|
||||
--mode sync|async # default: async
|
||||
```
|
||||
|
||||
**Step 3: Handle Results**
|
||||
|
||||
Returns same structure as create-like-this:
|
||||
```json
|
||||
{
|
||||
"slideUrl": "https://2slides.com/workspace?jobId=...",
|
||||
"pdfUrl": "https://...pdf...",
|
||||
"status": "completed",
|
||||
"message": "Successfully generated N slides",
|
||||
"slidePageCount": N
|
||||
}
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Same credit costs as create-like-this (100 credits/page for 1K/2K, 200 for 4K)
|
||||
- Processing time: ~30 seconds per page
|
||||
- Automatically generates PDF
|
||||
- Uses AI to create custom design based on content and specs
|
||||
|
||||
---
|
||||
|
||||
## 4. Document Summarization
|
||||
|
||||
Generate slides from document content.
|
||||
|
||||
### When to Use
|
||||
- User uploads a document (PDF, DOCX, TXT, etc.)
|
||||
- User says "create slides from this document"
|
||||
- User wants to summarize long content into presentation format
|
||||
|
||||
### Workflow
|
||||
|
||||
**Step 1: Read Document**
|
||||
|
||||
Use appropriate tool to read the document content:
|
||||
- PDF: Use PDF reading tools
|
||||
- DOCX: Use DOCX reading tools
|
||||
- TXT/MD: Use Read tool
|
||||
|
||||
**Step 2: Extract Key Points**
|
||||
|
||||
Analyze the document and extract:
|
||||
- Main topics and themes
|
||||
- Key points for each section
|
||||
- Important data, quotes, or examples
|
||||
- Logical flow and structure
|
||||
|
||||
**Step 3: Structure Content**
|
||||
|
||||
Format extracted information into presentation structure:
|
||||
|
||||
```
|
||||
Title: [Document Main Topic]
|
||||
|
||||
Introduction
|
||||
- Context
|
||||
- Purpose
|
||||
- Overview
|
||||
|
||||
[Section 1 from document]
|
||||
- Key point 1
|
||||
- Key point 2
|
||||
- Supporting detail
|
||||
|
||||
[Section 2 from document]
|
||||
- Key point 1
|
||||
- Key point 2
|
||||
- Supporting detail
|
||||
|
||||
Conclusion
|
||||
- Summary
|
||||
- Key takeaways
|
||||
- Next steps
|
||||
```
|
||||
|
||||
**Step 4: Generate Slides**
|
||||
|
||||
Use content-based generation workflow (Section 1). First search for a theme, then generate:
|
||||
|
||||
```bash
|
||||
# Search for appropriate theme
|
||||
python scripts/search_themes.py --query "business"
|
||||
|
||||
# Generate with theme ID
|
||||
python scripts/generate_slides.py --content "[Structured content from step 3]" --theme-id "theme123"
|
||||
```
|
||||
|
||||
**Tips:**
|
||||
- Keep slides concise (3-5 points per slide)
|
||||
- Focus on key insights, not full text
|
||||
- Use document headings as slide titles
|
||||
- Include important statistics or quotes
|
||||
- Ask user if they want specific sections highlighted
|
||||
|
||||
---
|
||||
|
||||
## 5. Voice Narration
|
||||
|
||||
Add AI-generated voice narration to slides.
|
||||
|
||||
### When to Use
|
||||
- User wants to add audio to slides
|
||||
- User requests "add voice narration" or "generate audio"
|
||||
- User wants presentations with spoken content
|
||||
- User needs multi-speaker narration
|
||||
|
||||
### Prerequisites
|
||||
|
||||
**IMPORTANT:** The slide generation job must be completed before adding narration.
|
||||
|
||||
1. Generate slides first using any method (Section 1, 2, 3, or 4)
|
||||
2. Get the job ID from the generation result
|
||||
3. Ensure job status is "completed" before requesting narration
|
||||
|
||||
### Workflow
|
||||
|
||||
**Step 1: Choose Voice**
|
||||
|
||||
30 voices available including:
|
||||
- Puck (default)
|
||||
- Aoede
|
||||
- Charon
|
||||
- Kore
|
||||
- Fenrir
|
||||
- Phoebe
|
||||
- And 24 more...
|
||||
|
||||
List all voices:
|
||||
```bash
|
||||
python scripts/generate_narration.py --list-voices
|
||||
```
|
||||
|
||||
**Step 2: Generate Narration**
|
||||
|
||||
Use the `generate_narration.py` script with the job ID:
|
||||
|
||||
```bash
|
||||
# Basic narration with default voice
|
||||
python scripts/generate_narration.py --job-id "abc-123-def-456"
|
||||
|
||||
# Single speaker, specific voice
|
||||
python scripts/generate_narration.py --job-id "abc-123-def-456" --voice Aoede
|
||||
|
||||
# No speaker intro
|
||||
python scripts/generate_narration.py --job-id "abc-123-def-456" --no-intro
|
||||
|
||||
# Multi-speaker (names required)
|
||||
python scripts/generate_narration.py --job-id "abc-123-def-456" --multi-speaker \
|
||||
--speaker1-name "Alice" --speaker2-name "Bob" \
|
||||
--speaker1-voice Aoede --speaker2-voice Puck
|
||||
```
|
||||
|
||||
**Parameters (aligned with [2slides API](https://2slides.com/api.md)):**
|
||||
- `--job-id`: Job ID (required, UUID for Nano Banana)
|
||||
- `--mode`: `single` or `multi` (default: single)
|
||||
- `--speaker-name`: Speaker name (single mode)
|
||||
- `--voice`: Voice name (default: Puck); use `--list-voices` for all 30
|
||||
- `--content-mode`: `concise` or `standard` (default: standard)
|
||||
- `--no-intro`: Omit speaker introduction (single mode)
|
||||
- `--speaker1-name`, `--speaker2-name`: Required for multi mode
|
||||
- `--speaker1-voice`, `--speaker2-voice`: Optional for multi mode
|
||||
- `--multi-speaker`: Shortcut for `--mode multi`
|
||||
|
||||
**Step 3: Check Status**
|
||||
|
||||
Narration generation runs asynchronously:
|
||||
|
||||
```bash
|
||||
python scripts/get_job_status.py --job-id "abc-123-def-456"
|
||||
```
|
||||
|
||||
**Step 4: Handle Results**
|
||||
|
||||
Once completed, the job will include narration files. Use download endpoint (Section 6) to get audio files.
|
||||
|
||||
**Notes:**
|
||||
- **Cost:** 210 credits per page (10 for text, 200 for audio)
|
||||
- Processing time varies by slide count
|
||||
- 30 voice options available
|
||||
- Supports 19 languages plus auto-detection
|
||||
- Multi-speaker mode uses different voices for variety
|
||||
|
||||
---
|
||||
|
||||
## 6. Download Export
|
||||
|
||||
Download slides as PNG images and voice narrations as WAV files.
|
||||
|
||||
### When to Use
|
||||
- User wants to download slides as images
|
||||
- User needs voice files separately
|
||||
- User wants transcripts
|
||||
- User needs slides in image format for other tools
|
||||
|
||||
### Workflow
|
||||
|
||||
**Step 1: Verify Job Complete**
|
||||
|
||||
Ensure slides (and optionally narration) are generated and job is completed.
|
||||
|
||||
**Step 2: Download Archive**
|
||||
|
||||
Use the `download_slides_pages_voices.py` script:
|
||||
|
||||
```bash
|
||||
# Download with default filename (<job_id>.zip)
|
||||
python scripts/download_slides_pages_voices.py --job-id "abc-123-def-456"
|
||||
|
||||
# Download to specific path
|
||||
python scripts/download_slides_pages_voices.py \
|
||||
--job-id "abc-123-def-456" \
|
||||
--output "my-presentation.zip"
|
||||
```
|
||||
|
||||
**Step 3: Extract Contents**
|
||||
|
||||
The ZIP archive contains:
|
||||
- **Pages:** PNG files for each slide
|
||||
- **Voices:** WAV audio files (if narration was generated)
|
||||
- **Transcripts:** Text transcripts of narration
|
||||
|
||||
**Notes:**
|
||||
- **Cost:** Completely FREE (no credits used)
|
||||
- Download URLs valid for **1 hour only**
|
||||
- Includes all pages and voice files
|
||||
- High quality PNG export
|
||||
- WAV format for audio
|
||||
|
||||
---
|
||||
|
||||
## 7. Theme Search
|
||||
|
||||
Find appropriate themes for presentations.
|
||||
|
||||
### When to Use
|
||||
- Before generating slides with specific styling
|
||||
- User asks "what themes are available?"
|
||||
- User wants professional or branded appearance
|
||||
|
||||
### Workflow
|
||||
|
||||
**Search themes:**
|
||||
|
||||
```bash
|
||||
# Search for specific style (query is required)
|
||||
python scripts/search_themes.py --query "business"
|
||||
python scripts/search_themes.py --query "creative"
|
||||
python scripts/search_themes.py --query "education"
|
||||
python scripts/search_themes.py --query "professional"
|
||||
|
||||
# Get more results
|
||||
python scripts/search_themes.py --query "modern" --limit 50
|
||||
```
|
||||
|
||||
**Theme selection:**
|
||||
|
||||
1. Show user available themes with names and descriptions
|
||||
2. Ask user to choose or let them use default
|
||||
3. Use the theme ID in generation request
|
||||
|
||||
---
|
||||
|
||||
## Using the MCP Server
|
||||
|
||||
If the 2slides MCP server is configured in Claude Desktop, use the integrated tools instead of scripts.
|
||||
|
||||
**Two Configuration Modes:**
|
||||
|
||||
1. **Streamable HTTP Protocol (Recommended)**
|
||||
- Simplest setup, no local installation
|
||||
- Configure: `"url": "https://2slides.com/api/mcp?apikey=YOUR_API_KEY"`
|
||||
|
||||
2. **NPM Package (stdio)**
|
||||
- Uses local npm package
|
||||
- Configure: `"command": "npx", "args": ["2slides-mcp"]`
|
||||
|
||||
**Available MCP tools:**
|
||||
- `slides_generate` - Generate slides from content
|
||||
- `slides_create_like_this` - Generate from reference image
|
||||
- `themes_search` - Search themes
|
||||
- `jobs_get` - Check job status
|
||||
|
||||
See [mcp-integration.md](references/mcp-integration.md) for complete setup instructions and detailed tool documentation.
|
||||
|
||||
**When to use MCP vs scripts:**
|
||||
- **Use MCP** in Claude Desktop when configured
|
||||
- **Use scripts** in Claude Code CLI or when MCP not available
|
||||
|
||||
---
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Sync vs Async Mode
|
||||
|
||||
**Sync Mode (default):**
|
||||
- Waits for generation to complete (30-60 seconds)
|
||||
- Returns results immediately
|
||||
- Best for quick presentations
|
||||
|
||||
**Async Mode:**
|
||||
- Returns job ID immediately
|
||||
- Poll for results with `get_job_status.py`
|
||||
- Best for large presentations or batch processing
|
||||
- **Recommended polling:** Check every 20-30 seconds to avoid server strain
|
||||
|
||||
### Rate Limits
|
||||
|
||||
Different endpoints have different rate limits:
|
||||
|
||||
- **Fast PPT (generate):** 10 requests per minute
|
||||
- **Nano Banana (create-like-this, create-pdf-slides):** 6 requests per minute
|
||||
|
||||
If rate limited, wait before retrying or check plan limits.
|
||||
|
||||
### Credit Costs
|
||||
|
||||
- **Fast PPT (generate endpoint):** 10 credits per page
|
||||
- **Nano Banana 1K/2K (create-like-this, create-pdf-slides):** 100 credits per page
|
||||
- **Nano Banana 4K:** 200 credits per page
|
||||
- **Voice Narration:** 210 credits per page (10 for text, 200 for audio)
|
||||
- **Download Export:** FREE (no credits)
|
||||
|
||||
### Purchasing Credits
|
||||
|
||||
2slides uses a pay-as-you-go credit system with no subscriptions required.
|
||||
|
||||
**Credit Packages:** (Current promotion: up to 20% off)
|
||||
- 2,000 credits: $5.00
|
||||
- 4,000 credits: $9.50 (5% off)
|
||||
- 10,000 credits: $22.50 (10% off)
|
||||
- 20,000 credits: $42.50 (15% off)
|
||||
- 40,000 credits: $80.00 (20% off)
|
||||
|
||||
**New users receive 500 free credits** for onboarding (~50 Fast PPT pages).
|
||||
|
||||
**Credits never expire** - use them at your own pace.
|
||||
|
||||
**Purchase credits at:** https://2slides.com/pricing
|
||||
|
||||
### Download URL Expiration
|
||||
|
||||
All download URLs (PDF, ZIP archives) are valid for **1 hour only**. Download files promptly after generation.
|
||||
|
||||
### Language Support
|
||||
|
||||
Generate slides in multiple languages (use full language name):
|
||||
|
||||
```bash
|
||||
--language "Auto" # Automatic detection (default)
|
||||
--language "English" # English
|
||||
--language "Simplified Chinese" # 简体中文
|
||||
--language "Traditional Chinese" # 繁體中文
|
||||
--language "Spanish" # Español
|
||||
--language "French" # Français
|
||||
--language "German" # Deutsch
|
||||
--language "Japanese" # 日本語
|
||||
--language "Korean" # 한국어
|
||||
```
|
||||
|
||||
And more: Arabic, Portuguese, Indonesian, Russian, Hindi, Vietnamese, Turkish, Polish, Italian
|
||||
|
||||
### Error Handling
|
||||
|
||||
**Common error codes:**
|
||||
|
||||
1. **Missing API key**
|
||||
```
|
||||
Error: API key not found
|
||||
Solution: Set SLIDES_2SLIDES_API_KEY environment variable
|
||||
```
|
||||
|
||||
2. **RATE_LIMIT_EXCEEDED**
|
||||
```
|
||||
Error: 429 Too Many Requests
|
||||
Solution: Wait 20-30 seconds before retrying
|
||||
Rate limits: Fast PPT (10/min), Nano Banana (6/min)
|
||||
```
|
||||
|
||||
3. **INSUFFICIENT_CREDITS**
|
||||
```
|
||||
Error: Not enough credits
|
||||
Solution: Add credits at https://2slides.com/api
|
||||
```
|
||||
|
||||
4. **INVALID_JOB_ID**
|
||||
```
|
||||
Error: Job ID not found or invalid
|
||||
Solution: Verify job ID format (must be UUID for Nano Banana)
|
||||
```
|
||||
|
||||
5. **Invalid content**
|
||||
```
|
||||
Error: 400 Bad Request
|
||||
Solution: Verify content format and parameters
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Script Parameter Reference (2slides API)
|
||||
|
||||
All scripts accept parameters that match [2slides API](https://2slides.com/api.md). Allowed values are defined in `scripts/api_constants.py` and enforced where applicable.
|
||||
|
||||
| Script | Key parameters | Allowed values (see script `--help` or api_constants.py) |
|
||||
|--------|----------------|----------------------------------------------------------|
|
||||
| `generate_slides.py` | `--language` | Auto, English, Spanish, Arabic, Portuguese, Indonesian, Japanese, Russian, Hindi, French, German, Greek, Vietnamese, Turkish, Polish, Italian, Korean, Simplified Chinese, Traditional Chinese, Thai |
|
||||
| | `--mode` | sync, async |
|
||||
| | `--aspect-ratio` | 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9 |
|
||||
| | `--resolution` | 1K, 2K, 4K |
|
||||
| | `--content-detail` | concise, standard |
|
||||
| `create_pdf_slides.py` | Same as above + `--design-style` (free text), `--mode` (default async) | |
|
||||
| `generate_narration.py` | `--mode` | single, multi |
|
||||
| | `--voice` | 30 voices (Puck, Aoede, Charon, …); use `--list-voices` |
|
||||
| | `--content-mode` | concise, standard |
|
||||
| | Multi: `--speaker1-name`, `--speaker2-name`, `--speaker1-voice`, `--speaker2-voice` | |
|
||||
| `search_themes.py` | `--query` (required), `--limit` (1–100) | |
|
||||
| `get_job_status.py` | `--job-id` (required) | |
|
||||
| `download_slides_pages_voices.py` | `--job-id` (required), `--output` (path) | |
|
||||
|
||||
---
|
||||
|
||||
## Additional Documentation
|
||||
|
||||
### API Reference
|
||||
See [api-reference.md](references/api-reference.md) for:
|
||||
- All endpoints and parameters
|
||||
- Request/response formats
|
||||
- Authentication details
|
||||
- Rate limits and best practices
|
||||
- Error codes and handling
|
||||
|
||||
### Pricing Information
|
||||
See [pricing.md](references/pricing.md) for:
|
||||
- Credit packages and pricing
|
||||
- Cost examples and calculations
|
||||
- Free trial details
|
||||
- Refund policy
|
||||
- Enterprise options
|
||||
|
||||
---
|
||||
|
||||
## Tips for Best Results
|
||||
|
||||
**Content Structure:**
|
||||
- Use clear headings and subheadings
|
||||
- Keep bullet points concise
|
||||
- Limit to 3-5 points per section
|
||||
- Include relevant examples or data
|
||||
|
||||
**Theme Selection:**
|
||||
- Theme ID is required for standard generation
|
||||
- Search with keywords matching presentation purpose
|
||||
- Common searches: "business", "professional", "creative", "education", "modern"
|
||||
- Each theme has unique styling and layout
|
||||
|
||||
**Reference Images:**
|
||||
- Use high-quality images for best results
|
||||
- Can use URL or base64 encoded image
|
||||
- Public URL must be accessible
|
||||
- Consider resolution setting (1K/2K/4K) based on quality needs
|
||||
- Use page=0 for automatic slide count detection
|
||||
|
||||
**Document Processing:**
|
||||
- Extract only key information
|
||||
- Don't try to fit entire document in slides
|
||||
- Focus on main insights and takeaways
|
||||
- Ask user which sections to emphasize
|
||||
|
||||
---
|
||||
|
||||
## Security & Safety Notes
|
||||
|
||||
- **Credentials:** This skill reads the API key from the `SLIDES_2SLIDES_API_KEY` environment variable. Never hard-code the key in commands, commit it, or echo it back to the user. The scripts send it as a bearer/`apikey` value to `https://2slides.com` over HTTPS only.
|
||||
- **Network + paid mutations:** Every generation call makes an outbound network request to the 2slides API and **spends the user's credits** (10–210 credits/page depending on mode). Treat generation, reference-image, custom-PDF, and narration calls as billable actions — confirm intent before generating large or high-resolution (4K) decks, and surface the expected page count/cost when it is non-trivial.
|
||||
- **No destructive local actions:** The scripts only read content/files the user points to and write generated output (e.g. a downloaded ZIP) to the path the user specifies. They do not modify or delete unrelated files.
|
||||
- **Input handling:** Reference-image and document inputs are sent to the 2slides service for processing. Do not submit confidential material the user has not authorized for third-party processing.
|
||||
- **Download URLs expire in 1 hour** — fetch artifacts promptly and do not treat the URLs as durable storage.
|
||||
|
||||
## Limitations
|
||||
|
||||
- Requires a valid 2slides account, API key, and sufficient credits; this skill does not provision or pay for credits.
|
||||
- Results are AI-generated drafts intended as a starting point, not a final, fact-checked deliverable — review content before use.
|
||||
- This skill does not replace environment-specific validation or expert review. Stop and ask for clarification if the API key, required inputs, or intended cost/scope are missing.
|
||||
- Rate limits apply (Fast PPT 10/min, Nano Banana 6/min); poll async jobs every 20–30s rather than tight-looping.
|
||||
|
||||
## Related Skills
|
||||
|
||||
- `@youtube-full` — fetch source material (transcripts) that can be summarized into a deck with this skill.
|
||||
@@ -0,0 +1,499 @@
|
||||
# 2slides API Reference
|
||||
|
||||
Complete API documentation for 2slides slide generation service.
|
||||
|
||||
## Base URL
|
||||
|
||||
```
|
||||
https://2slides.com/api/v1
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
All API requests require authentication using a Bearer token in the Authorization header:
|
||||
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
```
|
||||
|
||||
Get your API key from: https://2slides.com/api
|
||||
|
||||
Store the API key in environment variable: `SLIDES_2SLIDES_API_KEY`
|
||||
|
||||
## Endpoints
|
||||
|
||||
### 1. Generate Slides
|
||||
|
||||
Generate slides from user input with optional theme selection.
|
||||
|
||||
**Endpoint:** `POST /slides/generate`
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"userInput": "string (required) - Content to convert into slides",
|
||||
"themeId": "string (required) - Theme ID from themes/search",
|
||||
"responseLanguage": "string (optional, default: 'Auto') - Language code",
|
||||
"mode": "string (optional, default: 'sync') - 'sync' or 'async'"
|
||||
}
|
||||
```
|
||||
|
||||
**Supported Languages:**
|
||||
Auto, English, Simplified Chinese (简体中文), Traditional Chinese (繁體中文), Spanish, Arabic, Portuguese, Indonesian, Japanese, Russian, Hindi, French, German, Vietnamese, Turkish, Polish, Italian, Korean
|
||||
|
||||
**Response (sync mode):**
|
||||
```json
|
||||
{
|
||||
"slideUrl": "https://2slides.com/slides/...",
|
||||
"pdfUrl": "https://2slides.com/slides/.../download",
|
||||
"status": "completed"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (async mode):**
|
||||
```json
|
||||
{
|
||||
"jobId": "abc123...",
|
||||
"status": "pending"
|
||||
}
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- **Sync mode**: Waits for generation to complete and returns the result directly (may take 30-60 seconds)
|
||||
- **Async mode**: Returns immediately with a jobId to poll for results using `/jobs/{jobId}`
|
||||
|
||||
---
|
||||
|
||||
### 2. Create Like This (Reference Image)
|
||||
|
||||
Generate slides matching a reference image style (Nano Banana Pro mode).
|
||||
|
||||
**Endpoint:** `POST /slides/create-like-this`
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"userInput": "string (required) - Content for slides",
|
||||
"referenceImageUrl": "string (required) - URL or base64 of reference image",
|
||||
"responseLanguage": "string (optional, default: 'Auto')",
|
||||
"aspectRatio": "string (optional, default: '16:9') - width:height format",
|
||||
"resolution": "string (optional, default: '2K') - '1K', '2K', or '4K'",
|
||||
"page": "number (optional, default: 1) - 0 for auto-detection, max 100",
|
||||
"contentDetail": "string (optional, default: 'concise') - 'concise' or 'standard'"
|
||||
}
|
||||
```
|
||||
|
||||
**Resolution Options:**
|
||||
- **1K**: Standard quality
|
||||
- **2K**: High quality (default)
|
||||
- **4K**: Ultra high quality
|
||||
|
||||
**Content Detail Options:**
|
||||
- **concise**: Brief, keyword-focused content
|
||||
- **standard**: Comprehensive, detailed content
|
||||
|
||||
**Page Parameter:**
|
||||
- Set to `0` to enable automatic slide count detection
|
||||
- Set to specific number (1-100) for exact slide count
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"jobId": "608f8997-5207-480c-9ff2-d2475cba6b9d",
|
||||
"status": "success",
|
||||
"message": "Successfully generated N slides",
|
||||
"downloadUrl": "https://...pdf...",
|
||||
"jobUrl": "https://2slides.com/workspace?jobId=...",
|
||||
"createdAt": 1770108913384,
|
||||
"updatedAt": 1770108934015,
|
||||
"slidePageCount": 3,
|
||||
"successCount": 3,
|
||||
"failedCount": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response Fields:**
|
||||
- `success`: Boolean indicating if request succeeded
|
||||
- `data.jobId`: Unique job identifier
|
||||
- `data.status`: Generation status ("success" or "failed")
|
||||
- `data.message`: Human-readable status message
|
||||
- `data.downloadUrl`: Direct PDF download URL (temporary, expires in 1 hour)
|
||||
- `data.jobUrl`: View slides in 2slides workspace
|
||||
- `data.slidePageCount`: Number of slides generated
|
||||
- `data.successCount`: Number of successfully generated slides
|
||||
- `data.failedCount`: Number of failed slides
|
||||
|
||||
**Notes:**
|
||||
- This endpoint always runs synchronously
|
||||
- Processing time: ~30 seconds per page
|
||||
- Typical response time: 30-60 seconds for 1-2 pages
|
||||
- Automatically generates PDF
|
||||
- Matches the style and design of the reference image
|
||||
- **Timeout recommendation**: Set timeout to `max(120, pages * 40)` seconds
|
||||
|
||||
---
|
||||
|
||||
### 3. Create PDF Slides
|
||||
|
||||
Generate custom-designed slides from text with optional design specifications.
|
||||
|
||||
**Endpoint:** `POST /slides/create-pdf-slides`
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"userInput": "string (required) - Content for slides",
|
||||
"responseLanguage": "string (optional, default: 'Auto')",
|
||||
"aspectRatio": "string (optional, default: '16:9') - width:height format",
|
||||
"resolution": "string (optional, default: '2K') - '1K', '2K', or '4K'",
|
||||
"page": "number (optional, default: 1) - 0 for auto-detection, max 100",
|
||||
"contentDetail": "string (optional, default: 'concise') - 'concise' or 'standard'",
|
||||
"designSpec": "string (optional) - Design specifications (e.g., 'modern minimalist')"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"jobId": "608f8997-5207-480c-9ff2-d2475cba6b9d",
|
||||
"status": "success",
|
||||
"message": "Successfully generated N slides",
|
||||
"downloadUrl": "https://...pdf...",
|
||||
"jobUrl": "https://2slides.com/workspace?jobId=...",
|
||||
"slidePageCount": 3,
|
||||
"successCount": 3,
|
||||
"failedCount": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Similar to create-like-this but without reference image
|
||||
- Uses AI to generate custom design based on content and design specs
|
||||
- Same credit costs: 100 credits/page (1K/2K), 200 credits/page (4K)
|
||||
- Processing time: ~30 seconds per page
|
||||
- Always runs synchronously
|
||||
|
||||
---
|
||||
|
||||
### 4. Generate Narration
|
||||
|
||||
Add AI voice narration to slides in single or multi-speaker mode.
|
||||
|
||||
**Endpoint:** `POST /slides/generate-narration`
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"jobId": "string (required) - Job ID from slide generation (UUID format)",
|
||||
"language": "string (optional, default: 'Auto') - Language for narration",
|
||||
"voice": "string (optional, default: 'Puck') - Voice name from available voices",
|
||||
"multiSpeaker": "boolean (optional, default: false) - Enable multi-speaker mode"
|
||||
}
|
||||
```
|
||||
|
||||
**Available Voices (30 total):**
|
||||
Puck, Aoede, Charon, Kore, Fenrir, Phoebe, Asteria, Luna, Stella, Theia, Helios, Atlas, Clio, Melpomene, Calliope, Erato, Euterpe, Polyhymnia, Terpsichore, Thalia, Urania, Zeus, Hera, Poseidon, Athena, Apollo, Artemis, Ares, Aphrodite, Hephaestus
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"jobId": "abc123...",
|
||||
"status": "pending",
|
||||
"message": "Narration generation started"
|
||||
}
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Job must be completed before adding narration
|
||||
- Job ID must be UUID format for Nano Banana jobs
|
||||
- Cost: 210 credits per page (10 for text, 200 for audio)
|
||||
- Runs asynchronously - poll with /jobs/{jobId}
|
||||
- Multi-speaker mode uses different voices for variety
|
||||
- 19 languages supported plus auto-detection
|
||||
|
||||
---
|
||||
|
||||
### 5. Download Slides Pages and Voices
|
||||
|
||||
Export slides as PNG files and voice narrations as WAV files in a ZIP archive.
|
||||
|
||||
**Endpoint:** `POST /slides/download-slides-pages-voices`
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"jobId": "string (required) - Job ID from slide generation"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"downloadUrl": "https://...zip...",
|
||||
"message": "Download ready"
|
||||
}
|
||||
```
|
||||
|
||||
**Archive Contents:**
|
||||
- Pages: PNG files for each slide
|
||||
- Voices: WAV audio files (if narration generated)
|
||||
- Transcripts: Text files with narration transcripts
|
||||
|
||||
**Notes:**
|
||||
- **Cost: Completely FREE** (no credits used)
|
||||
- Download URL valid for **1 hour only**
|
||||
- High quality PNG export
|
||||
- WAV format for audio
|
||||
- Includes all slides and voice files
|
||||
|
||||
---
|
||||
|
||||
### 6. Search Themes
|
||||
|
||||
Search for available presentation themes.
|
||||
|
||||
**Endpoint:** `GET /themes/search`
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
```
|
||||
query: string (required) - Search keyword
|
||||
limit: number (optional, default: 20, max: 100)
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"themes": [
|
||||
{
|
||||
"id": "theme_id_123",
|
||||
"name": "Professional Blue",
|
||||
"description": "Clean professional theme with blue accents",
|
||||
"previewUrl": "https://..."
|
||||
}
|
||||
],
|
||||
"count": 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. Get Job Status
|
||||
|
||||
Retrieve the status and results of an async generation job.
|
||||
|
||||
**Endpoint:** `GET /jobs/{jobId}`
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
```
|
||||
|
||||
**Path Parameters:**
|
||||
```
|
||||
jobId: string (required) - Job ID from async generation
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"jobId": "abc123",
|
||||
"status": "completed|pending|failed",
|
||||
"slideUrl": "https://2slides.com/slides/...",
|
||||
"pdfUrl": "https://2slides.com/slides/.../download",
|
||||
"narrationStatus": "completed|pending|not_started",
|
||||
"error": "error message if failed"
|
||||
}
|
||||
```
|
||||
|
||||
**Status Values:**
|
||||
- `pending`: Job is still processing
|
||||
- `completed`: Slides are ready
|
||||
- `failed`: Generation failed (see error field)
|
||||
|
||||
**Narration Status Values:**
|
||||
- `not_started`: No narration requested
|
||||
- `pending`: Narration is being generated
|
||||
- `completed`: Narration is ready
|
||||
|
||||
**Polling Recommendation:**
|
||||
Poll every 20-30 seconds to avoid server strain
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
All endpoints return standard HTTP status codes:
|
||||
|
||||
- `200 OK`: Request succeeded
|
||||
- `400 Bad Request`: Invalid parameters
|
||||
- `401 Unauthorized`: Missing or invalid API key
|
||||
- `404 Not Found`: Resource not found
|
||||
- `429 Too Many Requests`: Rate limit exceeded
|
||||
- `500 Internal Server Error`: Server error
|
||||
|
||||
**Error Response Format:**
|
||||
```json
|
||||
{
|
||||
"error": "Error message",
|
||||
"code": "ERROR_CODE"
|
||||
}
|
||||
```
|
||||
|
||||
**Common Error Codes:**
|
||||
- `INSUFFICIENT_CREDITS`: Account has insufficient credits
|
||||
- `INVALID_JOB_ID`: Job ID not found or invalid format
|
||||
- `RATE_LIMIT_EXCEEDED`: Too many requests (see rate limits below)
|
||||
- `JOB_NOT_COMPLETED`: Job must complete before adding narration
|
||||
- `INVALID_UUID`: Job ID must be UUID format (for Nano Banana jobs)
|
||||
|
||||
---
|
||||
|
||||
## Credit Costs
|
||||
|
||||
- **Fast PPT (generate endpoint)**: 10 credits per page
|
||||
- **Nano Banana 1K/2K (create-like-this, create-pdf-slides)**: 100 credits per page
|
||||
- **Nano Banana 4K**: 200 credits per page
|
||||
- **Voice Narration**: 210 credits per page (10 for text, 200 for audio)
|
||||
- **Download Export**: FREE (no credits)
|
||||
|
||||
## Purchasing Credits
|
||||
|
||||
2slides operates on a **pay-as-you-go credit system** with no subscriptions.
|
||||
|
||||
**Credit Packages** (Current promotion: up to 20% off):
|
||||
|
||||
| Credits | Price | Cost per 1,000 | Savings |
|
||||
|---------|-------|---------------|---------|
|
||||
| 2,000 | $5.00 | $2.50 | — |
|
||||
| 4,000 | $9.50 | $2.38 | 5% |
|
||||
| 10,000 | $22.50 | $2.25 | 10% |
|
||||
| 20,000 | $42.50 | $2.13 | 15% |
|
||||
| 40,000 | $80.00 | $2.00 | 20% |
|
||||
|
||||
**Key Benefits:**
|
||||
- New users get **500 free credits** (~50 Fast PPT pages)
|
||||
- **Credits never expire**
|
||||
- No monthly subscriptions
|
||||
- 3-day refund window
|
||||
- Purchase at: https://2slides.com/pricing
|
||||
|
||||
**Example Costs:**
|
||||
- 10-slide Fast PPT presentation: 100 credits ($0.25 with largest package)
|
||||
- 10-slide Nano Banana 2K presentation: 1,000 credits ($2.00 with largest package)
|
||||
- 10-slide presentation with narration: 2,100 credits ($4.20 with largest package)
|
||||
|
||||
## Rate Limits
|
||||
|
||||
Different endpoints have different rate limits:
|
||||
|
||||
- **Fast PPT (generate)**: 10 requests per minute
|
||||
- **Nano Banana (create-like-this, create-pdf-slides)**: 6 requests per minute
|
||||
|
||||
**Best Practices:**
|
||||
- Poll async jobs every 20-30 seconds to avoid server strain
|
||||
- If rate limited (429 error), wait before retrying
|
||||
- Check your plan's rate limits at https://2slides.com/api
|
||||
|
||||
## Download URL Expiration
|
||||
|
||||
All download URLs (PDF, ZIP archives) remain valid for **1 hour only**. Download files promptly after generation.
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Content Formatting
|
||||
|
||||
**For best results, structure content clearly:**
|
||||
|
||||
```
|
||||
Title: Introduction to AI
|
||||
|
||||
Section 1: Machine Learning
|
||||
- Definition
|
||||
- Key concepts
|
||||
- Applications
|
||||
|
||||
Section 2: Deep Learning
|
||||
- Neural networks
|
||||
- Training process
|
||||
- Use cases
|
||||
```
|
||||
|
||||
### Choosing Sync vs Async Mode
|
||||
|
||||
- **Use sync** for quick generations (<5 slides)
|
||||
- **Use async** for larger presentations (>5 slides)
|
||||
- **Use async** when integrating into workflows that can poll
|
||||
|
||||
### Theme Selection
|
||||
|
||||
1. Search themes with relevant keywords
|
||||
2. Preview themes if URLs available
|
||||
3. Use theme ID in generation request
|
||||
4. Leave theme blank for default styling
|
||||
|
||||
### Language Support
|
||||
|
||||
Specify `responseLanguage` to generate slides in different languages:
|
||||
- `"Auto"` - Automatic language detection (default)
|
||||
- `"English"` - English
|
||||
- `"Simplified Chinese"` - 简体中文
|
||||
- `"Traditional Chinese"` - 繁體中文
|
||||
- `"Spanish"` - Español
|
||||
- `"Arabic"` - العربية
|
||||
- `"Portuguese"` - Português
|
||||
- `"Indonesian"` - Bahasa Indonesia
|
||||
- `"Japanese"` - 日本語
|
||||
- `"Russian"` - Русский
|
||||
- `"Hindi"` - हिन्दी
|
||||
- `"French"` - Français
|
||||
- `"German"` - Deutsch
|
||||
- `"Vietnamese"` - Tiếng Việt
|
||||
- `"Turkish"` - Türkçe
|
||||
- `"Polish"` - Polski
|
||||
- `"Italian"` - Italiano
|
||||
- `"Korean"` - 한국어
|
||||
+282
@@ -0,0 +1,282 @@
|
||||
# MCP Integration Guide
|
||||
|
||||
2slides provides an MCP (Model Context Protocol) server for seamless integration with Claude Desktop and other MCP-compatible AI agents.
|
||||
|
||||
## What is the MCP Server?
|
||||
|
||||
The 2slides MCP server exposes the same API functionality as direct API calls, but through a standardized tool interface that Claude can use directly without requiring script execution.
|
||||
|
||||
**Available Tools:**
|
||||
1. `slides_generate` - Generate slides from content
|
||||
2. `slides_create_like_this` - Generate slides from reference image
|
||||
3. `slides_create_pdf_slides` - Generate custom-designed slides (NEW)
|
||||
4. `slides_generate_narration` - Add AI voice narration (NEW)
|
||||
5. `slides_download_pages_voices` - Export slides and voices as ZIP (NEW)
|
||||
6. `themes_search` - Search available themes
|
||||
7. `jobs_get` - Check job status
|
||||
|
||||
**Note:** New tools (3-5) may require MCP server update to latest version.
|
||||
|
||||
## Installation & Configuration
|
||||
|
||||
2slides MCP server supports two integration modes:
|
||||
|
||||
### Mode 1: Streamable HTTP Protocol (Recommended)
|
||||
|
||||
Simplest setup using HTTP endpoint. No local installation required.
|
||||
|
||||
**Step 1:** Get your API key from https://2slides.com/api
|
||||
|
||||
**Step 2:** Configure Claude Desktop
|
||||
|
||||
Edit: `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"2slides": {
|
||||
"url": "https://2slides.com/api/mcp?apikey=YOUR_2SLIDES_API_KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3:** Restart Claude Desktop completely
|
||||
|
||||
**Advantages:**
|
||||
- ✅ No Node.js or npm required
|
||||
- ✅ Always uses latest version
|
||||
- ✅ Faster setup
|
||||
- ✅ No local dependencies
|
||||
|
||||
---
|
||||
|
||||
### Mode 2: NPM Package (stdio)
|
||||
|
||||
Uses local npm package for MCP server.
|
||||
|
||||
**Step 1:** Get your API key from https://2slides.com/api
|
||||
|
||||
**Step 2:** Configure Claude Desktop
|
||||
|
||||
Edit: `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"2slides": {
|
||||
"command": "npx",
|
||||
"args": ["2slides-mcp"],
|
||||
"env": {
|
||||
"API_KEY": "YOUR_2SLIDES_API_KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3:** Restart Claude Desktop completely
|
||||
|
||||
**Requirements:**
|
||||
- Node.js and npm installed
|
||||
- Internet connection for first-time package download
|
||||
|
||||
---
|
||||
|
||||
### Verify Installation
|
||||
|
||||
After restart, the 2slides tools should be available. Test by asking:
|
||||
"Search for business themes using 2slides"
|
||||
|
||||
## When to Use MCP vs Direct API
|
||||
|
||||
### Use MCP Server When:
|
||||
- Working in Claude Desktop or other MCP-compatible environments
|
||||
- Want seamless tool integration without script management
|
||||
- Prefer Claude to handle API calls directly
|
||||
- Need real-time interaction and feedback
|
||||
|
||||
### Use Direct API Scripts When:
|
||||
- Working in Claude Code CLI
|
||||
- MCP server is not configured or available
|
||||
- Need more control over parameters and error handling
|
||||
- Integrating into custom workflows or automation
|
||||
- Need to batch process multiple requests
|
||||
|
||||
## MCP Tool Details
|
||||
|
||||
### slides_generate
|
||||
|
||||
Generate slides from user content.
|
||||
|
||||
**Parameters:**
|
||||
- `userInput` (string, required): Content to convert
|
||||
- `themeId` (string, required): Theme ID from themes_search
|
||||
- `responseLanguage` (string, optional, default: "Auto"): Language name
|
||||
- `mode` (string, optional, default: "sync"): "sync" or "async"
|
||||
|
||||
**Example:**
|
||||
```
|
||||
First search for a theme:
|
||||
Use themes_search with:
|
||||
- query: "business"
|
||||
|
||||
Then generate with the theme ID:
|
||||
Use slides_generate with:
|
||||
- userInput: "Introduction to Python: Variables, Functions, Classes"
|
||||
- themeId: "theme_abc123"
|
||||
- mode: "sync"
|
||||
```
|
||||
|
||||
### slides_create_like_this
|
||||
|
||||
Generate slides matching a reference image.
|
||||
|
||||
**Parameters:**
|
||||
- `userInput` (string, required): Content for slides
|
||||
- `referenceImageUrl` (string, required): URL or base64 of reference image
|
||||
- `responseLanguage` (string, optional, default: "Auto"): Language name
|
||||
- `aspectRatio` (string, optional, default: "16:9"): width:height format
|
||||
- `resolution` (string, optional, default: "2K"): "1K", "2K", or "4K"
|
||||
- `page` (number, optional, default: 1): Number of slides (0 for auto-detection, max 100)
|
||||
- `contentDetail` (string, optional, default: "concise"): "concise" or "standard"
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Use slides_create_like_this with:
|
||||
- userInput: "Sales Report Q4 2025"
|
||||
- referenceImageUrl: "https://example.com/template.jpg"
|
||||
- resolution: "2K"
|
||||
- page: 0 # Auto-detect slide count
|
||||
- contentDetail: "standard"
|
||||
```
|
||||
|
||||
### themes_search
|
||||
|
||||
Search for available themes.
|
||||
|
||||
**Parameters:**
|
||||
- `query` (string, required): Search keyword
|
||||
- `limit` (number, optional, default: 20, max: 100): Max results
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Use themes_search with:
|
||||
- query: "business"
|
||||
- limit: 10
|
||||
```
|
||||
|
||||
**Note:** Query parameter is required. Search with keywords like "business", "professional", "creative", "education", "modern" to find appropriate themes.
|
||||
|
||||
### slides_create_pdf_slides
|
||||
|
||||
Generate custom-designed slides from text without a reference image.
|
||||
|
||||
**Parameters:**
|
||||
- `userInput` (string, required): Content for slides
|
||||
- `responseLanguage` (string, optional, default: "Auto"): Language name
|
||||
- `aspectRatio` (string, optional, default: "16:9"): width:height format
|
||||
- `resolution` (string, optional, default: "2K"): "1K", "2K", or "4K"
|
||||
- `page` (number, optional, default: 1): Number of slides (0 for auto-detection, max 100)
|
||||
- `contentDetail` (string, optional, default: "concise"): "concise" or "standard"
|
||||
- `designSpec` (string, optional): Design specifications
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Use slides_create_pdf_slides with:
|
||||
- userInput: "Sales Report Q4 2025"
|
||||
- designSpec: "modern minimalist, blue color scheme"
|
||||
- resolution: "2K"
|
||||
- page: 0 # Auto-detect slide count
|
||||
```
|
||||
|
||||
### slides_generate_narration
|
||||
|
||||
Add AI voice narration to completed slides.
|
||||
|
||||
**Parameters:**
|
||||
- `jobId` (string, required): Job ID from slide generation (UUID format)
|
||||
- `language` (string, optional, default: "Auto"): Language for narration
|
||||
- `voice` (string, optional, default: "Puck"): Voice name (30 options available)
|
||||
- `multiSpeaker` (boolean, optional, default: false): Enable multi-speaker mode
|
||||
|
||||
**Available Voices:**
|
||||
Puck, Aoede, Charon, Kore, Fenrir, Phoebe, Asteria, Luna, Stella, Theia, Helios, Atlas, Clio, Melpomene, Calliope, Erato, Euterpe, Polyhymnia, Terpsichore, Thalia, Urania, Zeus, Hera, Poseidon, Athena, Apollo, Artemis, Ares, Aphrodite, Hephaestus
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Use slides_generate_narration with:
|
||||
- jobId: "abc-123-def-456"
|
||||
- voice: "Aoede"
|
||||
- multiSpeaker: true
|
||||
- language: "English"
|
||||
```
|
||||
|
||||
**Note:** Job must be completed before adding narration. Cost: 210 credits per page.
|
||||
|
||||
### slides_download_pages_voices
|
||||
|
||||
Download slides as PNG images and voice files as WAV in a ZIP archive.
|
||||
|
||||
**Parameters:**
|
||||
- `jobId` (string, required): Job ID from slide generation
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Use slides_download_pages_voices with:
|
||||
- jobId: "abc-123-def-456"
|
||||
```
|
||||
|
||||
**Note:** Completely FREE (no credits). Download URL valid for 1 hour.
|
||||
|
||||
### jobs_get
|
||||
|
||||
Check status of async job.
|
||||
|
||||
**Parameters:**
|
||||
- `jobId` (string, required): Job ID from async generation
|
||||
|
||||
**Response includes:**
|
||||
- Slide generation status
|
||||
- Narration status (if applicable)
|
||||
- Download URLs (when completed)
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Use jobs_get with:
|
||||
- jobId: "abc123..."
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Tools Not Appearing
|
||||
|
||||
1. Verify configuration file syntax is valid JSON
|
||||
2. For HTTP mode: Check API key is correctly in the URL
|
||||
3. For npm mode: Ensure API key is correctly set in the `env` section
|
||||
4. Restart Claude Desktop completely (quit fully, not just close window)
|
||||
5. Check for error messages in Claude Desktop console
|
||||
|
||||
### API Key Issues
|
||||
|
||||
- Verify API key is active at https://2slides.com/api
|
||||
- Check for typos in the configuration
|
||||
- Ensure no extra quotes or spaces around the key
|
||||
- For HTTP mode: API key must be in the URL query parameter
|
||||
|
||||
### HTTP Mode Issues
|
||||
|
||||
- Verify URL format: `https://2slides.com/api/mcp?apikey=YOUR_KEY`
|
||||
- Check internet connectivity
|
||||
- Ensure API key has no special characters that need URL encoding
|
||||
|
||||
### NPM Mode Issues
|
||||
|
||||
- Ensure `npx` is available (requires Node.js)
|
||||
- Try running `npx 2slides-mcp` manually to check for errors
|
||||
- Verify internet connection for package download
|
||||
- Check Node.js version compatibility
|
||||
|
||||
## GitHub Repository
|
||||
|
||||
For more information, visit: https://github.com/2slides/mcp-2slides
|
||||
@@ -0,0 +1,195 @@
|
||||
# 2slides Pricing & Credit Information
|
||||
|
||||
Complete pricing details and credit system information.
|
||||
|
||||
## Credit System Overview
|
||||
|
||||
2slides operates on a **pay-as-you-go credit system** with no monthly subscriptions or recurring charges.
|
||||
|
||||
### Key Benefits
|
||||
|
||||
- ✅ **Credits never expire** - Use them at your own pace
|
||||
- ✅ **No subscriptions** - Pay only for what you use
|
||||
- ✅ **Volume discounts** - Save up to 20% on larger packages
|
||||
- ✅ **3-day refund window** - Risk-free purchase
|
||||
- ✅ **500 free credits** - Free trial for new users
|
||||
|
||||
## Credit Packages
|
||||
|
||||
**Current Promotion:** Up to 20% off credits for a limited time.
|
||||
|
||||
| Credits | Original Price | Current Price | Discount | Cost per 1,000 |
|
||||
|---------|----------------|---------------|----------|----------------|
|
||||
| 2,000 | $5.00 | $5.00 | — | $2.50 |
|
||||
| 4,000 | $10.00 | $9.50 | 5% | $2.38 |
|
||||
| 10,000 | $25.00 | $22.50 | 10% | $2.25 |
|
||||
| 20,000 | $50.00 | $42.50 | 15% | $2.13 |
|
||||
| 40,000 | $100.00 | $80.00 | 20% | $2.00 |
|
||||
|
||||
**Purchase at:** https://2slides.com/pricing
|
||||
|
||||
## Credit Costs by Feature
|
||||
|
||||
| Feature | Credits per Page | Example (10 pages) |
|
||||
|---------|-----------------|-------------------|
|
||||
| Fast PPT (theme-based) | 10 | 100 credits |
|
||||
| Nano Banana 1K/2K (image/custom) | 100 | 1,000 credits |
|
||||
| Nano Banana 4K | 200 | 2,000 credits |
|
||||
| Voice Narration | +210 | +2,100 credits |
|
||||
| Download Export | FREE | 0 credits |
|
||||
|
||||
### Detailed Cost Breakdown
|
||||
|
||||
**Fast PPT Generation (Theme-Based)**
|
||||
- 10 credits per page
|
||||
- Uses pre-designed themes
|
||||
- Fastest generation mode
|
||||
- Cost example: 20-page presentation = 200 credits
|
||||
|
||||
**Nano Banana (Image Matching / Custom PDF)**
|
||||
- **1K/2K resolution:** 100 credits per page
|
||||
- **4K resolution:** 200 credits per page
|
||||
- Matches reference image style or generates custom design
|
||||
- Higher quality output
|
||||
- Cost example: 10-page 2K presentation = 1,000 credits
|
||||
|
||||
**Voice Narration**
|
||||
- 210 credits per page total
|
||||
- 10 credits for text processing
|
||||
- 200 credits for audio generation
|
||||
- 30 voice options available
|
||||
- Multi-speaker mode included
|
||||
- Cost example: 5-page narration = 1,050 credits
|
||||
|
||||
**Download Export**
|
||||
- Completely FREE (0 credits)
|
||||
- Export slides as PNG images
|
||||
- Export voice files as WAV
|
||||
- Includes transcripts
|
||||
|
||||
## Free Trial
|
||||
|
||||
**New users receive 500 free credits** upon account creation.
|
||||
|
||||
**What you can do with 500 credits:**
|
||||
- Create ~50 Fast PPT slide pages
|
||||
- Create ~5 Nano Banana 2K pages
|
||||
- Create ~2 Nano Banana 2K pages with full narration
|
||||
- Mix and match features as needed
|
||||
|
||||
## Example Cost Calculations
|
||||
|
||||
### Scenario 1: Quick Business Presentation
|
||||
- **Need:** 15-slide Fast PPT presentation
|
||||
- **Credits required:** 150 credits (15 pages × 10 credits)
|
||||
- **Cost with 2,000 package:** $0.38
|
||||
- **Cost with 40,000 package:** $0.30
|
||||
|
||||
### Scenario 2: Branded Marketing Deck
|
||||
- **Need:** 20-slide Nano Banana 2K matching brand image
|
||||
- **Credits required:** 2,000 credits (20 pages × 100 credits)
|
||||
- **Cost with 4,000 package:** $4.75
|
||||
- **Cost with 40,000 package:** $4.00
|
||||
|
||||
### Scenario 3: Training Presentation with Audio
|
||||
- **Need:** 30-slide 2K presentation with voice narration
|
||||
- **Credits required:** 6,300 credits
|
||||
- Slides: 3,000 credits (30 pages × 100 credits)
|
||||
- Narration: 3,300 credits (30 pages × 110 credits - voice only)
|
||||
- **Cost with 10,000 package:** $14.18
|
||||
- **Cost with 40,000 package:** $12.60
|
||||
|
||||
### Scenario 4: High-Resolution Portfolio
|
||||
- **Need:** 10-slide 4K Nano Banana presentation
|
||||
- **Credits required:** 2,000 credits (10 pages × 200 credits)
|
||||
- **Cost with 4,000 package:** $4.75
|
||||
- **Cost with 40,000 package:** $4.00
|
||||
|
||||
### Scenario 5: Complete Package
|
||||
- **Need:** 25-slide 2K presentation with narration, exported as PNG/WAV
|
||||
- **Credits required:** 5,250 credits
|
||||
- Slides: 2,500 credits (25 pages × 100 credits)
|
||||
- Narration: 2,750 credits (25 pages × 110 credits - voice only)
|
||||
- Export: 0 credits (FREE)
|
||||
- **Cost with 10,000 package:** $11.81
|
||||
- **Cost with 40,000 package:** $10.50
|
||||
|
||||
## Payment Methods
|
||||
|
||||
Accepted payment methods via Stripe:
|
||||
- Major credit cards (Visa, Mastercard, American Express, Discover)
|
||||
- Apple Pay
|
||||
- Google Pay
|
||||
|
||||
## Refund Policy
|
||||
|
||||
- **3-day refund window** after purchase
|
||||
- Contact support through https://2slides.com for refund requests
|
||||
- Credits must not have been substantially used
|
||||
|
||||
## Enterprise & Team Plans
|
||||
|
||||
Currently in development. For high-volume or team needs, contact 2slides support through https://2slides.com.
|
||||
|
||||
## Checking Your Credit Balance
|
||||
|
||||
**Via Web:**
|
||||
1. Visit https://2slides.com/api
|
||||
2. Log in to your account
|
||||
3. View your dashboard for current credit balance and usage history
|
||||
|
||||
**Via API:**
|
||||
- Credit balance is returned in API error responses when insufficient
|
||||
- Check account page for detailed usage tracking
|
||||
|
||||
## Credit Expiration
|
||||
|
||||
**Credits NEVER expire.** Purchase credits and use them at your own pace without time pressure.
|
||||
|
||||
## Best Practices for Credit Management
|
||||
|
||||
1. **Start with free credits** - Use your 500 free credits to test features
|
||||
2. **Calculate needs** - Estimate your typical usage before purchasing
|
||||
3. **Buy in bulk** - Larger packages offer better value (up to 20% off)
|
||||
4. **Monitor usage** - Check your dashboard regularly to track consumption
|
||||
5. **Plan ahead** - Buy credits before you need them to take advantage of promotions
|
||||
|
||||
## Rate Limits
|
||||
|
||||
Credit purchases do not affect API rate limits:
|
||||
- Fast PPT: 10 requests per minute
|
||||
- Nano Banana: 6 requests per minute
|
||||
|
||||
Rate limits are based on API tier, not credit balance.
|
||||
|
||||
## Common Questions
|
||||
|
||||
**Q: Do credits expire?**
|
||||
A: No, credits never expire.
|
||||
|
||||
**Q: Can I get a refund?**
|
||||
A: Yes, within 3 days of purchase if credits haven't been substantially used.
|
||||
|
||||
**Q: What happens if I run out of credits?**
|
||||
A: API requests will return an INSUFFICIENT_CREDITS error. Purchase more credits to continue.
|
||||
|
||||
**Q: Can I share credits with my team?**
|
||||
A: Currently, credits are tied to individual API keys. Team plans are in development.
|
||||
|
||||
**Q: Are there discounts for students or nonprofits?**
|
||||
A: Contact 2slides support for special pricing inquiries.
|
||||
|
||||
**Q: How do I know how many credits I have left?**
|
||||
A: Check your dashboard at https://2slides.com/api
|
||||
|
||||
## Resources
|
||||
|
||||
- **Purchase Credits:** https://2slides.com/pricing
|
||||
- **API Dashboard:** https://2slides.com/api
|
||||
- **Main Website:** https://2slides.com
|
||||
- **API Documentation:** See api-reference.md
|
||||
- **Skill Guide:** See SKILL.md
|
||||
|
||||
---
|
||||
|
||||
*Pricing information last updated: 2026-02-10*
|
||||
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
2slides API allowed parameter values. Aligned with https://2slides.com/api.md
|
||||
"""
|
||||
|
||||
API_BASE_URL = "https://2slides.com/api/v1"
|
||||
|
||||
# responseLanguage (all endpoints that accept it)
|
||||
RESPONSE_LANGUAGES = [
|
||||
"Auto",
|
||||
"English",
|
||||
"Spanish",
|
||||
"Arabic",
|
||||
"Portuguese",
|
||||
"Indonesian",
|
||||
"Japanese",
|
||||
"Russian",
|
||||
"Hindi",
|
||||
"French",
|
||||
"German",
|
||||
"Greek",
|
||||
"Vietnamese",
|
||||
"Turkish",
|
||||
"Polish",
|
||||
"Italian",
|
||||
"Korean",
|
||||
"Simplified Chinese",
|
||||
"Traditional Chinese",
|
||||
"Thai",
|
||||
]
|
||||
|
||||
# aspectRatio (create-like-this, create-pdf-slides)
|
||||
ASPECT_RATIOS = [
|
||||
"1:1",
|
||||
"2:3",
|
||||
"3:2",
|
||||
"3:4",
|
||||
"4:3",
|
||||
"4:5",
|
||||
"5:4",
|
||||
"9:16",
|
||||
"16:9",
|
||||
"21:9",
|
||||
]
|
||||
|
||||
# resolution (create-like-this, create-pdf-slides)
|
||||
RESOLUTIONS = ["1K", "2K", "4K"]
|
||||
|
||||
# contentDetail / contentMode
|
||||
CONTENT_DETAILS = ["concise", "standard"]
|
||||
|
||||
# mode (generate, create-like-this, create-pdf-slides)
|
||||
MODES = ["sync", "async"]
|
||||
|
||||
# generate-narration: Supported Voices (30 total, from API doc)
|
||||
NARRATION_VOICES = [
|
||||
"Puck",
|
||||
"Aoede",
|
||||
"Charon",
|
||||
"Kore",
|
||||
"Fenrir",
|
||||
"Zephyr",
|
||||
"Leda",
|
||||
"Orus",
|
||||
"Callirrhoe",
|
||||
"Autonoe",
|
||||
"Enceladus",
|
||||
"Iapetus",
|
||||
"Umbriel",
|
||||
"Algieba",
|
||||
"Despina",
|
||||
"Erinome",
|
||||
"Algenib",
|
||||
"Rasalgethi",
|
||||
"Laomedeia",
|
||||
"Achernar",
|
||||
"Alnilam",
|
||||
"Schedar",
|
||||
"Gacrux",
|
||||
"Pulcherrima",
|
||||
"Achird",
|
||||
"Zubenelgenubi",
|
||||
"Vindemiatrix",
|
||||
"Sadachbia",
|
||||
"Sadaltager",
|
||||
"Sulafat",
|
||||
]
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate custom-designed slides from text using the 2slides API.
|
||||
Similar to create-like-this but without needing a reference image.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
import requests
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
|
||||
API_BASE_URL = "https://2slides.com/api/v1"
|
||||
|
||||
|
||||
def get_api_key() -> str:
|
||||
"""Get API key from environment variable."""
|
||||
api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"API key not found. Set SLIDES_2SLIDES_API_KEY environment variable.\n"
|
||||
"Get your API key from: https://2slides.com/api"
|
||||
)
|
||||
return api_key
|
||||
|
||||
|
||||
def create_pdf_slides(
|
||||
user_input: str,
|
||||
response_language: str = "Auto",
|
||||
aspect_ratio: str = "16:9",
|
||||
resolution: str = "2K",
|
||||
page: int = 1,
|
||||
content_detail: str = "concise",
|
||||
design_spec: Optional[str] = None,
|
||||
api_key: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate custom-designed slides from text with optional design specifications.
|
||||
|
||||
Args:
|
||||
user_input: Content to convert into slides
|
||||
response_language: Language (default: "Auto")
|
||||
Options: Auto, English, Simplified Chinese, Traditional Chinese, Spanish,
|
||||
Arabic, Portuguese, Indonesian, Japanese, Russian, Hindi, French, German,
|
||||
Vietnamese, Turkish, Polish, Italian, Korean
|
||||
aspect_ratio: Aspect ratio in width:height format (default: "16:9")
|
||||
resolution: Output quality - "1K", "2K", or "4K" (default: "2K")
|
||||
page: Number of slides, 0 for auto-detection, max 100 (default: 1)
|
||||
content_detail: "concise" (brief) or "standard" (detailed) (default: "concise")
|
||||
design_spec: Optional design specifications (e.g., "modern minimalist", "corporate blue")
|
||||
api_key: API key (uses env var if not provided)
|
||||
|
||||
Returns:
|
||||
Dict with generation result
|
||||
"""
|
||||
if api_key is None:
|
||||
api_key = get_api_key()
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"userInput": user_input,
|
||||
"responseLanguage": response_language,
|
||||
"aspectRatio": aspect_ratio,
|
||||
"resolution": resolution,
|
||||
"page": page,
|
||||
"contentDetail": content_detail
|
||||
}
|
||||
|
||||
if design_spec:
|
||||
payload["designSpec"] = design_spec
|
||||
|
||||
url = f"{API_BASE_URL}/slides/create-pdf-slides"
|
||||
|
||||
# Calculate dynamic timeout: ~30s per page, minimum 120s
|
||||
timeout = max(120, page * 40)
|
||||
|
||||
print("Generating custom-designed slides...", file=sys.stderr)
|
||||
print(f"(Timeout set to {timeout}s for {page} page(s))", file=sys.stderr)
|
||||
response = requests.post(url, headers=headers, json=payload, timeout=timeout)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
# Handle the actual API response structure
|
||||
if result.get("success") and "data" in result:
|
||||
data = result["data"]
|
||||
# Transform to expected format for consistency
|
||||
normalized_result = {
|
||||
"slideUrl": data.get("jobUrl"),
|
||||
"pdfUrl": data.get("downloadUrl"),
|
||||
"status": "completed" if data.get("status") == "success" else data.get("status"),
|
||||
"message": data.get("message"),
|
||||
"slidePageCount": data.get("slidePageCount"),
|
||||
"jobId": data.get("jobId")
|
||||
}
|
||||
print("✓ Slides generated successfully!", file=sys.stderr)
|
||||
print(f" Pages: {data.get('slidePageCount')}", file=sys.stderr)
|
||||
return normalized_result
|
||||
else:
|
||||
# Fallback to raw result if structure is unexpected
|
||||
print("✓ Request completed!", file=sys.stderr)
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate custom-designed slides using 2slides API",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
# Generate slides with auto design
|
||||
%(prog)s --content "Sales Report Q4 2025"
|
||||
|
||||
# Generate with specific design
|
||||
%(prog)s --content "Marketing Plan" --design-spec "modern minimalist, blue color scheme"
|
||||
|
||||
# Generate in 4K resolution
|
||||
%(prog)s --content "Product Launch" --resolution 4K --page 5
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument("--content", required=True, help="Content for slides")
|
||||
parser.add_argument("--design-spec", help="Optional design specifications")
|
||||
parser.add_argument("--language", default="Auto", help="Response language (default: Auto)")
|
||||
parser.add_argument("--aspect-ratio", default="16:9", help="Aspect ratio in width:height format (default: 16:9)")
|
||||
parser.add_argument("--resolution", choices=["1K", "2K", "4K"], default="2K",
|
||||
help="Output quality (default: 2K)")
|
||||
parser.add_argument("--page", type=int, default=1, help="Number of slides, 0 for auto (default: 1, max: 100)")
|
||||
parser.add_argument("--content-detail", choices=["concise", "standard"], default="concise",
|
||||
help="Content detail level (default: concise)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
result = create_pdf_slides(
|
||||
user_input=args.content,
|
||||
response_language=args.language,
|
||||
aspect_ratio=args.aspect_ratio,
|
||||
resolution=args.resolution,
|
||||
page=args.page,
|
||||
content_detail=args.content_detail,
|
||||
design_spec=args.design_spec
|
||||
)
|
||||
|
||||
print(json.dumps(result, indent=2))
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+157
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Download slides pages as PNG files and voice narrations as WAV files.
|
||||
Exports everything as a ZIP archive (completely free).
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
import requests
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
|
||||
API_BASE_URL = "https://2slides.com/api/v1"
|
||||
|
||||
|
||||
def get_api_key() -> str:
|
||||
"""Get API key from environment variable."""
|
||||
api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"API key not found. Set SLIDES_2SLIDES_API_KEY environment variable.\n"
|
||||
"Get your API key from: https://2slides.com/api"
|
||||
)
|
||||
return api_key
|
||||
|
||||
|
||||
def download_slides_pages_voices(
|
||||
job_id: str,
|
||||
output_path: Optional[str] = None,
|
||||
api_key: Optional[str] = None
|
||||
) -> str:
|
||||
"""
|
||||
Download slides pages and voice narrations as a ZIP archive.
|
||||
|
||||
Args:
|
||||
job_id: Job ID from slide generation
|
||||
output_path: Optional path to save the ZIP file (default: <job_id>.zip)
|
||||
api_key: API key (uses env var if not provided)
|
||||
|
||||
Returns:
|
||||
Path to the downloaded ZIP file
|
||||
|
||||
Notes:
|
||||
- Exports pages as PNG files
|
||||
- Exports voices as WAV files
|
||||
- Includes transcripts
|
||||
- Completely free (no credit cost)
|
||||
- Download URL valid for 1 hour
|
||||
"""
|
||||
if api_key is None:
|
||||
api_key = get_api_key()
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"jobId": job_id
|
||||
}
|
||||
|
||||
url = f"{API_BASE_URL}/slides/download-slides-pages-voices"
|
||||
|
||||
print(f"Requesting download for job: {job_id}...", file=sys.stderr)
|
||||
|
||||
response = requests.post(url, headers=headers, json=payload, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
# Check API response structure
|
||||
if not result.get("success"):
|
||||
error_msg = result.get("error", "Unknown error")
|
||||
raise ValueError(f"API error: {error_msg}")
|
||||
|
||||
# Get download URL from data field
|
||||
data = result.get("data")
|
||||
if not data:
|
||||
raise ValueError("No data in API response")
|
||||
|
||||
download_url = data.get("downloadUrl")
|
||||
if not download_url:
|
||||
raise ValueError("No download URL in response")
|
||||
|
||||
# Optional: log additional info
|
||||
file_name = data.get("fileName", "unknown.zip")
|
||||
expires_in = data.get("expiresIn", 3600)
|
||||
print(f" Filename: {file_name}", file=sys.stderr)
|
||||
print(f" Expires in: {expires_in} seconds", file=sys.stderr)
|
||||
|
||||
# Download the ZIP file
|
||||
if output_path is None:
|
||||
output_path = f"{job_id}.zip"
|
||||
|
||||
print(f"Downloading ZIP archive to: {output_path}...", file=sys.stderr)
|
||||
|
||||
zip_response = requests.get(download_url, stream=True, timeout=120)
|
||||
zip_response.raise_for_status()
|
||||
|
||||
# Save to file
|
||||
with open(output_path, 'wb') as f:
|
||||
for chunk in zip_response.iter_content(chunk_size=8192):
|
||||
f.write(chunk)
|
||||
|
||||
file_size = os.path.getsize(output_path)
|
||||
print(f"✓ Downloaded successfully!", file=sys.stderr)
|
||||
print(f" File: {output_path}", file=sys.stderr)
|
||||
print(f" Size: {file_size:,} bytes", file=sys.stderr)
|
||||
|
||||
return output_path
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Download 2slides pages and voices as ZIP archive (FREE)",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
# Download with default filename
|
||||
%(prog)s --job-id "abc-123-def-456"
|
||||
|
||||
# Download to specific path
|
||||
%(prog)s --job-id "abc-123-def-456" --output slides.zip
|
||||
|
||||
Archive Contents:
|
||||
- Pages as PNG files
|
||||
- Voice files as WAV
|
||||
- Transcripts
|
||||
|
||||
Note: Download URLs are valid for 1 hour only
|
||||
Cost: Completely FREE (no credits used)
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument("--job-id", required=True, help="Job ID from slide generation")
|
||||
parser.add_argument("--output", help="Output ZIP file path (default: <job_id>.zip)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
output_path = download_slides_pages_voices(
|
||||
job_id=args.job_id,
|
||||
output_path=args.output
|
||||
)
|
||||
|
||||
# Output path for easy parsing
|
||||
print(json.dumps({"success": True, "output": output_path}, indent=2))
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate AI voice narration for slides using the 2slides API.
|
||||
Supports single and multi-speaker modes with 30 voice options.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
import requests
|
||||
from typing import Optional, Dict, Any, List
|
||||
|
||||
|
||||
API_BASE_URL = "https://2slides.com/api/v1"
|
||||
|
||||
# Available voice options (30 voices)
|
||||
AVAILABLE_VOICES = [
|
||||
"Puck", "Aoede", "Charon", "Kore", "Fenrir", "Phoebe", "Asteria",
|
||||
"Luna", "Stella", "Theia", "Helios", "Atlas", "Clio", "Melpomene",
|
||||
"Calliope", "Erato", "Euterpe", "Polyhymnia", "Terpsichore", "Thalia",
|
||||
"Urania", "Zeus", "Hera", "Poseidon", "Athena", "Apollo", "Artemis",
|
||||
"Ares", "Aphrodite", "Hephaestus"
|
||||
]
|
||||
|
||||
|
||||
def get_api_key() -> str:
|
||||
"""Get API key from environment variable."""
|
||||
api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"API key not found. Set SLIDES_2SLIDES_API_KEY environment variable.\n"
|
||||
"Get your API key from: https://2slides.com/api"
|
||||
)
|
||||
return api_key
|
||||
|
||||
|
||||
def generate_narration(
|
||||
job_id: str,
|
||||
language: str = "Auto",
|
||||
voice: str = "Puck",
|
||||
multi_speaker: bool = False,
|
||||
api_key: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate AI voice narration for slides.
|
||||
|
||||
Args:
|
||||
job_id: Job ID from slide generation (must be UUID format for Nano Banana)
|
||||
language: Language for narration (default: "Auto")
|
||||
Options: Auto, English, Simplified Chinese, Traditional Chinese, Spanish,
|
||||
Arabic, Portuguese, Indonesian, Japanese, Russian, Hindi, French, German,
|
||||
Vietnamese, Turkish, Polish, Italian, Korean
|
||||
voice: Voice name (default: "Puck")
|
||||
Options: Puck, Aoede, Charon, Kore, Fenrir, Phoebe, Asteria, Luna, Stella,
|
||||
Theia, Helios, Atlas, Clio, Melpomene, Calliope, Erato, Euterpe, Polyhymnia,
|
||||
Terpsichore, Thalia, Urania, Zeus, Hera, Poseidon, Athena, Apollo, Artemis,
|
||||
Ares, Aphrodite, Hephaestus
|
||||
multi_speaker: Enable multi-speaker mode (default: False)
|
||||
api_key: API key (uses env var if not provided)
|
||||
|
||||
Returns:
|
||||
Dict with narration generation result
|
||||
|
||||
Notes:
|
||||
- Job must be completed before adding narration
|
||||
- Cost: 210 credits per page (10 for text, 200 for audio)
|
||||
- Processing time: Varies by slide count
|
||||
"""
|
||||
if api_key is None:
|
||||
api_key = get_api_key()
|
||||
|
||||
if voice not in AVAILABLE_VOICES:
|
||||
print(f"Warning: Voice '{voice}' not in known voices list", file=sys.stderr)
|
||||
print(f"Available voices: {', '.join(AVAILABLE_VOICES)}", file=sys.stderr)
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"jobId": job_id,
|
||||
"language": language,
|
||||
"voice": voice,
|
||||
"multiSpeaker": multi_speaker
|
||||
}
|
||||
|
||||
url = f"{API_BASE_URL}/slides/generate-narration"
|
||||
|
||||
print("Generating voice narration...", file=sys.stderr)
|
||||
print(f"Voice: {voice}, Multi-speaker: {multi_speaker}", file=sys.stderr)
|
||||
|
||||
# Set reasonable timeout for narration generation
|
||||
timeout = 120
|
||||
|
||||
response = requests.post(url, headers=headers, json=payload, timeout=timeout)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
# Check API response structure
|
||||
if not result.get("success"):
|
||||
# Common error example:
|
||||
# {"error":"Job is not completed","code":"JOB_NOT_COMPLETED",...}
|
||||
error_msg = result.get("error", "Unknown error")
|
||||
code = result.get("code")
|
||||
details = result.get("details")
|
||||
extra = f" (code={code})" if code else ""
|
||||
raise ValueError(f"API error: {error_msg}{extra}{f' details={details}' if details else ''}")
|
||||
|
||||
# API may return either:
|
||||
# - { success:true, data:{...} }
|
||||
# - { success:true, jobId:"...", message:"..." } (no data field)
|
||||
data = result.get("data")
|
||||
if not data:
|
||||
data = {
|
||||
"jobId": result.get("jobId") or job_id,
|
||||
"status": result.get("status") or "pending",
|
||||
"message": result.get("message") or "Narration generation started"
|
||||
}
|
||||
|
||||
print("✓ Narration generation started!", file=sys.stderr)
|
||||
print(f" Job ID: {data.get('jobId')}", file=sys.stderr)
|
||||
print("Use get_job_status.py to check progress", file=sys.stderr)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def list_voices():
|
||||
"""Print available voices."""
|
||||
print("Available voices (30 total):")
|
||||
print("-" * 40)
|
||||
for i, voice in enumerate(AVAILABLE_VOICES, 1):
|
||||
print(f"{i:2d}. {voice}")
|
||||
print("-" * 40)
|
||||
print("\nPopular choices: Puck, Aoede, Charon")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate AI voice narration for 2slides presentations",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
# List available voices
|
||||
%(prog)s --list-voices
|
||||
|
||||
# Generate narration with default voice
|
||||
%(prog)s --job-id "abc-123-def-456"
|
||||
|
||||
# Generate with specific voice
|
||||
%(prog)s --job-id "abc-123-def-456" --voice "Aoede"
|
||||
|
||||
# Generate with multi-speaker mode
|
||||
%(prog)s --job-id "abc-123-def-456" --multi-speaker
|
||||
|
||||
# Generate in Spanish
|
||||
%(prog)s --job-id "abc-123-def-456" --language "Spanish" --voice "Charon"
|
||||
|
||||
Credit Cost: 210 credits per page (10 for text, 200 for audio)
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument("--job-id", help="Job ID from slide generation (UUID format)")
|
||||
parser.add_argument("--language", default="Auto", help="Narration language (default: Auto)")
|
||||
parser.add_argument("--voice", default="Puck", help="Voice name (default: Puck)")
|
||||
parser.add_argument("--multi-speaker", action="store_true", help="Enable multi-speaker mode")
|
||||
parser.add_argument("--list-voices", action="store_true", help="List available voices and exit")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.list_voices:
|
||||
list_voices()
|
||||
return
|
||||
|
||||
if not args.job_id:
|
||||
print("Error: --job-id is required (or use --list-voices)", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
result = generate_narration(
|
||||
job_id=args.job_id,
|
||||
language=args.language,
|
||||
voice=args.voice,
|
||||
multi_speaker=args.multi_speaker
|
||||
)
|
||||
|
||||
print(json.dumps(result, indent=2))
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate slides using the 2slides API.
|
||||
Supports both content-based and reference image-based generation.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import argparse
|
||||
import requests
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
|
||||
API_BASE_URL = "https://2slides.com/api/v1"
|
||||
|
||||
|
||||
def get_api_key() -> str:
|
||||
"""Get API key from environment variable."""
|
||||
api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"API key not found. Set SLIDES_2SLIDES_API_KEY environment variable.\n"
|
||||
"Get your API key from: https://2slides.com/api"
|
||||
)
|
||||
return api_key
|
||||
|
||||
|
||||
def generate_slides(
|
||||
user_input: str,
|
||||
theme_id: str,
|
||||
response_language: str = "Auto",
|
||||
mode: str = "sync",
|
||||
api_key: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate slides from user input.
|
||||
|
||||
Args:
|
||||
user_input: Content to convert into slides
|
||||
theme_id: Theme ID (required, use search_themes.py to find themes)
|
||||
response_language: Language (default: "Auto")
|
||||
Options: Auto, English, Simplified Chinese, Traditional Chinese, Spanish,
|
||||
Arabic, Portuguese, Indonesian, Japanese, Russian, Hindi, French, German,
|
||||
Vietnamese, Turkish, Polish, Italian, Korean
|
||||
mode: "sync" or "async" (default: "sync")
|
||||
api_key: API key (uses env var if not provided)
|
||||
|
||||
Returns:
|
||||
Dict with generation result or job ID
|
||||
"""
|
||||
if api_key is None:
|
||||
api_key = get_api_key()
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"userInput": user_input,
|
||||
"themeId": theme_id,
|
||||
"responseLanguage": response_language,
|
||||
"mode": mode
|
||||
}
|
||||
|
||||
url = f"{API_BASE_URL}/slides/generate"
|
||||
|
||||
# Set timeout: 90s for sync (waits for completion), 30s for async (just creates job)
|
||||
timeout = 90 if mode == "sync" else 30
|
||||
|
||||
print(f"Generating slides in {mode} mode...", file=sys.stderr)
|
||||
response = requests.post(url, headers=headers, json=payload, timeout=timeout)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
# Check API response structure
|
||||
if not result.get("success"):
|
||||
error_msg = result.get("error", "Unknown error")
|
||||
raise ValueError(f"API error: {error_msg}")
|
||||
|
||||
# Extract data from response
|
||||
data = result.get("data")
|
||||
if not data:
|
||||
raise ValueError("No data in API response")
|
||||
|
||||
if mode == "sync":
|
||||
print("✓ Slides generated successfully!", file=sys.stderr)
|
||||
print(f" Pages: {data.get('slidePageCount', 'N/A')}", file=sys.stderr)
|
||||
if data.get("downloadUrl"):
|
||||
print(f" Download URL: {data.get('downloadUrl')}", file=sys.stderr)
|
||||
else:
|
||||
print(f"✓ Job created: {data.get('jobId')}", file=sys.stderr)
|
||||
print("Use get_job_status.py to check status", file=sys.stderr)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def create_like_this(
|
||||
user_input: str,
|
||||
reference_image_url: str,
|
||||
response_language: str = "Auto",
|
||||
aspect_ratio: str = "16:9",
|
||||
resolution: str = "2K",
|
||||
page: int = 1,
|
||||
content_detail: str = "concise",
|
||||
api_key: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate slides matching a reference image style (Nano Banana Pro).
|
||||
|
||||
Args:
|
||||
user_input: Content to convert into slides
|
||||
reference_image_url: URL or base64 of reference image to match style
|
||||
response_language: Language (default: "Auto")
|
||||
Options: Auto, English, Simplified Chinese, Traditional Chinese, Spanish,
|
||||
Arabic, Portuguese, Indonesian, Japanese, Russian, Hindi, French, German,
|
||||
Vietnamese, Turkish, Polish, Italian, Korean
|
||||
aspect_ratio: Aspect ratio in width:height format (default: "16:9")
|
||||
resolution: Output quality - "1K", "2K", or "4K" (default: "2K")
|
||||
page: Number of slides, 0 for auto-detection, max 100 (default: 1)
|
||||
content_detail: "concise" (brief, keyword-focused) or "standard" (comprehensive) (default: "concise")
|
||||
api_key: API key (uses env var if not provided)
|
||||
|
||||
Returns:
|
||||
Dict with generation result
|
||||
"""
|
||||
if api_key is None:
|
||||
api_key = get_api_key()
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"userInput": user_input,
|
||||
"referenceImageUrl": reference_image_url,
|
||||
"responseLanguage": response_language,
|
||||
"aspectRatio": aspect_ratio,
|
||||
"resolution": resolution,
|
||||
"page": page,
|
||||
"contentDetail": content_detail
|
||||
}
|
||||
|
||||
url = f"{API_BASE_URL}/slides/create-like-this"
|
||||
|
||||
# Calculate dynamic timeout: ~30s per page, minimum 120s
|
||||
timeout = max(120, page * 40)
|
||||
|
||||
print("Generating slides from reference image...", file=sys.stderr)
|
||||
print(f"(Timeout set to {timeout}s for {page} page(s))", file=sys.stderr)
|
||||
response = requests.post(url, headers=headers, json=payload, timeout=timeout)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
# Handle the actual API response structure
|
||||
if result.get("success") and "data" in result:
|
||||
data = result["data"]
|
||||
# Transform to expected format for consistency
|
||||
normalized_result = {
|
||||
"slideUrl": data.get("jobUrl"),
|
||||
"pdfUrl": data.get("downloadUrl"),
|
||||
"status": "completed" if data.get("status") == "success" else data.get("status"),
|
||||
"message": data.get("message"),
|
||||
"slidePageCount": data.get("slidePageCount"),
|
||||
"jobId": data.get("jobId")
|
||||
}
|
||||
print("✓ Slides generated successfully!", file=sys.stderr)
|
||||
print(f" Pages: {data.get('slidePageCount')}", file=sys.stderr)
|
||||
return normalized_result
|
||||
else:
|
||||
# Fallback to raw result if structure is unexpected
|
||||
print("✓ Request completed!", file=sys.stderr)
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate slides using 2slides API",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
# Generate slides from content
|
||||
%(prog)s --content "Intro to AI: ML, Deep Learning, Neural Networks"
|
||||
|
||||
# Generate with specific theme
|
||||
%(prog)s --content "Business Plan" --theme-id "theme123"
|
||||
|
||||
# Generate in async mode
|
||||
%(prog)s --content "Long presentation" --mode async
|
||||
|
||||
# Generate from reference image
|
||||
%(prog)s --content "Sales Report" --reference-image "https://example.com/image.jpg"
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument("--content", required=True, help="Content for slides")
|
||||
parser.add_argument("--theme-id", help="Theme ID (required for standard generation)")
|
||||
parser.add_argument("--reference-image", help="Reference image URL (use this OR theme-id)")
|
||||
parser.add_argument("--language", default="Auto", help="Response language (default: Auto)")
|
||||
parser.add_argument("--mode", choices=["sync", "async"], default="sync",
|
||||
help="Generation mode (default: sync)")
|
||||
parser.add_argument("--aspect-ratio", default="16:9", help="Aspect ratio in width:height format (default: 16:9)")
|
||||
parser.add_argument("--resolution", choices=["1K", "2K", "4K"], default="2K",
|
||||
help="Output quality (default: 2K)")
|
||||
parser.add_argument("--page", type=int, default=1, help="Number of slides, 0 for auto (default: 1, max: 100)")
|
||||
parser.add_argument("--content-detail", choices=["concise", "standard"], default="concise",
|
||||
help="Content detail level (default: concise)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
if args.reference_image:
|
||||
result = create_like_this(
|
||||
user_input=args.content,
|
||||
reference_image_url=args.reference_image,
|
||||
response_language=args.language,
|
||||
aspect_ratio=args.aspect_ratio,
|
||||
resolution=args.resolution,
|
||||
page=args.page,
|
||||
content_detail=args.content_detail
|
||||
)
|
||||
else:
|
||||
if not args.theme_id:
|
||||
print("Error: --theme-id is required for standard generation", file=sys.stderr)
|
||||
print("Use --reference-image for style-based generation instead", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
result = generate_slides(
|
||||
user_input=args.content,
|
||||
theme_id=args.theme_id,
|
||||
response_language=args.language,
|
||||
mode=args.mode
|
||||
)
|
||||
|
||||
print(json.dumps(result, indent=2))
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Check the status of an async slide generation job.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
import requests
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
|
||||
API_BASE_URL = "https://2slides.com/api/v1"
|
||||
|
||||
|
||||
def get_api_key() -> str:
|
||||
"""Get API key from environment variable."""
|
||||
api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"API key not found. Set SLIDES_2SLIDES_API_KEY environment variable.\n"
|
||||
"Get your API key from: https://2slides.com/api"
|
||||
)
|
||||
return api_key
|
||||
|
||||
|
||||
def get_job_status(
|
||||
job_id: str,
|
||||
api_key: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Get the status of a slide generation job.
|
||||
|
||||
Args:
|
||||
job_id: Job ID from async generation
|
||||
api_key: API key (uses env var if not provided)
|
||||
|
||||
Returns:
|
||||
Dict with job status and result
|
||||
"""
|
||||
if api_key is None:
|
||||
api_key = get_api_key()
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
url = f"{API_BASE_URL}/jobs/{job_id}"
|
||||
|
||||
print(f"Checking job status: {job_id}...", file=sys.stderr)
|
||||
response = requests.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
# Check API response structure
|
||||
if not result.get("success"):
|
||||
error_msg = result.get("error", "Unknown error")
|
||||
raise ValueError(f"API error: {error_msg}")
|
||||
|
||||
# Extract data from response
|
||||
data = result.get("data")
|
||||
if not data:
|
||||
raise ValueError("No data in API response")
|
||||
|
||||
status = data.get("status", "unknown")
|
||||
|
||||
print(f"✓ Job status: {status}", file=sys.stderr)
|
||||
if data.get("message"):
|
||||
print(f" Message: {data.get('message')}", file=sys.stderr)
|
||||
if data.get("slidePageCount"):
|
||||
print(f" Pages: {data.get('slidePageCount')}", file=sys.stderr)
|
||||
if data.get("downloadUrl"):
|
||||
print(f" Download URL: {data.get('downloadUrl')}", file=sys.stderr)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Check 2slides job status",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
# Check job status
|
||||
%(prog)s --job-id abc123
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument("--job-id", required=True, help="Job ID to check")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
result = get_job_status(job_id=args.job_id)
|
||||
print(json.dumps(result, indent=2))
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Search for available themes in the 2slides catalog.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
import requests
|
||||
from typing import Optional, List, Dict, Any
|
||||
|
||||
|
||||
API_BASE_URL = "https://2slides.com/api/v1"
|
||||
|
||||
|
||||
def get_api_key() -> str:
|
||||
"""Get API key from environment variable."""
|
||||
api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"API key not found. Set SLIDES_2SLIDES_API_KEY environment variable.\n"
|
||||
"Get your API key from: https://2slides.com/api"
|
||||
)
|
||||
return api_key
|
||||
|
||||
|
||||
def search_themes(
|
||||
query: str,
|
||||
limit: int = 20,
|
||||
api_key: Optional[str] = None
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Search for themes.
|
||||
|
||||
Args:
|
||||
query: Search query (required keyword)
|
||||
limit: Maximum number of results (max 100, default 20)
|
||||
api_key: API key (uses env var if not provided)
|
||||
|
||||
Returns:
|
||||
List of theme objects
|
||||
"""
|
||||
if api_key is None:
|
||||
api_key = get_api_key()
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
params = {
|
||||
"query": query,
|
||||
"limit": min(limit, 100)
|
||||
}
|
||||
|
||||
url = f"{API_BASE_URL}/themes/search"
|
||||
|
||||
print(f"Searching themes{f': {query}' if query else ''}...", file=sys.stderr)
|
||||
response = requests.get(url, headers=headers, params=params)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
# Check API response structure
|
||||
if not result.get("success"):
|
||||
error_msg = result.get("error", "Unknown error")
|
||||
raise ValueError(f"API error: {error_msg}")
|
||||
|
||||
# Extract data from response
|
||||
data = result.get("data")
|
||||
if not data:
|
||||
raise ValueError("No data in API response")
|
||||
|
||||
themes = data.get("themes", [])
|
||||
|
||||
print(f"✓ Found {len(themes)} theme(s)", file=sys.stderr)
|
||||
|
||||
return themes
|
||||
|
||||
|
||||
def format_theme(theme: Dict[str, Any]) -> str:
|
||||
"""Format a theme object for display."""
|
||||
theme_id = theme.get("id", "N/A")
|
||||
name = theme.get("name", "Unnamed")
|
||||
description = theme.get("description", "No description")
|
||||
|
||||
return f"ID: {theme_id}\nName: {name}\nDescription: {description}\n"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Search for 2slides themes",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
# Search for business themes
|
||||
%(prog)s --query "business"
|
||||
|
||||
# Search for creative themes
|
||||
%(prog)s --query "creative"
|
||||
|
||||
# Get more results
|
||||
%(prog)s --query "professional" --limit 50
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument("--query", required=True, help="Search query (required keyword)")
|
||||
parser.add_argument("--limit", type=int, default=20,
|
||||
help="Maximum results (max 100, default 20)")
|
||||
parser.add_argument("--json", action="store_true",
|
||||
help="Output raw JSON")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
themes = search_themes(
|
||||
query=args.query,
|
||||
limit=args.limit
|
||||
)
|
||||
|
||||
if args.json:
|
||||
print(json.dumps(themes, indent=2))
|
||||
else:
|
||||
print()
|
||||
for i, theme in enumerate(themes, 1):
|
||||
print(f"Theme {i}:")
|
||||
print(format_theme(theme))
|
||||
print("-" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user