158 lines
4.3 KiB
Python
Executable File
158 lines
4.3 KiB
Python
Executable File
#!/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()
|