diff --git a/.wave/repo.json b/.wave/repo.json index a7ee1bb1..31be026b 100644 --- a/.wave/repo.json +++ b/.wave/repo.json @@ -5,42 +5,220 @@ "purpose": "WAVE is media infrastructure for the agentic internet: one call shape moves live and on-demand media across every transport, and both kinds of user, people and agents, discover it, call it, and pay for it per call. This SDK is the TypeScript client for that call shape: API modules 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 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 d7d481e0..a7db36fc 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,286 @@ const render = await wave.client.post("/v1/render", { const ledger = await wave.meter.ledger({ channel: "mail" }); ``` +## 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 - **Pricing Pages** — create/list/read tier manifests (pricing.wave.online/ hosted pages; scopes pricing:write/pricing:read)