Skillshub assemblyai-deploy-integration
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/jeremylongshore/claude-code-plugins-plus-skills/assemblyai-deploy-integration" ~/.claude/skills/comeonoliver-skillshub-assemblyai-deploy-integration && rm -rf "$T"
manifest:
skills/jeremylongshore/claude-code-plugins-plus-skills/assemblyai-deploy-integration/SKILL.mdsource content
AssemblyAI Deploy Integration
Overview
Deploy AssemblyAI-powered transcription services to Vercel (serverless), Google Cloud Run (containers), and Fly.io with proper secrets management and webhook configuration.
Prerequisites
- AssemblyAI API key for production
- Platform CLI installed (
,vercel
, orgcloud
)fly - Application with working AssemblyAI integration
Instructions
Vercel Deployment (Serverless)
# Add secrets vercel env add ASSEMBLYAI_API_KEY production vercel env add ASSEMBLYAI_WEBHOOK_SECRET production # Deploy vercel --prod
API Route for Transcription:
// app/api/transcribe/route.ts (Next.js App Router) import { AssemblyAI } from 'assemblyai'; import { NextRequest, NextResponse } from 'next/server'; const client = new AssemblyAI({ apiKey: process.env.ASSEMBLYAI_API_KEY!, }); export async function POST(req: NextRequest) { const { audioUrl, features } = await req.json(); if (!audioUrl) { return NextResponse.json({ error: 'audioUrl required' }, { status: 400 }); } // Use submit() + webhook for production (non-blocking) const transcript = await client.transcripts.submit({ audio: audioUrl, webhook_url: `${process.env.NEXT_PUBLIC_APP_URL}/api/webhooks/assemblyai`, webhook_auth_header_name: 'X-Webhook-Secret', webhook_auth_header_value: process.env.ASSEMBLYAI_WEBHOOK_SECRET!, speaker_labels: features?.speakerLabels ?? false, sentiment_analysis: features?.sentiment ?? false, }); return NextResponse.json({ transcriptId: transcript.id, status: transcript.status, }); }
Webhook Handler:
// app/api/webhooks/assemblyai/route.ts import { AssemblyAI } from 'assemblyai'; import { NextRequest, NextResponse } from 'next/server'; const client = new AssemblyAI({ apiKey: process.env.ASSEMBLYAI_API_KEY!, }); export async function POST(req: NextRequest) { // Verify webhook authenticity const secret = req.headers.get('x-webhook-secret'); if (secret !== process.env.ASSEMBLYAI_WEBHOOK_SECRET) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { transcript_id, status } = await req.json(); if (status === 'completed') { const transcript = await client.transcripts.get(transcript_id); // Store transcript, notify user, trigger downstream processing console.log(`Transcript ${transcript_id} completed: ${transcript.text?.length} chars`); } else if (status === 'error') { console.error(`Transcript ${transcript_id} failed`); } return NextResponse.json({ received: true }); }
Vercel config:
{ "functions": { "app/api/transcribe/route.ts": { "maxDuration": 60 }, "app/api/webhooks/assemblyai/route.ts": { "maxDuration": 10 } } }
Google Cloud Run Deployment
FROM node:20-slim WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 8080 CMD ["node", "dist/server.js"]
# Store secret in Secret Manager echo -n "your-api-key" | gcloud secrets create assemblyai-api-key --data-file=- # Build and deploy gcloud builds submit --tag gcr.io/$PROJECT_ID/assemblyai-service gcloud run deploy assemblyai-service \ --image gcr.io/$PROJECT_ID/assemblyai-service \ --region us-central1 \ --platform managed \ --set-secrets=ASSEMBLYAI_API_KEY=assemblyai-api-key:latest \ --allow-unauthenticated \ --memory 512Mi \ --timeout 300
Fly.io Deployment
# fly.toml app = "my-assemblyai-app" primary_region = "iad" [env] NODE_ENV = "production" PORT = "3000" [http_service] internal_port = 3000 force_https = true auto_stop_machines = true auto_start_machines = true min_machines_running = 1
fly secrets set ASSEMBLYAI_API_KEY=your-api-key fly secrets set ASSEMBLYAI_WEBHOOK_SECRET=your-webhook-secret fly deploy
Streaming Token Endpoint (All Platforms)
// Endpoint to generate temporary tokens for browser streaming // Works on any platform — the key is to never expose your API key to the client import { AssemblyAI } from 'assemblyai'; const client = new AssemblyAI({ apiKey: process.env.ASSEMBLYAI_API_KEY!, }); export async function GET() { const token = await client.streaming.createTemporaryToken({ expires_in_seconds: 300, }); return Response.json({ token }); }
Health Check (Platform-Agnostic)
import { AssemblyAI } from 'assemblyai'; const client = new AssemblyAI({ apiKey: process.env.ASSEMBLYAI_API_KEY!, }); export async function GET() { const start = Date.now(); try { await client.transcripts.list({ limit: 1 }); return Response.json({ status: 'healthy', assemblyai: { connected: true, latencyMs: Date.now() - start }, timestamp: new Date().toISOString(), }); } catch { return Response.json({ status: 'degraded', assemblyai: { connected: false, latencyMs: Date.now() - start }, timestamp: new Date().toISOString(), }, { status: 503 }); } }
Output
- Application deployed with AssemblyAI secrets securely configured
- Webhook endpoint for async transcription notifications
- Streaming token endpoint for browser clients
- Health check endpoint monitoring AssemblyAI connectivity
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Secret not available at runtime | Wrong env name or missing secret | Verify with platform CLI |
| Webhook not receiving events | URL not publicly accessible | Verify URL, check firewall/CORS |
| Function timeout (Vercel) | takes too long | Use + webhook pattern |
| Cold start latency | Serverless spin-up | Set minimum instances or use |
Resources
Next Steps
For webhook handling, see
assemblyai-webhooks-events.