diff --git a/.wave/repo.json b/.wave/repo.json index cd26dbe..98d108d 100644 --- a/.wave/repo.json +++ b/.wave/repo.json @@ -5,42 +5,220 @@ "purpose": "Official TypeScript SDK for the WAVE API — 42 API module subpaths covering streaming, production, device management, analytics, content, and monetization behind a single `Wave` client. Most modules are SDK-side TypeScript surface only; see capability statuses for what has a live fleet backend today.", "visibility": "public", "primaryLanguage": "TypeScript", - "topics": ["sdk", "typescript", "streaming", "video", "audio", "production", "webrtc", "ndi", "srt", "clips", "voice", "transcription", "captions", "analytics"], + "topics": [ + "sdk", + "typescript", + "streaming", + "video", + "audio", + "production", + "webrtc", + "ndi", + "srt", + "clips", + "voice", + "transcription", + "captions", + "analytics" + ], "capabilities": [ - { "id": "pipeline", "does": "Live stream lifecycle, protocols, recordings, viewer metrics via `wave.pipeline`", "status": "lib" }, - { "id": "clips", "does": "Video clips, exports, AI highlights via `wave.clips`", "status": "lib" }, - { "id": "editor", "does": "Video editing, tracks, transitions, effects via `wave.editor`", "status": "lib" }, - { "id": "voice", "does": "Text-to-speech via `wave.voice.synthesize()`; voice-clone methods exist as SDK client surface but are not backed by the wave-voice product yet", "status": "lib" }, - { "id": "transcribe", "does": "Transcription with speaker diarization via `wave.transcribe`", "status": "lib" }, - { "id": "captions", "does": "Auto-captions, translation, burn-in via `wave.captions`", "status": "lib" }, - { "id": "studio", "does": "Multi-camera production, scenes, transitions, graphics, audio mixing via `wave.studio` (SDK TypeScript surface; no fleet backend yet)", "status": "planned" }, - { "id": "prism", "does": "Virtual Device Bridge (NDI/ONVIF/VISCA/Dante to USB UVC/UAC) via `wave.prism` (SDK TypeScript surface; no fleet backend yet)", "status": "planned" }, - { "id": "fleet", "does": "Desktop Node fleet management, health, commands via `wave.fleet` (SDK TypeScript surface; no fleet backend yet)", "status": "planned" }, - { "id": "ghost", "does": "AI auto-directing (Autopilot), suggestions, overrides via `wave.ghost` (SDK TypeScript surface; no fleet backend yet)", "status": "planned" }, - { "id": "mesh", "does": "Multi-region failover, replication, topology via `wave.mesh` (SDK TypeScript surface; no fleet backend yet)", "status": "planned" }, - { "id": "pulse", "does": "Analytics, BI dashboards, revenue metrics via `wave.pulse` (SDK TypeScript surface; no fleet backend yet)", "status": "planned" }, - { "id": "vault", "does": "Recording storage, VOD, archive policies via `wave.vault` (SDK TypeScript surface; no fleet backend yet)", "status": "planned" }, - { "id": "creator", "does": "Monetization, subscriptions, tips, payouts via `wave.creator` (SDK TypeScript surface; no fleet backend yet)", "status": "planned" }, - { "id": "phone", "does": "Telephony bridging via `wave.phone` — core features are planned in the fleet SSOT, not yet shipped", "status": "planned" }, - { "id": "podcast", "does": "Podcast publishing/distribution via `wave.podcast` — core features are planned in the fleet SSOT, not yet shipped", "status": "planned" }, - { "id": "wave-dispatch", "does": "Agent routing (route/pool) and an OpenAI-compatible proxy for LLM/agent traffic, shipped at the WAVE gateway; reachable from the SDK today via the base `WaveClient` request methods (no dedicated wrapper module yet)", "status": "ga" }, - { "id": "gateway-agent-payments", "does": "x402 and MPP card-rail agent payments with scope-gate and settlement-guard, shipped at the WAVE gateway; reachable from the SDK today via the base `WaveClient` request methods (no dedicated wrapper module yet)", "status": "ga" } + { + "id": "pipeline", + "does": "Live stream lifecycle, protocols, recordings, viewer metrics via `wave.pipeline`", + "status": "lib" + }, + { + "id": "clips", + "does": "Video clips, exports, AI highlights via `wave.clips`", + "status": "lib" + }, + { + "id": "editor", + "does": "Video editing, tracks, transitions, effects via `wave.editor`", + "status": "lib" + }, + { + "id": "voice", + "does": "Text-to-speech via `wave.voice.synthesize()`; voice-clone methods exist as SDK client surface but are not backed by the wave-voice product yet", + "status": "lib" + }, + { + "id": "transcribe", + "does": "Transcription with speaker diarization via `wave.transcribe`", + "status": "lib" + }, + { + "id": "captions", + "does": "Auto-captions, translation, burn-in via `wave.captions`", + "status": "lib" + }, + { + "id": "studio", + "does": "Multi-camera production, scenes, transitions, graphics, audio mixing via `wave.studio` (SDK TypeScript surface; no fleet backend yet)", + "status": "planned" + }, + { + "id": "prism", + "does": "Virtual Device Bridge (NDI/ONVIF/VISCA/Dante to USB UVC/UAC) via `wave.prism` (SDK TypeScript surface; no fleet backend yet)", + "status": "planned" + }, + { + "id": "fleet", + "does": "Desktop Node fleet management, health, commands via `wave.fleet` (SDK TypeScript surface; no fleet backend yet)", + "status": "planned" + }, + { + "id": "ghost", + "does": "AI auto-directing (Autopilot), suggestions, overrides via `wave.ghost` (SDK TypeScript surface; no fleet backend yet)", + "status": "planned" + }, + { + "id": "mesh", + "does": "Multi-region failover, replication, topology via `wave.mesh` (SDK TypeScript surface; no fleet backend yet)", + "status": "planned" + }, + { + "id": "pulse", + "does": "Analytics, BI dashboards, revenue metrics via `wave.pulse` (SDK TypeScript surface; no fleet backend yet)", + "status": "planned" + }, + { + "id": "vault", + "does": "Recording storage, VOD, archive policies via `wave.vault` (SDK TypeScript surface; no fleet backend yet)", + "status": "planned" + }, + { + "id": "creator", + "does": "Monetization, subscriptions, tips, payouts via `wave.creator` (SDK TypeScript surface; no fleet backend yet)", + "status": "planned" + }, + { + "id": "phone", + "does": "Telephony bridging via `wave.phone` — core features are planned in the fleet SSOT, not yet shipped", + "status": "planned" + }, + { + "id": "podcast", + "does": "Podcast publishing/distribution via `wave.podcast` — core features are planned in the fleet SSOT, not yet shipped", + "status": "planned" + }, + { + "id": "wave-dispatch", + "does": "Agent routing (route/pool) and an OpenAI-compatible proxy for LLM/agent traffic, shipped at the WAVE gateway; reachable from the SDK today via the base `WaveClient` request methods (no dedicated wrapper module yet)", + "status": "ga" + }, + { + "id": "gateway-agent-payments", + "does": "x402 and MPP card-rail agent payments with scope-gate and settlement-guard, shipped at the WAVE gateway; reachable from the SDK today via the base `WaveClient` request methods (no dedicated wrapper module yet)", + "status": "ga" + } ], "claims": [ - { "id": "package-name", "text": "The npm package is published as @wave-av/sdk", "resolver": { "type": "grep", "target": "package.json", "expect": "\"name\": \"@wave-av/sdk\"" } }, - { "id": "package-version", "text": "Current package.json version is 2.1.0-next.0", "resolver": { "type": "grep", "target": "package.json", "expect": "\"version\": \"2.1.0-next.0\"" } }, - { "id": "module-count", "text": "42 independently-importable API module subpaths are declared under package.json exports, plus the package root", "resolver": { "type": "grep", "target": "package.json", "expect": "\"./realtime\":" } }, - { "id": "wave-client-class", "text": "A single `Wave` client class in src/index.ts composes every API module as a readonly property", "resolver": { "type": "grep", "target": "src/index.ts", "expect": "export class Wave" } }, - { "id": "subpath-exports", "text": "Each API module is independently importable via a package.json subpath export (e.g. @wave-av/sdk/pipeline)", "resolver": { "type": "grep", "target": "package.json", "expect": "\"./pipeline\":" } }, - { "id": "base-client-generic-request", "text": "The base WaveClient exposes a generic protected request() method that any endpoint — including gateway/dispatch routes without a dedicated wrapper module — can be reached through", "resolver": { "type": "grep", "target": "src/client.ts", "expect": "protected async request" } }, - { "id": "voice-tts-not-cloning", "text": "wave.voice.synthesize() implements text-to-speech; the SDK also declares cloneVoice() client methods that are not backed by the wave-voice product", "resolver": { "type": "grep", "target": "src/voice.ts", "expect": "async synthesize(" } }, - { "id": "docs-surface", "text": "Documentation surface is docs.wave.online", "resolver": { "type": "grep", "target": "package.json", "expect": "\"homepage\": \"https://docs.wave.online/sdk\"" } }, - { "id": "license", "text": "Licensed Apache-2.0", "resolver": { "type": "grep", "target": "package.json", "expect": "\"license\": \"Apache-2.0\"" } }, - { "id": "node-engine", "text": "Requires Node.js >=18.0.0", "resolver": { "type": "grep", "target": "package.json", "expect": "\"node\": \">=18.0.0\"" } }, - { "id": "zod-peer", "text": "Takes zod ^3.22.0 as a peer dependency for runtime validation", "resolver": { "type": "grep", "target": "package.json", "expect": "\"zod\": \"^3.22.0\"" } } + { + "id": "package-name", + "text": "The npm package is published as @wave-av/sdk", + "resolver": { + "type": "grep", + "target": "package.json", + "expect": "\"name\": \"@wave-av/sdk\"" + } + }, + { + "id": "package-version", + "text": "Current package.json version is 2.1.0-next.0", + "resolver": { + "type": "grep", + "target": "package.json", + "expect": "\"version\": \"2.1.0-next.0\"" + } + }, + { + "id": "module-count", + "text": "42 independently-importable API module subpaths are declared under package.json exports, plus the package root", + "resolver": { + "type": "grep", + "target": "package.json", + "expect": "\"./realtime\":" + } + }, + { + "id": "wave-client-class", + "text": "A single `Wave` client class in src/index.ts composes every API module as a readonly property", + "resolver": { + "type": "grep", + "target": "src/index.ts", + "expect": "export class Wave" + } + }, + { + "id": "subpath-exports", + "text": "Each API module is independently importable via a package.json subpath export (e.g. @wave-av/sdk/pipeline)", + "resolver": { + "type": "grep", + "target": "package.json", + "expect": "\"./pipeline\":" + } + }, + { + "id": "base-client-generic-request", + "text": "The base WaveClient exposes a generic protected request() method that any endpoint — including gateway/dispatch routes without a dedicated wrapper module — can be reached through", + "resolver": { + "type": "grep", + "target": "src/client.ts", + "expect": "protected async request" + } + }, + { + "id": "voice-tts-not-cloning", + "text": "wave.voice.synthesize() implements text-to-speech; the SDK also declares cloneVoice() client methods that are not backed by the wave-voice product", + "resolver": { + "type": "grep", + "target": "src/voice.ts", + "expect": "async synthesize(" + } + }, + { + "id": "docs-surface", + "text": "Documentation surface is docs.wave.online", + "resolver": { + "type": "grep", + "target": "package.json", + "expect": "\"homepage\": \"https://docs.wave.online/sdk\"" + } + }, + { + "id": "license", + "text": "Licensed Apache-2.0", + "resolver": { + "type": "grep", + "target": "package.json", + "expect": "\"license\": \"Apache-2.0\"" + } + }, + { + "id": "node-engine", + "text": "Requires Node.js >=18.0.0", + "resolver": { + "type": "grep", + "target": "package.json", + "expect": "\"node\": \">=18.0.0\"" + } + }, + { + "id": "zod-peer", + "text": "Takes zod ^3.22.0 as a peer dependency for runtime validation", + "resolver": { + "type": "grep", + "target": "package.json", + "expect": "\"zod\": \"^3.22.0\"" + } + } ], "install": [ - { "manager": "npm", "cmd": "npm install @wave-av/sdk" } + { + "manager": "npm", + "cmd": "npm install @wave-av/sdk" + } ], "quickstart": { "lang": "ts", @@ -50,5 +228,426 @@ "docs": "https://docs.wave.online/sdk", "npm": "https://www.npmjs.com/package/@wave-av/sdk", "repo": "https://github.com/wave-av/sdk" - } + }, + "sections": [ + { + "kind": "table", + "heading": "API modules — Core streaming", + "columns": [ + "API", + "Access", + "Status", + "Description" + ], + "rows": [ + [ + "`wave.pipeline`", + "`PipelineAPI`", + "lib", + "Live stream lifecycle, protocols, recordings, viewer metrics" + ], + [ + "`wave.studio`", + "`StudioAPI`", + "planned", + "Multi-camera production, scenes, transitions, graphics, audio mixing" + ] + ] + }, + { + "kind": "table", + "heading": "API modules — Enterprise", + "columns": [ + "API", + "Access", + "Status", + "Description" + ], + "rows": [ + [ + "`wave.fleet`", + "`FleetAPI`", + "planned", + "Desktop Node fleet management, health, commands" + ], + [ + "`wave.ghost`", + "`GhostAPI`", + "planned", + "AI auto-directing (Autopilot), suggestions, overrides" + ], + [ + "`wave.mesh`", + "`MeshAPI`", + "planned", + "Multi-region failover, replication, topology" + ], + [ + "`wave.edge`", + "`EdgeAPI`", + "sdk-surface", + "CDN, edge workers, cache, routing rules" + ], + [ + "`wave.pulse`", + "`PulseAPI`", + "planned", + "Analytics, BI dashboards, revenue metrics" + ], + [ + "`wave.prism`", + "`PrismAPI`", + "planned", + "Virtual Device Bridge (NDI/ONVIF/VISCA/Dante to USB UVC/UAC)" + ], + [ + "`wave.zoom`", + "`ZoomAPI`", + "sdk-surface", + "Zoom meetings, rooms, recordings, RTMS" + ] + ] + }, + { + "kind": "table", + "heading": "API modules — Content & commerce", + "columns": [ + "API", + "Access", + "Status", + "Description" + ], + "rows": [ + [ + "`wave.clips`", + "`ClipsAPI`", + "lib", + "Video clips, exports, AI highlights" + ], + [ + "`wave.editor`", + "`EditorAPI`", + "lib", + "Video editing, tracks, transitions, effects" + ], + [ + "`wave.voice`", + "`VoiceAPI`", + "lib", + "Text-to-speech via `synthesize()`; voice-clone methods are SDK surface only" + ], + [ + "`wave.phone`", + "`PhoneAPI`", + "planned", + "Voice calling, conferences, numbers" + ], + [ + "`wave.collab`", + "`CollabAPI`", + "sdk-surface", + "Real-time collaboration rooms" + ], + [ + "`wave.captions`", + "`CaptionsAPI`", + "lib", + "Auto-captions, translation, burn-in" + ], + [ + "`wave.chapters`", + "`ChaptersAPI`", + "sdk-surface", + "Video chapters and markers" + ], + [ + "`wave.studioAI`", + "`StudioAIAPI`", + "sdk-surface", + "AI production assistant, suggestions" + ], + [ + "`wave.transcribe`", + "`TranscribeAPI`", + "lib", + "Transcription with speaker diarization" + ], + [ + "`wave.sentiment`", + "`SentimentAPI`", + "sdk-surface", + "Sentiment and emotion analysis" + ], + [ + "`wave.search`", + "`SearchAPI`", + "sdk-surface", + "Full-text, visual, and audio search" + ], + [ + "`wave.scene`", + "`SceneAPI`", + "sdk-surface", + "AI scene detection and shot classification" + ], + [ + "`wave.vault`", + "`VaultAPI`", + "planned", + "Recording storage, VOD, archive policies" + ], + [ + "`wave.marketplace`", + "`MarketplaceAPI`", + "sdk-surface", + "Templates, plugins, graphics marketplace" + ], + [ + "`wave.connect`", + "`ConnectAPI`", + "sdk-surface", + "Third-party integrations, webhooks" + ], + [ + "`wave.distribution`", + "`DistributionAPI`", + "sdk-surface", + "Social simulcasting, scheduled posts" + ], + [ + "`wave.desktop`", + "`DesktopAPI`", + "sdk-surface", + "Desktop Node app management" + ], + [ + "`wave.signage`", + "`SignageAPI`", + "sdk-surface", + "Digital signage displays, playlists" + ], + [ + "`wave.qr`", + "`QrAPI`", + "sdk-surface", + "Dynamic QR codes, analytics" + ], + [ + "`wave.audience`", + "`AudienceAPI`", + "sdk-surface", + "Polls, Q&A, reactions, engagement" + ], + [ + "`wave.creator`", + "`CreatorAPI`", + "planned", + "Monetization, subscriptions, tips, payouts" + ] + ] + }, + { + "kind": "table", + "heading": "API modules — Specialized", + "columns": [ + "API", + "Access", + "Status", + "Description" + ], + "rows": [ + [ + "`wave.podcast`", + "`PodcastAPI`", + "planned", + "Podcast episodes, RSS, distribution" + ], + [ + "`wave.slides`", + "`SlidesAPI`", + "sdk-surface", + "Presentation-to-video conversion" + ], + [ + "`wave.usb`", + "`UsbAPI`", + "sdk-surface", + "USB device relay and management" + ] + ] + }, + { + "kind": "table", + "heading": "API modules — Platform", + "columns": [ + "API", + "Access", + "Status", + "Description" + ], + "rows": [ + [ + "`wave.drm`", + "`DrmAPI`", + "sdk-surface", + "Digital Rights Management: content protection with Widevine, FairPlay, and PlayReady" + ], + [ + "`wave.notifications`", + "`NotificationsAPI`", + "sdk-surface", + "User notification preferences, delivery channels, and notification management" + ], + [ + "`wave.perception`", + "`PerceptionAPI`", + "sdk-surface", + "Agentic live-media perception: one `subscribe()` verb attaches an agent to any live stream" + ], + [ + "`wave.realtime`", + "`RealtimeAPI`", + "sdk-surface", + "Control & event plane: presence, pub/sub broadcast, and the streaming-event bus" + ] + ] + }, + { + "kind": "prose", + "heading": "What the Status column means", + "body": "`lib` — the TypeScript client surface exists AND a live fleet backend serves it today. `planned` — the client surface exists, the backend does not yet; calling it will not work against production. `sdk-surface` — the client module is exported and typed, but this repo's SSOT declares no backend status for it, so treat it as unproven. Statuses come from `.wave/repo.json`, the same file this README is generated from." + }, + { + "kind": "code", + "heading": "Product example — Streams (Pipeline)", + "lang": "typescript", + "body": "import { Wave } from \"@wave-av/sdk\";\n\nconst wave = new Wave({ apiKey: process.env.WAVE_API_KEY! });\n\nconst stream = await wave.pipeline.create({\n title: \"My Live Stream\",\n protocol: \"webrtc\",\n recording_enabled: true,\n});\nawait wave.pipeline.start(stream.id);\nconst live = await wave.pipeline.waitForLive(stream.id);\nconsole.log(`Playback: ${live.playback_url}`);\nawait wave.pipeline.stop(stream.id);" + }, + { + "kind": "code", + "heading": "Product example — Clips", + "lang": "typescript", + "body": "import { Wave } from \"@wave-av/sdk\";\n\nconst wave = new Wave({ apiKey: process.env.WAVE_API_KEY! });\n\nconst clip = await wave.clips.create({\n title: \"Best Moment\",\n source: { type: \"stream\", id: \"stream_123\", start_time: 120, end_time: 150 },\n});\nconst ready = await wave.clips.waitForReady(clip.id);\nconsole.log(`Clip URL: ${ready.playback_url}`);" + }, + { + "kind": "code", + "heading": "Product example — Captions", + "lang": "typescript", + "body": "import { Wave } from \"@wave-av/sdk\";\n\nconst wave = new Wave({ apiKey: process.env.WAVE_API_KEY! });\n\nconst track = await wave.captions.generate({\n media_id: \"video_123\",\n media_type: \"video\",\n language: \"en\",\n speaker_diarization: true,\n});\nconst ready = await wave.captions.waitForReady(track.id);\nawait wave.captions.translate(ready.id, { target_language: \"es\" });" + }, + { + "kind": "code", + "heading": "Product example — Voice", + "lang": "typescript", + "body": "import { Wave } from \"@wave-av/sdk\";\n\nconst wave = new Wave({ apiKey: process.env.WAVE_API_KEY! });\n\nconst voices = await wave.voice.listVoices({ language: \"en\" });\nconst result = await wave.voice.synthesize({\n text: \"Welcome to WAVE live streaming.\",\n voice_id: voices.data[0].id,\n format: \"mp3\",\n});\nconst audio = await wave.voice.waitForSynthesis(result.id);\nconsole.log(`Audio: ${audio.audio_url}`);" + }, + { + "kind": "code", + "heading": "Product example — Transcription", + "lang": "typescript", + "body": "import { Wave } from \"@wave-av/sdk\";\n\nconst wave = new Wave({ apiKey: process.env.WAVE_API_KEY! });\n\nconst job = await wave.transcribe.create({\n source_type: \"recording\",\n source_id: \"rec_456\",\n language: \"en\",\n speaker_diarization: true,\n});\nconst result = await wave.transcribe.waitForReady(job.id);\nconst text = await wave.transcribe.getText(result.id, { include_speakers: true });\nconsole.log(text);" + }, + { + "kind": "code", + "heading": "Product example — Editor", + "lang": "typescript", + "body": "import { Wave } from \"@wave-av/sdk\";\n\nconst wave = new Wave({ apiKey: process.env.WAVE_API_KEY! });\n\nconst project = await wave.editor.createProject({\n name: \"Highlight Reel\",\n width: 1920,\n height: 1080,\n frame_rate: 30,\n});\nconst track = await wave.editor.addTrack(project.id, { name: \"Main\", type: \"video\" });\nawait wave.editor.addElement(project.id, {\n track_id: track.id,\n type: \"clip\",\n source_id: \"clip_789\",\n start_time: 0,\n});\nconst job = await wave.editor.render(project.id, { format: \"mp4\", quality: \"high\" });\nconst rendered = await wave.editor.waitForRender(project.id, job.id);\nconsole.log(`Output: ${rendered.output_url}`);" + }, + { + "kind": "code", + "heading": "Configuration", + "lang": "typescript", + "body": "const wave = new Wave({\n apiKey: \"your-api-key\", // Required\n organizationId: \"org_123\", // Multi-tenant isolation\n baseUrl: \"https://api.wave.online\", // Default\n timeout: 30000, // Request timeout (ms)\n maxRetries: 3, // Retry attempts\n debug: false, // Debug logging\n});" + }, + { + "kind": "code", + "heading": "Individual API imports", + "lang": "typescript", + "body": "import { WaveClient, PipelineAPI, PrismAPI } from \"@wave-av/sdk\";\n\nconst client = new WaveClient({ apiKey: \"key\" });\nconst pipeline = new PipelineAPI(client);\nconst prism = new PrismAPI(client);" + }, + { + "kind": "code", + "heading": "Error handling", + "lang": "typescript", + "body": "import { WaveError, RateLimitError } from \"@wave-av/sdk\";\n\ntry {\n await wave.pipeline.get(\"invalid-id\");\n} catch (error) {\n if (error instanceof RateLimitError) {\n console.log(`Rate limited. Retry after ${error.retryAfter}ms`);\n } else if (error instanceof WaveError) {\n console.log(`${error.code}: ${error.message} (${error.statusCode})`);\n }\n}" + }, + { + "kind": "code", + "heading": "Events", + "lang": "typescript", + "body": "wave.client.on(\"request.start\", (url, method) => {\n console.log(`${method} ${url}`);\n});\n\nwave.client.on(\"rate_limit.hit\", (retryAfter) => {\n console.log(`Rate limited. Waiting ${retryAfter}ms`);\n});" + }, + { + "kind": "prose", + "heading": "Troubleshooting — Types not resolving from subpath imports", + "body": "Ensure your `tsconfig.json` uses `\"moduleResolution\": \"node16\"` or `\"nodenext\"`:" + }, + { + "kind": "code", + "heading": "Troubleshooting — Types not resolving from subpath imports (fix)", + "lang": "json", + "body": "{\n \"compilerOptions\": {\n \"module\": \"node16\",\n \"moduleResolution\": \"node16\"\n }\n}" + }, + { + "kind": "prose", + "heading": "Troubleshooting — Rate limit errors", + "body": "The SDK retries automatically with exponential backoff. To handle rate limits explicitly:" + }, + { + "kind": "code", + "heading": "Troubleshooting — Rate limit errors (example)", + "lang": "typescript", + "body": "wave.client.on(\"rate_limit.hit\", (retryAfter) => {\n console.log(`Rate limited. Retry in ${retryAfter}ms`);\n});" + }, + { + "kind": "prose", + "heading": "Troubleshooting — ESM vs CJS", + "body": "The SDK supports both ESM and CJS. If using CommonJS, ensure you're importing correctly:" + }, + { + "kind": "code", + "heading": "Troubleshooting — ESM vs CJS (example)", + "lang": "javascript", + "body": "const { Wave } = require(\"@wave-av/sdk\");" + }, + { + "kind": "prose", + "heading": "Requirements", + "body": "- Node.js 18+ (`engines.node` is `>=18.0.0`)\n- TypeScript 4.7+ for subpath type resolution (`moduleResolution: node16`); this package is built with TypeScript 5.9" + }, + { + "kind": "table", + "heading": "Related packages", + "columns": [ + "Package", + "Description" + ], + "rows": [ + [ + "[@wave-av/adk](https://www.npmjs.com/package/@wave-av/adk)", + "Agent Developer Kit for building AI video agents" + ], + [ + "[@wave-av/mcp-server](https://www.npmjs.com/package/@wave-av/mcp-server)", + "MCP server for Claude, Cursor, Windsurf" + ], + [ + "[@wave-av/cli](https://www.npmjs.com/package/@wave-av/cli)", + "Command-line interface" + ], + [ + "[@wave-av/create-app](https://www.npmjs.com/package/@wave-av/create-app)", + "Scaffold a new project" + ], + [ + "[@wave-av/workflow-sdk](https://www.npmjs.com/package/@wave-av/workflow-sdk)", + "Workflow orchestration" + ], + [ + "[OpenAPI spec](https://github.com/wave-av/api-spec)", + "Full API specification" + ] + ] + } + ] } diff --git a/README.md b/README.md index 4ec4721..f90dd5c 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,286 @@ const synthesis = await wave.voice.synthesize({ }); ``` +## API modules — Core streaming + +| API | Access | Status | Description | +| --- | --- | --- | --- | +| `wave.pipeline` | `PipelineAPI` | lib | Live stream lifecycle, protocols, recordings, viewer metrics | +| `wave.studio` | `StudioAPI` | planned | Multi-camera production, scenes, transitions, graphics, audio mixing | + +## API modules — Enterprise + +| API | Access | Status | Description | +| --- | --- | --- | --- | +| `wave.fleet` | `FleetAPI` | planned | Desktop Node fleet management, health, commands | +| `wave.ghost` | `GhostAPI` | planned | AI auto-directing (Autopilot), suggestions, overrides | +| `wave.mesh` | `MeshAPI` | planned | Multi-region failover, replication, topology | +| `wave.edge` | `EdgeAPI` | sdk-surface | CDN, edge workers, cache, routing rules | +| `wave.pulse` | `PulseAPI` | planned | Analytics, BI dashboards, revenue metrics | +| `wave.prism` | `PrismAPI` | planned | Virtual Device Bridge (NDI/ONVIF/VISCA/Dante to USB UVC/UAC) | +| `wave.zoom` | `ZoomAPI` | sdk-surface | Zoom meetings, rooms, recordings, RTMS | + +## API modules — Content & commerce + +| API | Access | Status | Description | +| --- | --- | --- | --- | +| `wave.clips` | `ClipsAPI` | lib | Video clips, exports, AI highlights | +| `wave.editor` | `EditorAPI` | lib | Video editing, tracks, transitions, effects | +| `wave.voice` | `VoiceAPI` | lib | Text-to-speech via `synthesize()`; voice-clone methods are SDK surface only | +| `wave.phone` | `PhoneAPI` | planned | Voice calling, conferences, numbers | +| `wave.collab` | `CollabAPI` | sdk-surface | Real-time collaboration rooms | +| `wave.captions` | `CaptionsAPI` | lib | Auto-captions, translation, burn-in | +| `wave.chapters` | `ChaptersAPI` | sdk-surface | Video chapters and markers | +| `wave.studioAI` | `StudioAIAPI` | sdk-surface | AI production assistant, suggestions | +| `wave.transcribe` | `TranscribeAPI` | lib | Transcription with speaker diarization | +| `wave.sentiment` | `SentimentAPI` | sdk-surface | Sentiment and emotion analysis | +| `wave.search` | `SearchAPI` | sdk-surface | Full-text, visual, and audio search | +| `wave.scene` | `SceneAPI` | sdk-surface | AI scene detection and shot classification | +| `wave.vault` | `VaultAPI` | planned | Recording storage, VOD, archive policies | +| `wave.marketplace` | `MarketplaceAPI` | sdk-surface | Templates, plugins, graphics marketplace | +| `wave.connect` | `ConnectAPI` | sdk-surface | Third-party integrations, webhooks | +| `wave.distribution` | `DistributionAPI` | sdk-surface | Social simulcasting, scheduled posts | +| `wave.desktop` | `DesktopAPI` | sdk-surface | Desktop Node app management | +| `wave.signage` | `SignageAPI` | sdk-surface | Digital signage displays, playlists | +| `wave.qr` | `QrAPI` | sdk-surface | Dynamic QR codes, analytics | +| `wave.audience` | `AudienceAPI` | sdk-surface | Polls, Q&A, reactions, engagement | +| `wave.creator` | `CreatorAPI` | planned | Monetization, subscriptions, tips, payouts | + +## API modules — Specialized + +| API | Access | Status | Description | +| --- | --- | --- | --- | +| `wave.podcast` | `PodcastAPI` | planned | Podcast episodes, RSS, distribution | +| `wave.slides` | `SlidesAPI` | sdk-surface | Presentation-to-video conversion | +| `wave.usb` | `UsbAPI` | sdk-surface | USB device relay and management | + +## API modules — Platform + +| API | Access | Status | Description | +| --- | --- | --- | --- | +| `wave.drm` | `DrmAPI` | sdk-surface | Digital Rights Management: content protection with Widevine, FairPlay, and PlayReady | +| `wave.notifications` | `NotificationsAPI` | sdk-surface | User notification preferences, delivery channels, and notification management | +| `wave.perception` | `PerceptionAPI` | sdk-surface | Agentic live-media perception: one `subscribe()` verb attaches an agent to any live stream | +| `wave.realtime` | `RealtimeAPI` | sdk-surface | Control & event plane: presence, pub/sub broadcast, and the streaming-event bus | + +## What the Status column means + +`lib` — the TypeScript client surface exists AND a live fleet backend serves it today. `planned` — the client surface exists, the backend does not yet; calling it will not work against production. `sdk-surface` — the client module is exported and typed, but this repo's SSOT declares no backend status for it, so treat it as unproven. Statuses come from `.wave/repo.json`, the same file this README is generated from. + +## Product example — Streams (Pipeline) + +```typescript +import { Wave } from "@wave-av/sdk"; + +const wave = new Wave({ apiKey: process.env.WAVE_API_KEY! }); + +const stream = await wave.pipeline.create({ + title: "My Live Stream", + protocol: "webrtc", + recording_enabled: true, +}); +await wave.pipeline.start(stream.id); +const live = await wave.pipeline.waitForLive(stream.id); +console.log(`Playback: ${live.playback_url}`); +await wave.pipeline.stop(stream.id); +``` + +## Product example — Clips + +```typescript +import { Wave } from "@wave-av/sdk"; + +const wave = new Wave({ apiKey: process.env.WAVE_API_KEY! }); + +const clip = await wave.clips.create({ + title: "Best Moment", + source: { type: "stream", id: "stream_123", start_time: 120, end_time: 150 }, +}); +const ready = await wave.clips.waitForReady(clip.id); +console.log(`Clip URL: ${ready.playback_url}`); +``` + +## Product example — Captions + +```typescript +import { Wave } from "@wave-av/sdk"; + +const wave = new Wave({ apiKey: process.env.WAVE_API_KEY! }); + +const track = await wave.captions.generate({ + media_id: "video_123", + media_type: "video", + language: "en", + speaker_diarization: true, +}); +const ready = await wave.captions.waitForReady(track.id); +await wave.captions.translate(ready.id, { target_language: "es" }); +``` + +## Product example — Voice + +```typescript +import { Wave } from "@wave-av/sdk"; + +const wave = new Wave({ apiKey: process.env.WAVE_API_KEY! }); + +const voices = await wave.voice.listVoices({ language: "en" }); +const result = await wave.voice.synthesize({ + text: "Welcome to WAVE live streaming.", + voice_id: voices.data[0].id, + format: "mp3", +}); +const audio = await wave.voice.waitForSynthesis(result.id); +console.log(`Audio: ${audio.audio_url}`); +``` + +## Product example — Transcription + +```typescript +import { Wave } from "@wave-av/sdk"; + +const wave = new Wave({ apiKey: process.env.WAVE_API_KEY! }); + +const job = await wave.transcribe.create({ + source_type: "recording", + source_id: "rec_456", + language: "en", + speaker_diarization: true, +}); +const result = await wave.transcribe.waitForReady(job.id); +const text = await wave.transcribe.getText(result.id, { include_speakers: true }); +console.log(text); +``` + +## Product example — Editor + +```typescript +import { Wave } from "@wave-av/sdk"; + +const wave = new Wave({ apiKey: process.env.WAVE_API_KEY! }); + +const project = await wave.editor.createProject({ + name: "Highlight Reel", + width: 1920, + height: 1080, + frame_rate: 30, +}); +const track = await wave.editor.addTrack(project.id, { name: "Main", type: "video" }); +await wave.editor.addElement(project.id, { + track_id: track.id, + type: "clip", + source_id: "clip_789", + start_time: 0, +}); +const job = await wave.editor.render(project.id, { format: "mp4", quality: "high" }); +const rendered = await wave.editor.waitForRender(project.id, job.id); +console.log(`Output: ${rendered.output_url}`); +``` + +## Configuration + +```typescript +const wave = new Wave({ + apiKey: "your-api-key", // Required + organizationId: "org_123", // Multi-tenant isolation + baseUrl: "https://api.wave.online", // Default + timeout: 30000, // Request timeout (ms) + maxRetries: 3, // Retry attempts + debug: false, // Debug logging +}); +``` + +## Individual API imports + +```typescript +import { WaveClient, PipelineAPI, PrismAPI } from "@wave-av/sdk"; + +const client = new WaveClient({ apiKey: "key" }); +const pipeline = new PipelineAPI(client); +const prism = new PrismAPI(client); +``` + +## Error handling + +```typescript +import { WaveError, RateLimitError } from "@wave-av/sdk"; + +try { + await wave.pipeline.get("invalid-id"); +} catch (error) { + if (error instanceof RateLimitError) { + console.log(`Rate limited. Retry after ${error.retryAfter}ms`); + } else if (error instanceof WaveError) { + console.log(`${error.code}: ${error.message} (${error.statusCode})`); + } +} +``` + +## Events + +```typescript +wave.client.on("request.start", (url, method) => { + console.log(`${method} ${url}`); +}); + +wave.client.on("rate_limit.hit", (retryAfter) => { + console.log(`Rate limited. Waiting ${retryAfter}ms`); +}); +``` + +## Troubleshooting — Types not resolving from subpath imports + +Ensure your `tsconfig.json` uses `"moduleResolution": "node16"` or `"nodenext"`: + +## Troubleshooting — Types not resolving from subpath imports (fix) + +```json +{ + "compilerOptions": { + "module": "node16", + "moduleResolution": "node16" + } +} +``` + +## Troubleshooting — Rate limit errors + +The SDK retries automatically with exponential backoff. To handle rate limits explicitly: + +## Troubleshooting — Rate limit errors (example) + +```typescript +wave.client.on("rate_limit.hit", (retryAfter) => { + console.log(`Rate limited. Retry in ${retryAfter}ms`); +}); +``` + +## Troubleshooting — ESM vs CJS + +The SDK supports both ESM and CJS. If using CommonJS, ensure you're importing correctly: + +## Troubleshooting — ESM vs CJS (example) + +```javascript +const { Wave } = require("@wave-av/sdk"); +``` + +## Requirements + +- Node.js 18+ (`engines.node` is `>=18.0.0`) +- TypeScript 4.7+ for subpath type resolution (`moduleResolution: node16`); this package is built with TypeScript 5.9 + +## Related packages + +| Package | Description | +| --- | --- | +| [@wave-av/adk](https://www.npmjs.com/package/@wave-av/adk) | Agent Developer Kit for building AI video agents | +| [@wave-av/mcp-server](https://www.npmjs.com/package/@wave-av/mcp-server) | MCP server for Claude, Cursor, Windsurf | +| [@wave-av/cli](https://www.npmjs.com/package/@wave-av/cli) | Command-line interface | +| [@wave-av/create-app](https://www.npmjs.com/package/@wave-av/create-app) | Scaffold a new project | +| [@wave-av/workflow-sdk](https://www.npmjs.com/package/@wave-av/workflow-sdk) | Workflow orchestration | +| [OpenAPI spec](https://github.com/wave-av/api-spec) | Full API specification | + ## Capabilities | Capability | Status |