@wave-av/cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@wave-av/cli",
3
+ "version": "1.0.0",
4
+ "description": "WAVE CLI - Command-line interface for the WAVE streaming platform",
5
+ "main": "./dist/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "wave": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "templates",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsup",
17
+ "dev": "tsup --watch",
18
+ "type-check": "tsc --noEmit",
19
+ "test": "vitest run",
20
+ "test:watch": "vitest",
21
+ "lint": "eslint src/",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "wave",
26
+ "cli",
27
+ "streaming",
28
+ "video",
29
+ "broadcast",
30
+ "production"
31
+ ],
32
+ "author": "WAVE Inc. <cli@wave.online>",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/wave-av/wave-surfer-connect.git",
37
+ "directory": "packages/cli"
38
+ },
39
+ "homepage": "https://docs.wave.online/cli",
40
+ "bugs": {
41
+ "url": "https://github.com/wave-av/wave-surfer-connect/issues"
42
+ },
43
+ "engines": {
44
+ "node": ">=18.0.0"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public",
48
+ "registry": "https://registry.npmjs.org/"
49
+ },
50
+ "dependencies": {
51
+ "@wave-av/sdk": "workspace:*",
52
+ "chalk": "^5.4.1",
53
+ "cli-table3": "^0.6.5",
54
+ "commander": "^13.1.0",
55
+ "conf": "^13.1.0",
56
+ "inquirer": "^12.3.2",
57
+ "keytar": "^7.9.0",
58
+ "open": "^10.1.0",
59
+ "ora": "^8.2.0",
60
+ "ws": "^8.18.0",
61
+ "yaml": "^2.7.0",
62
+ "zod": "3.25.76"
63
+ },
64
+ "devDependencies": {
65
+ "@sentry/node": "^9.4.0",
66
+ "@types/inquirer": "^9.0.7",
67
+ "@types/node": "^22.13.0",
68
+ "@types/ws": "^8.5.14",
69
+ "tsup": "^8.0.0",
70
+ "typescript": "^5.9.3",
71
+ "vitest": "^4.0.16"
72
+ }
73
+ }
@@ -0,0 +1,2 @@
1
+ WAVE_API_KEY=wave_live_your_api_key_here
2
+ WAVE_ORG_ID=your_org_id_here
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "wave-api-integration",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "npx tsx src/index.ts",
8
+ "build": "tsc"
9
+ },
10
+ "dependencies": {
11
+ "@wave/sdk": "^2.0.0"
12
+ },
13
+ "devDependencies": {
14
+ "tsx": "^4.0.0",
15
+ "typescript": "^5.9.0"
16
+ }
17
+ }
@@ -0,0 +1,24 @@
1
+ import { Wave } from "@wave/sdk";
2
+
3
+ const wave = new Wave({
4
+ apiKey: process.env.WAVE_API_KEY!,
5
+ });
6
+
7
+ async function main() {
8
+ // List your streams
9
+ const streams = await wave.pipeline.list({ limit: 10 });
10
+ console.log(`Found ${streams.data.length} streams\n`);
11
+
12
+ for (const stream of streams.data) {
13
+ console.log(` ${stream.id} - ${stream.title} (${stream.status})`);
14
+ }
15
+
16
+ // Get organization usage
17
+ const usage = await wave.billing.getUsage();
18
+ console.log(`\nCurrent usage:`);
19
+ console.log(` Streams: ${usage.streams_count}`);
20
+ console.log(` Storage: ${usage.storage_gb}GB`);
21
+ console.log(` Bandwidth: ${usage.bandwidth_gb}GB`);
22
+ }
23
+
24
+ main().catch(console.error);
@@ -0,0 +1 @@
1
+ WAVE_API_KEY=wave_live_your_api_key_here
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "wave-project",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "npx tsx src/index.ts",
8
+ "build": "tsc"
9
+ },
10
+ "dependencies": {
11
+ "@wave/sdk": "^2.0.0"
12
+ },
13
+ "devDependencies": {
14
+ "tsx": "^4.0.0",
15
+ "typescript": "^5.9.0"
16
+ }
17
+ }
@@ -0,0 +1,16 @@
1
+ import { Wave } from "@wave/sdk";
2
+
3
+ const wave = new Wave({
4
+ apiKey: process.env.WAVE_API_KEY!,
5
+ });
6
+
7
+ async function main() {
8
+ const streams = await wave.pipeline.list();
9
+ console.log(`Found ${streams.data.length} streams`);
10
+
11
+ for (const stream of streams.data) {
12
+ console.log(`- ${stream.title} (${stream.status})`);
13
+ }
14
+ }
15
+
16
+ main().catch(console.error);
@@ -0,0 +1 @@
1
+ WAVE_API_KEY=wave_live_your_api_key_here
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "wave-multi-camera",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "npx tsx src/index.ts",
8
+ "build": "tsc"
9
+ },
10
+ "dependencies": {
11
+ "@wave/sdk": "^2.0.0"
12
+ },
13
+ "devDependencies": {
14
+ "tsx": "^4.0.0",
15
+ "typescript": "^5.9.0"
16
+ }
17
+ }
@@ -0,0 +1,49 @@
1
+ import { Wave } from "@wave/sdk";
2
+
3
+ const wave = new Wave({
4
+ apiKey: process.env.WAVE_API_KEY!,
5
+ });
6
+
7
+ async function main() {
8
+ // Create a multi-camera production session
9
+ const production = await wave.studio.create({
10
+ title: "Multi-Camera Production",
11
+ description: "Multi-source production demo",
12
+ });
13
+
14
+ console.log(`Production created: ${production.id}`);
15
+
16
+ // Add camera sources
17
+ const cam1 = await wave.studio.addSource(production.id, {
18
+ type: "camera",
19
+ label: "Camera 1 - Wide",
20
+ url: "rtmp://localhost/live/cam1",
21
+ });
22
+
23
+ const cam2 = await wave.studio.addSource(production.id, {
24
+ type: "camera",
25
+ label: "Camera 2 - Close-up",
26
+ url: "rtmp://localhost/live/cam2",
27
+ });
28
+
29
+ console.log(`Sources added: ${cam1.id}, ${cam2.id}`);
30
+
31
+ // Create scenes
32
+ const fullscreen = await wave.studio.createScene(production.id, {
33
+ name: "Fullscreen",
34
+ layout: "single",
35
+ });
36
+
37
+ const sideBySide = await wave.studio.createScene(production.id, {
38
+ name: "Side by Side",
39
+ layout: "split",
40
+ });
41
+
42
+ console.log(`Scenes created: ${fullscreen.id}, ${sideBySide.id}`);
43
+
44
+ // Start production
45
+ await wave.studio.start(production.id);
46
+ console.log("Production started!");
47
+ }
48
+
49
+ main().catch(console.error);
@@ -0,0 +1 @@
1
+ WAVE_API_KEY=wave_live_your_api_key_here
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "wave-podcast",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "npx tsx src/index.ts",
8
+ "build": "tsc"
9
+ },
10
+ "dependencies": {
11
+ "@wave/sdk": "^2.0.0"
12
+ },
13
+ "devDependencies": {
14
+ "tsx": "^4.0.0",
15
+ "typescript": "^5.9.0"
16
+ }
17
+ }
@@ -0,0 +1,33 @@
1
+ import { Wave } from "@wave/sdk";
2
+
3
+ const wave = new Wave({
4
+ apiKey: process.env.WAVE_API_KEY!,
5
+ });
6
+
7
+ async function main() {
8
+ // Create a podcast episode recording
9
+ const stream = await wave.pipeline.create({
10
+ title: "Podcast Episode Recording",
11
+ protocol: "webrtc",
12
+ description: "Audio-focused recording session",
13
+ });
14
+
15
+ console.log(`Recording session created: ${stream.id}`);
16
+
17
+ // Start recording
18
+ await wave.pipeline.start(stream.id);
19
+ const recording = await wave.pipeline.startRecording(stream.id);
20
+ console.log(`Recording started: ${recording.id}`);
21
+
22
+ // After recording, generate transcription
23
+ console.log("Generating transcription...");
24
+ const transcription = await wave.transcribe.create({
25
+ recording_id: recording.id,
26
+ language: "en",
27
+ model: "enhanced",
28
+ });
29
+
30
+ console.log(`Transcription: ${transcription.id} (${transcription.status})`);
31
+ }
32
+
33
+ main().catch(console.error);
@@ -0,0 +1 @@
1
+ WAVE_API_KEY=wave_live_your_api_key_here
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "wave-srt-contribution",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "npx tsx src/index.ts",
8
+ "build": "tsc"
9
+ },
10
+ "dependencies": {
11
+ "@wave/sdk": "^2.0.0"
12
+ },
13
+ "devDependencies": {
14
+ "tsx": "^4.0.0",
15
+ "typescript": "^5.9.0"
16
+ }
17
+ }
@@ -0,0 +1,29 @@
1
+ import { Wave } from "@wave/sdk";
2
+
3
+ const wave = new Wave({
4
+ apiKey: process.env.WAVE_API_KEY!,
5
+ });
6
+
7
+ async function main() {
8
+ // Create an SRT contribution stream (low-latency ingest)
9
+ const stream = await wave.pipeline.create({
10
+ title: "SRT Contribution Feed",
11
+ protocol: "srt",
12
+ description: "Low-latency SRT ingest for remote contribution",
13
+ });
14
+
15
+ console.log(`SRT stream created: ${stream.id}`);
16
+ console.log(`SRT ingest URL: ${stream.ingest_url}`);
17
+ console.log(`Use this URL in your SRT encoder (OBS, vMix, etc.)`);
18
+
19
+ // Start accepting connections
20
+ const started = await wave.pipeline.start(stream.id);
21
+ console.log(`Status: ${started.status}`);
22
+
23
+ // Monitor health
24
+ const health = await wave.pipeline.getHealth(stream.id);
25
+ console.log(`Bitrate: ${health.bitrate_kbps}kbps`);
26
+ console.log(`Latency: ${health.latency_ms}ms`);
27
+ }
28
+
29
+ main().catch(console.error);
@@ -0,0 +1,2 @@
1
+ WAVE_API_KEY=wave_live_your_api_key_here
2
+ WAVE_ORG_ID=your_org_id_here
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "wave-studio-plugin",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "npx tsx src/index.ts",
8
+ "build": "tsc"
9
+ },
10
+ "dependencies": {
11
+ "@wave/sdk": "^2.0.0"
12
+ },
13
+ "devDependencies": {
14
+ "tsx": "^4.0.0",
15
+ "typescript": "^5.9.0"
16
+ }
17
+ }
@@ -0,0 +1,32 @@
1
+ import { Wave } from "@wave/sdk";
2
+
3
+ const wave = new Wave({
4
+ apiKey: process.env.WAVE_API_KEY!,
5
+ });
6
+
7
+ async function main() {
8
+ // Register a custom Studio plugin
9
+ const plugin = await wave.studio.registerPlugin({
10
+ name: "My Custom Plugin",
11
+ description: "A custom production plugin for WAVE Studio",
12
+ version: "1.0.0",
13
+ capabilities: ["overlay", "transition"],
14
+ });
15
+
16
+ console.log(`Plugin registered: ${plugin.id}`);
17
+
18
+ // Listen for Studio events
19
+ const connection = await wave.studio.connect(plugin.id);
20
+
21
+ connection.on("scene.switch", (scene) => {
22
+ console.log(`Scene switched to: ${scene.name}`);
23
+ });
24
+
25
+ connection.on("source.added", (source) => {
26
+ console.log(`New source added: ${source.name} (${source.type})`);
27
+ });
28
+
29
+ console.log("Studio plugin connected and listening for events...");
30
+ }
31
+
32
+ main().catch(console.error);
@@ -0,0 +1,3 @@
1
+ WAVE_API_KEY=wave_live_your_api_key_here
2
+ WAVE_WEBHOOK_SECRET=whsec_your_webhook_secret_here
3
+ PORT=3000
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "wave-webhook-handler",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "npx tsx src/index.ts",
8
+ "build": "tsc"
9
+ },
10
+ "dependencies": {
11
+ "@wave/sdk": "^2.0.0",
12
+ "express": "^4.21.0"
13
+ },
14
+ "devDependencies": {
15
+ "@types/express": "^5.0.0",
16
+ "tsx": "^4.0.0",
17
+ "typescript": "^5.9.0"
18
+ }
19
+ }
@@ -0,0 +1,52 @@
1
+ import express from "express";
2
+ import { Wave } from "@wave/sdk";
3
+
4
+ const wave = new Wave({
5
+ apiKey: process.env.WAVE_API_KEY!,
6
+ });
7
+
8
+ const app = express();
9
+
10
+ // WAVE sends JSON payloads for webhook events
11
+ app.use(express.json());
12
+
13
+ // Verify webhook signatures to ensure requests are from WAVE
14
+ app.post("/webhooks/wave", async (req, res) => {
15
+ const signature = req.headers["wave-signature"] as string | undefined;
16
+ const secret = process.env.WAVE_WEBHOOK_SECRET;
17
+
18
+ if (!signature || !secret) {
19
+ res.status(401).json({ error: "Missing signature or secret" });
20
+ return;
21
+ }
22
+
23
+ const isValid = wave.webhooks.verify(req.body, signature, secret);
24
+ if (!isValid) {
25
+ res.status(401).json({ error: "Invalid signature" });
26
+ return;
27
+ }
28
+
29
+ const event = req.body;
30
+ console.log(`Received event: ${event.type}`);
31
+
32
+ switch (event.type) {
33
+ case "stream.started":
34
+ console.log(`Stream ${event.data.stream_id} started`);
35
+ break;
36
+ case "stream.ended":
37
+ console.log(`Stream ${event.data.stream_id} ended`);
38
+ break;
39
+ case "recording.ready":
40
+ console.log(`Recording ready: ${event.data.recording_url}`);
41
+ break;
42
+ default:
43
+ console.log(`Unhandled event type: ${event.type}`);
44
+ }
45
+
46
+ res.json({ received: true });
47
+ });
48
+
49
+ const PORT = process.env.PORT ?? 3000;
50
+ app.listen(PORT, () => {
51
+ console.log(`Webhook server listening on port ${PORT}`);
52
+ });
@@ -0,0 +1 @@
1
+ WAVE_API_KEY=wave_live_your_api_key_here
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "wave-webrtc-demo",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "npx tsx src/index.ts",
8
+ "build": "tsc"
9
+ },
10
+ "dependencies": {
11
+ "@wave/sdk": "^2.0.0"
12
+ },
13
+ "devDependencies": {
14
+ "tsx": "^4.0.0",
15
+ "typescript": "^5.9.0"
16
+ }
17
+ }
@@ -0,0 +1,31 @@
1
+ import { Wave } from "@wave/sdk";
2
+
3
+ const wave = new Wave({
4
+ apiKey: process.env.WAVE_API_KEY!,
5
+ });
6
+
7
+ async function main() {
8
+ // Create a WebRTC stream
9
+ const stream = await wave.pipeline.create({
10
+ title: "WebRTC Demo Stream",
11
+ protocol: "webrtc",
12
+ description: "Created with WAVE CLI",
13
+ });
14
+
15
+ console.log(`Stream created: ${stream.id}`);
16
+ console.log(`Ingest URL: ${stream.ingest_url}`);
17
+ console.log(`Playback URL: ${stream.playback_url}`);
18
+
19
+ // Start the stream
20
+ const started = await wave.pipeline.start(stream.id);
21
+ console.log(`Stream status: ${started.status}`);
22
+
23
+ // Wait for it to go live
24
+ const live = await wave.pipeline.waitForLive(stream.id, {
25
+ timeout: 60000,
26
+ pollInterval: 2000,
27
+ });
28
+ console.log(`Stream is live! Viewers: ${live.viewer_count}`);
29
+ }
30
+
31
+ main().catch(console.error);