@mentra/sdk 2.1.27 → 2.1.28
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/dist/app/session/api-client.d.ts.map +1 -1
- package/dist/app/session/dashboard.d.ts +5 -8
- package/dist/app/session/dashboard.d.ts.map +1 -1
- package/dist/app/session/events.d.ts +2 -1
- package/dist/app/session/events.d.ts.map +1 -1
- package/dist/app/session/index.d.ts +62 -3
- package/dist/app/session/index.d.ts.map +1 -1
- package/dist/app/session/modules/audio.d.ts +33 -4
- package/dist/app/session/modules/audio.d.ts.map +1 -1
- package/dist/app/session/modules/camera-managed-extension.d.ts +2 -3
- package/dist/app/session/modules/camera-managed-extension.d.ts.map +1 -1
- package/dist/app/session/modules/camera.d.ts +5 -5
- package/dist/app/session/modules/camera.d.ts.map +1 -1
- package/dist/app/session/modules/led.d.ts +141 -0
- package/dist/app/session/modules/led.d.ts.map +1 -0
- package/dist/app/session/modules/location.d.ts +1 -2
- package/dist/app/session/modules/location.d.ts.map +1 -1
- package/dist/app/session/modules/simple-storage.d.ts.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5347 -112
- package/dist/index.js.map +45 -0
- package/dist/logging/logger.d.ts +1 -1
- package/dist/logging/logger.d.ts.map +1 -1
- package/dist/types/capabilities.d.ts +3 -0
- package/dist/types/capabilities.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -14
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/message-types.d.ts +8 -1
- package/dist/types/message-types.d.ts.map +1 -1
- package/dist/types/messages/app-to-cloud.d.ts +48 -2
- package/dist/types/messages/app-to-cloud.d.ts.map +1 -1
- package/dist/types/messages/cloud-to-app.d.ts +16 -6
- package/dist/types/messages/cloud-to-app.d.ts.map +1 -1
- package/dist/types/messages/cloud-to-glasses.d.ts +29 -1
- package/dist/types/messages/cloud-to-glasses.d.ts.map +1 -1
- package/dist/types/messages/glasses-to-cloud.d.ts +24 -1
- package/dist/types/messages/glasses-to-cloud.d.ts.map +1 -1
- package/dist/types/rtmp-stream.d.ts +1 -1
- package/dist/types/rtmp-stream.d.ts.map +1 -1
- package/dist/types/streams.d.ts +28 -1
- package/dist/types/streams.d.ts.map +1 -1
- package/package.json +9 -3
- package/dist/app/index.js +0 -24
- package/dist/app/server/index.js +0 -658
- package/dist/app/session/api-client.js +0 -101
- package/dist/app/session/dashboard.js +0 -149
- package/dist/app/session/events.js +0 -315
- package/dist/app/session/index.js +0 -1573
- package/dist/app/session/layouts.js +0 -372
- package/dist/app/session/modules/audio.js +0 -321
- package/dist/app/session/modules/camera-managed-extension.js +0 -310
- package/dist/app/session/modules/camera.js +0 -607
- package/dist/app/session/modules/index.js +0 -19
- package/dist/app/session/modules/location.js +0 -61
- package/dist/app/session/modules/simple-storage.js +0 -232
- package/dist/app/session/settings.js +0 -358
- package/dist/app/token/index.js +0 -22
- package/dist/app/token/utils.js +0 -144
- package/dist/app/webview/index.js +0 -382
- package/dist/constants/index.js +0 -16
- package/dist/constants/log-messages/color.js +0 -14
- package/dist/constants/log-messages/logos.js +0 -48
- package/dist/constants/log-messages/updates.js +0 -55
- package/dist/constants/log-messages/warning.js +0 -89
- package/dist/examples/managed-rtmp-streaming-example.js +0 -158
- package/dist/examples/managed-rtmp-streaming-with-restream-example.js +0 -124
- package/dist/examples/rtmp-streaming-example.js +0 -102
- package/dist/logging/logger.js +0 -79
- package/dist/types/capabilities.js +0 -9
- package/dist/types/dashboard/index.js +0 -12
- package/dist/types/enums.js +0 -75
- package/dist/types/index.js +0 -101
- package/dist/types/layouts.js +0 -3
- package/dist/types/message-types.js +0 -212
- package/dist/types/messages/app-to-cloud.js +0 -95
- package/dist/types/messages/base.js +0 -3
- package/dist/types/messages/cloud-to-app.js +0 -78
- package/dist/types/messages/cloud-to-glasses.js +0 -68
- package/dist/types/messages/glasses-to-cloud.js +0 -140
- package/dist/types/models.js +0 -101
- package/dist/types/photo-data.js +0 -2
- package/dist/types/rtmp-stream.js +0 -3
- package/dist/types/streams.js +0 -306
- package/dist/types/token.js +0 -7
- package/dist/types/webhooks.js +0 -28
- package/dist/utils/animation-utils.js +0 -340
- package/dist/utils/bitmap-utils.js +0 -475
- package/dist/utils/permissions-utils.js +0 -263
- package/dist/utils/resource-tracker.js +0 -153
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.cameraWarn = exports.postNotficationWarn = exports.readNotficationWarn = exports.calendarWarn = exports.baackgroundLocationWarn = exports.locationWarn = exports.noMicrophoneWarn = void 0;
|
|
7
|
-
/**
|
|
8
|
-
* warning.ts
|
|
9
|
-
*
|
|
10
|
-
* This file defines styled warning messages that are displayed when an app
|
|
11
|
-
* attempts to use functionality requiring permissions it hasn't declared.
|
|
12
|
-
*
|
|
13
|
-
* Each function generates a bordered terminal warning box with:
|
|
14
|
-
* - ASCII art logo (left side)
|
|
15
|
-
* - Permission requirement details (right side)
|
|
16
|
-
* - Link to developer portal for adding permissions
|
|
17
|
-
*
|
|
18
|
-
* The warnings use chalk for terminal colors and boxen for bordered output,
|
|
19
|
-
* creating a professional side-by-side layout that alerts developers to
|
|
20
|
-
* missing permissions in their app configuration.
|
|
21
|
-
*
|
|
22
|
-
* These are shown during SDK runtime when permission checks fail, helping
|
|
23
|
-
* developers identify and fix permission issues quickly.
|
|
24
|
-
*/
|
|
25
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
26
|
-
const boxen_1 = __importDefault(require("boxen"));
|
|
27
|
-
const logos_1 = require("./logos");
|
|
28
|
-
const createPermissionWarning = (permissionName, funcName, packageName) => {
|
|
29
|
-
// Strip ANSI codes for width calculation
|
|
30
|
-
// eslint-disable-next-line no-control-regex
|
|
31
|
-
const stripAnsi = (str) => str.replace(/\u001b\[\d+m/g, "");
|
|
32
|
-
const title = chalk_1.default.bold.yellow("⚠️ Permission Required");
|
|
33
|
-
const message = `${chalk_1.default.yellow(funcName || "This function")} requires ${chalk_1.default.bold(permissionName)} permission.`;
|
|
34
|
-
const instructions = chalk_1.default.dim("Please enable this permission in the developer portal at:");
|
|
35
|
-
const url = chalk_1.default.cyan.underline(`https://console.mentra.glass/apps/${packageName}/edit`);
|
|
36
|
-
const hint = chalk_1.default.dim("under *Required Permissions*.");
|
|
37
|
-
// Split logo into lines (without color for width calculation)
|
|
38
|
-
const logoLines = logos_1.warnLog.split("\n");
|
|
39
|
-
const coloredLogoLines = logoLines.map((line) => chalk_1.default.yellow(line));
|
|
40
|
-
const textContent = [title, "", message, "", instructions, url, "", hint];
|
|
41
|
-
// Find actual logo width (max line length without ANSI codes)
|
|
42
|
-
const logoWidth = Math.max(...logoLines.map((line) => stripAnsi(line).length));
|
|
43
|
-
// Create side-by-side layout
|
|
44
|
-
const maxLines = Math.max(coloredLogoLines.length, textContent.length);
|
|
45
|
-
const combinedLines = [];
|
|
46
|
-
for (let i = 0; i < maxLines; i++) {
|
|
47
|
-
const rawLogoLine = logoLines[i] || "";
|
|
48
|
-
const coloredLogoLine = coloredLogoLines[i] || "";
|
|
49
|
-
const actualLogoLength = stripAnsi(rawLogoLine).length;
|
|
50
|
-
const padding = " ".repeat(Math.max(0, logoWidth - actualLogoLength));
|
|
51
|
-
const textLine = textContent[i] || "";
|
|
52
|
-
combinedLines.push(`${coloredLogoLine}${padding} ${textLine}`);
|
|
53
|
-
}
|
|
54
|
-
return (0, boxen_1.default)(combinedLines.join("\n"), {
|
|
55
|
-
padding: 1,
|
|
56
|
-
margin: 1,
|
|
57
|
-
borderStyle: "round",
|
|
58
|
-
borderColor: "yellow",
|
|
59
|
-
float: "left",
|
|
60
|
-
});
|
|
61
|
-
};
|
|
62
|
-
const noMicrophoneWarn = (funcName, packageName) => {
|
|
63
|
-
return createPermissionWarning("microphone", funcName, packageName);
|
|
64
|
-
};
|
|
65
|
-
exports.noMicrophoneWarn = noMicrophoneWarn;
|
|
66
|
-
const locationWarn = (funcName, packageName) => {
|
|
67
|
-
return createPermissionWarning("location", funcName, packageName);
|
|
68
|
-
};
|
|
69
|
-
exports.locationWarn = locationWarn;
|
|
70
|
-
const baackgroundLocationWarn = (funcName, packageName) => {
|
|
71
|
-
return createPermissionWarning("background location", funcName, packageName);
|
|
72
|
-
};
|
|
73
|
-
exports.baackgroundLocationWarn = baackgroundLocationWarn;
|
|
74
|
-
const calendarWarn = (funcName, packageName) => {
|
|
75
|
-
return createPermissionWarning("calendar", funcName, packageName);
|
|
76
|
-
};
|
|
77
|
-
exports.calendarWarn = calendarWarn;
|
|
78
|
-
const readNotficationWarn = (funcName, packageName) => {
|
|
79
|
-
return createPermissionWarning("read notification", funcName, packageName);
|
|
80
|
-
};
|
|
81
|
-
exports.readNotficationWarn = readNotficationWarn;
|
|
82
|
-
const postNotficationWarn = (funcName, packageName) => {
|
|
83
|
-
return createPermissionWarning("post notification", funcName, packageName);
|
|
84
|
-
};
|
|
85
|
-
exports.postNotficationWarn = postNotficationWarn;
|
|
86
|
-
const cameraWarn = (funcName, packageName) => {
|
|
87
|
-
return createPermissionWarning("camera", funcName, packageName);
|
|
88
|
-
};
|
|
89
|
-
exports.cameraWarn = cameraWarn;
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
/**
|
|
4
|
-
* Managed RTMP Streaming Example
|
|
5
|
-
*
|
|
6
|
-
* This example demonstrates how to use the MentraOS SDK's managed streaming
|
|
7
|
-
* feature. With managed streaming, you don't need your own RTMP server -
|
|
8
|
-
* MentraOS handles all the infrastructure and provides viewer URLs.
|
|
9
|
-
*
|
|
10
|
-
* Perfect for:
|
|
11
|
-
* - Social media streaming (X, YouTube Live, TikTok Live)
|
|
12
|
-
* - Quick demos and prototypes
|
|
13
|
-
* - Production apps without existing streaming infrastructure
|
|
14
|
-
*
|
|
15
|
-
* NEW: You can now add re-streaming to multiple platforms! See
|
|
16
|
-
* managed-rtmp-streaming-with-restream-example.ts for details.
|
|
17
|
-
*/
|
|
18
|
-
const __1 = require("../");
|
|
19
|
-
// Initialize App session
|
|
20
|
-
const session = new __1.AppSession({
|
|
21
|
-
packageName: 'com.example.managed-streaming',
|
|
22
|
-
apiKey: 'your-api-key',
|
|
23
|
-
userId: 'example-user@example.com',
|
|
24
|
-
appServer: {}, // In a real app, this would be a AppServer instance
|
|
25
|
-
mentraOSWebsocketUrl: 'ws://localhost:8002/app-ws'
|
|
26
|
-
});
|
|
27
|
-
// Track current stream for cleanup
|
|
28
|
-
let currentStreamId = null;
|
|
29
|
-
// Connect to MentraOS Cloud and start streaming
|
|
30
|
-
async function main() {
|
|
31
|
-
try {
|
|
32
|
-
// 1. Connect to MentraOS Cloud
|
|
33
|
-
await session.connect('managed-streaming-session');
|
|
34
|
-
console.log('✅ Connected to MentraOS Cloud');
|
|
35
|
-
// 2. Subscribe to stream status updates
|
|
36
|
-
session.subscribe(__1.StreamType.MANAGED_STREAM_STATUS);
|
|
37
|
-
setupStreamStatusHandler();
|
|
38
|
-
// 3. Start managed streaming
|
|
39
|
-
await startManagedStream();
|
|
40
|
-
// 4. Keep streaming for 2 minutes then stop
|
|
41
|
-
setTimeout(async () => {
|
|
42
|
-
await stopManagedStream();
|
|
43
|
-
session.disconnect();
|
|
44
|
-
}, 2 * 60 * 1000);
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
console.error('❌ Error:', error);
|
|
48
|
-
session.disconnect();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// Start a managed stream
|
|
52
|
-
async function startManagedStream() {
|
|
53
|
-
try {
|
|
54
|
-
console.log('🎬 Starting managed stream...');
|
|
55
|
-
// Start streaming with zero configuration!
|
|
56
|
-
const result = await session.camera.startManagedStream();
|
|
57
|
-
currentStreamId = result.streamId;
|
|
58
|
-
console.log('\n🎉 Stream started successfully!');
|
|
59
|
-
console.log('📺 Share these URLs with viewers:');
|
|
60
|
-
console.log(` HLS URL (Best compatibility): ${result.hlsUrl}`);
|
|
61
|
-
console.log(` DASH URL (Alternative): ${result.dashUrl}`);
|
|
62
|
-
if (result.webrtcUrl) {
|
|
63
|
-
console.log(` WebRTC URL (Low latency): ${result.webrtcUrl}`);
|
|
64
|
-
}
|
|
65
|
-
console.log('\n💡 Viewers can open the HLS URL in:');
|
|
66
|
-
console.log(' - Any modern web browser');
|
|
67
|
-
console.log(' - VLC Media Player');
|
|
68
|
-
console.log(' - Mobile video players');
|
|
69
|
-
console.log(' - Or embed in your app with video.js or hls.js\n');
|
|
70
|
-
}
|
|
71
|
-
catch (error) {
|
|
72
|
-
console.error('❌ Failed to start managed stream:', error);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// Example: Enable WebRTC for low-latency viewing
|
|
76
|
-
async function startLowLatencyStream() {
|
|
77
|
-
try {
|
|
78
|
-
const result = await session.camera.startManagedStream({
|
|
79
|
-
enableWebRTC: true
|
|
80
|
-
});
|
|
81
|
-
console.log('✅ Low-latency stream started');
|
|
82
|
-
console.log('🚀 WebRTC URL:', result.webrtcUrl);
|
|
83
|
-
console.log(' (Latency: ~2-3 seconds vs 5-10 seconds for HLS)');
|
|
84
|
-
}
|
|
85
|
-
catch (error) {
|
|
86
|
-
console.error('❌ Failed to start stream:', error);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
// Set up handler for stream status updates
|
|
90
|
-
function setupStreamStatusHandler() {
|
|
91
|
-
session.on(__1.StreamType.MANAGED_STREAM_STATUS, (status) => {
|
|
92
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
93
|
-
switch (status.status) {
|
|
94
|
-
case 'initializing':
|
|
95
|
-
console.log(`[${timestamp}] 📡 Stream initializing...`);
|
|
96
|
-
break;
|
|
97
|
-
case 'active':
|
|
98
|
-
console.log(`[${timestamp}] 🟢 Stream is LIVE!`);
|
|
99
|
-
if (status.hlsUrl) {
|
|
100
|
-
console.log(` View at: ${status.hlsUrl}`);
|
|
101
|
-
}
|
|
102
|
-
break;
|
|
103
|
-
case 'stopping':
|
|
104
|
-
console.log(`[${timestamp}] 🟡 Stream stopping...`);
|
|
105
|
-
break;
|
|
106
|
-
case 'stopped':
|
|
107
|
-
console.log(`[${timestamp}] 🔴 Stream stopped`);
|
|
108
|
-
currentStreamId = null;
|
|
109
|
-
break;
|
|
110
|
-
case 'error':
|
|
111
|
-
console.error(`[${timestamp}] ❌ Stream error: ${status.message}`);
|
|
112
|
-
currentStreamId = null;
|
|
113
|
-
break;
|
|
114
|
-
default:
|
|
115
|
-
console.log(`[${timestamp}] Stream status: ${status.status}`);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
// Stop the managed stream
|
|
120
|
-
async function stopManagedStream() {
|
|
121
|
-
if (!currentStreamId) {
|
|
122
|
-
console.log('No active stream to stop');
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
try {
|
|
126
|
-
console.log('🛑 Stopping managed stream...');
|
|
127
|
-
await session.camera.stopManagedStream();
|
|
128
|
-
console.log('✅ Stream stopped successfully');
|
|
129
|
-
currentStreamId = null;
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
console.error('❌ Error stopping stream:', error);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// Handle errors
|
|
136
|
-
session.events.on('error', (error) => {
|
|
137
|
-
console.error('Session error:', error);
|
|
138
|
-
});
|
|
139
|
-
// Handle disconnection
|
|
140
|
-
session.events.on('disconnected', (info) => {
|
|
141
|
-
console.log('Disconnected:', info);
|
|
142
|
-
currentStreamId = null;
|
|
143
|
-
});
|
|
144
|
-
// Graceful shutdown on exit
|
|
145
|
-
process.on('SIGINT', async () => {
|
|
146
|
-
console.log('\n👋 Shutting down...');
|
|
147
|
-
if (currentStreamId) {
|
|
148
|
-
await stopManagedStream();
|
|
149
|
-
}
|
|
150
|
-
session.disconnect();
|
|
151
|
-
process.exit(0);
|
|
152
|
-
});
|
|
153
|
-
// Run the example
|
|
154
|
-
console.log('🚀 Managed RTMP Streaming Example');
|
|
155
|
-
console.log('==================================');
|
|
156
|
-
console.log('This example demonstrates zero-infrastructure streaming.');
|
|
157
|
-
console.log('No RTMP server needed - MentraOS handles everything!\n');
|
|
158
|
-
main().catch(console.error);
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Example: Managed RTMP Streaming with Re-streaming to Multiple Platforms
|
|
4
|
-
*
|
|
5
|
-
* This example demonstrates how to use the managed streaming feature with
|
|
6
|
-
* automatic re-streaming to platforms like YouTube, Twitch, and Facebook.
|
|
7
|
-
*
|
|
8
|
-
* The cloud handles all RTMP endpoints and automatically forwards your stream
|
|
9
|
-
* to the specified destinations.
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const __1 = require("../");
|
|
13
|
-
class MultiPlatformStreamingApp extends __1.AppServer {
|
|
14
|
-
constructor() {
|
|
15
|
-
super({
|
|
16
|
-
packageName: 'com.example.multiplatform-streaming',
|
|
17
|
-
apiKey: process.env.MENTRAOS_API_KEY || 'your-api-key',
|
|
18
|
-
port: 3000
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
async onSession(session, sessionId, userId) {
|
|
22
|
-
console.log(`New session started: ${sessionId} for user ${userId}`);
|
|
23
|
-
// Subscribe to managed stream status updates
|
|
24
|
-
const managedStreamCleanup = session.camera.onManagedStreamStatus((status) => {
|
|
25
|
-
console.log(`Stream status: ${status.status}`);
|
|
26
|
-
// Check output statuses
|
|
27
|
-
if (status.outputs && status.outputs.length > 0) {
|
|
28
|
-
console.log('Re-stream outputs:');
|
|
29
|
-
status.outputs.forEach(output => {
|
|
30
|
-
console.log(`- ${output.name || output.url}: ${output.status}`);
|
|
31
|
-
if (output.error) {
|
|
32
|
-
console.error(` Error: ${output.error}`);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
if (status.status === 'active') {
|
|
37
|
-
console.log('Stream is live!');
|
|
38
|
-
console.log('HLS URL:', status.hlsUrl);
|
|
39
|
-
console.log('DASH URL:', status.dashUrl);
|
|
40
|
-
session.layouts.showTextWall('Multi-platform stream is live!');
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
// Start managed stream when glasses connect
|
|
44
|
-
const connectCleanup = session.events.onConnected(async () => {
|
|
45
|
-
console.log('Glasses connected! Starting multi-platform stream...');
|
|
46
|
-
session.layouts.showTextWall('Starting multi-platform stream...');
|
|
47
|
-
try {
|
|
48
|
-
const streamResult = await session.camera.startManagedStream({
|
|
49
|
-
quality: '720p',
|
|
50
|
-
enableWebRTC: true,
|
|
51
|
-
// NEW: Add re-streaming destinations
|
|
52
|
-
restreamDestinations: [
|
|
53
|
-
{
|
|
54
|
-
url: 'rtmp://a.rtmp.youtube.com/live2/YOUR-YOUTUBE-STREAM-KEY',
|
|
55
|
-
name: 'YouTube'
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
url: 'rtmp://live.twitch.tv/app/YOUR-TWITCH-STREAM-KEY',
|
|
59
|
-
name: 'Twitch'
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
url: 'rtmps://live-api-s.facebook.com:443/rtmp/YOUR-FACEBOOK-STREAM-KEY',
|
|
63
|
-
name: 'Facebook'
|
|
64
|
-
}
|
|
65
|
-
],
|
|
66
|
-
// Optional: Custom encoding settings
|
|
67
|
-
video: {
|
|
68
|
-
width: 1280,
|
|
69
|
-
height: 720,
|
|
70
|
-
bitrate: 2000000, // 2 Mbps
|
|
71
|
-
frameRate: 30
|
|
72
|
-
},
|
|
73
|
-
audio: {
|
|
74
|
-
bitrate: 128000, // 128 kbps
|
|
75
|
-
sampleRate: 48000,
|
|
76
|
-
echoCancellation: true,
|
|
77
|
-
noiseSuppression: true
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
console.log('Managed stream started successfully!');
|
|
81
|
-
console.log('Stream ID:', streamResult.streamId);
|
|
82
|
-
console.log('HLS URL:', streamResult.hlsUrl);
|
|
83
|
-
console.log('DASH URL:', streamResult.dashUrl);
|
|
84
|
-
console.log('WebRTC URL:', streamResult.webrtcUrl);
|
|
85
|
-
// The stream is now being:
|
|
86
|
-
// 1. Sent from glasses to the RTMP relay
|
|
87
|
-
// 2. Forwarded to Cloudflare for HLS/DASH distribution
|
|
88
|
-
// 3. Re-streamed to YouTube, Twitch, and Facebook automatically
|
|
89
|
-
}
|
|
90
|
-
catch (error) {
|
|
91
|
-
console.error('Failed to start managed stream:', error);
|
|
92
|
-
session.layouts.showTextWall(`Failed to start stream: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
// Stop stream when disconnected
|
|
96
|
-
const disconnectCleanup = session.events.onDisconnected(async () => {
|
|
97
|
-
console.log('Glasses disconnected, stopping stream...');
|
|
98
|
-
try {
|
|
99
|
-
await session.camera.stopManagedStream();
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
console.error('Error stopping stream:', error);
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
// Register cleanup handlers
|
|
106
|
-
this.addCleanupHandler(managedStreamCleanup);
|
|
107
|
-
this.addCleanupHandler(connectCleanup);
|
|
108
|
-
this.addCleanupHandler(disconnectCleanup);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
// Start the app server
|
|
112
|
-
const app = new MultiPlatformStreamingApp();
|
|
113
|
-
app.start().catch(console.error);
|
|
114
|
-
// Important notes:
|
|
115
|
-
//
|
|
116
|
-
// 1. Stream Keys: Replace YOUR-*-STREAM-KEY with actual stream keys from each platform
|
|
117
|
-
// 2. Platform Requirements: Each platform has specific requirements:
|
|
118
|
-
// - YouTube: Requires 720p+ resolution, 30fps+, 2.5-4 Mbps bitrate
|
|
119
|
-
// - Twitch: Flexible, but recommends 3-6 Mbps for 1080p
|
|
120
|
-
// - Facebook: Supports up to 1080p, recommends 4 Mbps
|
|
121
|
-
//
|
|
122
|
-
// 3. The RTMP relay automatically transcodes your stream to meet platform requirements
|
|
123
|
-
// 4. You can monitor the status of each output in the ManagedStreamStatus updates
|
|
124
|
-
// 5. If an output fails, the main stream and other outputs continue working
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const session_1 = require("../app/session");
|
|
4
|
-
// import type { StreamStatus } from '../app/session/modules/streaming';
|
|
5
|
-
// Initialize App session
|
|
6
|
-
const session = new session_1.AppSession({
|
|
7
|
-
packageName: 'com.example.streaming-demo',
|
|
8
|
-
apiKey: 'your-api-key',
|
|
9
|
-
userId: 'example-user@example.com',
|
|
10
|
-
appServer: {}, // In a real app, this would be a AppServer instance
|
|
11
|
-
// In a real app, this would be the production server URL
|
|
12
|
-
mentraOSWebsocketUrl: 'ws://localhost:8002/app-ws'
|
|
13
|
-
});
|
|
14
|
-
// Connect to MentraOS Cloud
|
|
15
|
-
async function startApp() {
|
|
16
|
-
try {
|
|
17
|
-
// Connect with a session ID
|
|
18
|
-
await session.connect('streaming-demo-session');
|
|
19
|
-
console.log('Connected to MentraOS Cloud');
|
|
20
|
-
// Set up status handler
|
|
21
|
-
setupStreamStatusHandler();
|
|
22
|
-
// Request a stream
|
|
23
|
-
await requestStream();
|
|
24
|
-
// After some time, stop the stream
|
|
25
|
-
setTimeout(stopStream, 60000); // 1 minute
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
console.error('Error starting app:', error);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
// Set up handler for stream status updates
|
|
32
|
-
function setupStreamStatusHandler() {
|
|
33
|
-
// Register a handler for stream status updates
|
|
34
|
-
const cleanup = session.camera.onStreamStatus((status) => {
|
|
35
|
-
console.log(`Stream status: ${status.status}`);
|
|
36
|
-
// Log detailed information if available
|
|
37
|
-
if (status.stats) {
|
|
38
|
-
console.log(`Stream stats:
|
|
39
|
-
Bitrate: ${status.stats.bitrate} bps
|
|
40
|
-
FPS: ${status.stats.fps}
|
|
41
|
-
Dropped frames: ${status.stats.droppedFrames}
|
|
42
|
-
Duration: ${status.stats.duration} seconds
|
|
43
|
-
`);
|
|
44
|
-
}
|
|
45
|
-
// Handle different status types
|
|
46
|
-
switch (status.status) {
|
|
47
|
-
case 'initializing':
|
|
48
|
-
console.log('Stream is initializing...');
|
|
49
|
-
break;
|
|
50
|
-
case 'streaming':
|
|
51
|
-
console.log('Stream is actively streaming!');
|
|
52
|
-
break;
|
|
53
|
-
case 'active':
|
|
54
|
-
console.log('Stream is active and running!');
|
|
55
|
-
break;
|
|
56
|
-
case 'error':
|
|
57
|
-
console.error(`Stream error: ${status.errorDetails}`);
|
|
58
|
-
break;
|
|
59
|
-
case 'stopped':
|
|
60
|
-
console.log('Stream has stopped');
|
|
61
|
-
// Clean up resources or update UI as needed
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
// Store the cleanup function somewhere if you need to unregister later
|
|
66
|
-
// For this example, we'll just let it run for the lifetime of the app
|
|
67
|
-
}
|
|
68
|
-
// Request an RTMP stream
|
|
69
|
-
async function requestStream() {
|
|
70
|
-
try {
|
|
71
|
-
// Request a stream with configuration
|
|
72
|
-
await session.camera.startStream({
|
|
73
|
-
rtmpUrl: 'rtmp://your-rtmp-server.com/live/stream-key',
|
|
74
|
-
video: {
|
|
75
|
-
width: 1280,
|
|
76
|
-
height: 720,
|
|
77
|
-
bitrate: 1500000, // 1.5 Mbps
|
|
78
|
-
frameRate: 30
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
console.log('Stream request sent successfully');
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
console.error('Error requesting stream:', error);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
// Stop the stream
|
|
88
|
-
async function stopStream() {
|
|
89
|
-
try {
|
|
90
|
-
await session.camera.stopStream();
|
|
91
|
-
console.log('Stop stream request sent successfully');
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
console.error('Error stopping stream:', error);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// Error handling
|
|
98
|
-
session.events.on('error', (error) => {
|
|
99
|
-
console.error('Session error:', error);
|
|
100
|
-
});
|
|
101
|
-
// Start the app
|
|
102
|
-
startApp();
|
package/dist/logging/logger.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.logger = void 0;
|
|
7
|
-
const pino_1 = __importDefault(require("pino"));
|
|
8
|
-
// Constants and configuration
|
|
9
|
-
const BETTERSTACK_SOURCE_TOKEN = process.env.BETTERSTACK_SOURCE_TOKEN;
|
|
10
|
-
const BETTERSTACK_ENDPOINT = process.env.BETTERSTACK_ENDPOINT || 'https://s1311181.eu-nbg-2.betterstackdata.com';
|
|
11
|
-
const NODE_ENV = process.env.NODE_ENV || 'development';
|
|
12
|
-
const PORTER_APP_NAME = process.env.PORTER_APP_NAME || 'cloud-local';
|
|
13
|
-
// Determine log level based on environment
|
|
14
|
-
const LOG_LEVEL = NODE_ENV === 'production' ? 'info' : 'debug';
|
|
15
|
-
// Setup streams array for Pino multistream
|
|
16
|
-
const streams = [];
|
|
17
|
-
// Use pretty print in development for better readability
|
|
18
|
-
// if (PRETTY_PRINT && NODE_ENV !== 'production') {
|
|
19
|
-
// Pretty transport for development
|
|
20
|
-
const prettyTransport = pino_1.default.transport({
|
|
21
|
-
target: 'pino-pretty',
|
|
22
|
-
options: {
|
|
23
|
-
colorize: true,
|
|
24
|
-
translateTime: 'SYS:standard',
|
|
25
|
-
ignore: 'pid,hostname,env,module,server',
|
|
26
|
-
messageFormat: '{msg}',
|
|
27
|
-
errorProps: '*',
|
|
28
|
-
customPrettifiers: {
|
|
29
|
-
// Add custom prettifiers here if needed
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
streams.push({
|
|
34
|
-
stream: prettyTransport,
|
|
35
|
-
level: LOG_LEVEL,
|
|
36
|
-
});
|
|
37
|
-
// } else {
|
|
38
|
-
// // Plain console in production (JSON format)
|
|
39
|
-
// streams.push({
|
|
40
|
-
// stream: process.stdout,
|
|
41
|
-
// level: LOG_LEVEL,
|
|
42
|
-
// });
|
|
43
|
-
// }
|
|
44
|
-
// Add BetterStack transport if token is provided
|
|
45
|
-
if (BETTERSTACK_SOURCE_TOKEN) {
|
|
46
|
-
const betterStackTransport = pino_1.default.transport({
|
|
47
|
-
target: '@logtail/pino',
|
|
48
|
-
options: {
|
|
49
|
-
sourceToken: BETTERSTACK_SOURCE_TOKEN,
|
|
50
|
-
options: { endpoint: BETTERSTACK_ENDPOINT },
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
streams.push({
|
|
54
|
-
stream: betterStackTransport,
|
|
55
|
-
level: LOG_LEVEL,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
// Create multistream
|
|
59
|
-
const multistream = pino_1.default.multistream(streams);
|
|
60
|
-
/**
|
|
61
|
-
* Configuration for the root logger
|
|
62
|
-
*/
|
|
63
|
-
const baseLoggerOptions = {
|
|
64
|
-
level: LOG_LEVEL,
|
|
65
|
-
base: {
|
|
66
|
-
env: NODE_ENV,
|
|
67
|
-
server: PORTER_APP_NAME,
|
|
68
|
-
},
|
|
69
|
-
timestamp: pino_1.default.stdTimeFunctions.isoTime,
|
|
70
|
-
};
|
|
71
|
-
// Create the root logger with multiple streams
|
|
72
|
-
exports.logger = (0, pino_1.default)(baseLoggerOptions, multistream);
|
|
73
|
-
// Flush logger on process exit
|
|
74
|
-
// process.on('beforeExit', async () => {
|
|
75
|
-
// logger.flush(); // Flush the root logger
|
|
76
|
-
// console.log('Logger flushed before exit');
|
|
77
|
-
// });
|
|
78
|
-
// Default export is the logger
|
|
79
|
-
exports.default = exports.logger;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Capability Discovery Types
|
|
4
|
-
*
|
|
5
|
-
* Defines the structure for device capability profiles that Apps can query
|
|
6
|
-
* to determine what hardware and software features are available on the
|
|
7
|
-
* connected smart glasses.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DashboardMode = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Dashboard modes supported by the system
|
|
6
|
-
*/
|
|
7
|
-
var DashboardMode;
|
|
8
|
-
(function (DashboardMode) {
|
|
9
|
-
DashboardMode["MAIN"] = "main";
|
|
10
|
-
DashboardMode["EXPANDED"] = "expanded";
|
|
11
|
-
// ALWAYS_ON = 'always_on' // Persistent minimal dashboard
|
|
12
|
-
})(DashboardMode || (exports.DashboardMode = DashboardMode = {}));
|
package/dist/types/enums.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// src/enums.ts
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.HardwareRequirementLevel = exports.HardwareType = exports.AppSettingType = exports.ViewType = exports.LayoutType = exports.AppType = void 0;
|
|
5
|
-
/**
|
|
6
|
-
* Types of Third-Party Applications (Apps)
|
|
7
|
-
*/
|
|
8
|
-
var AppType;
|
|
9
|
-
(function (AppType) {
|
|
10
|
-
AppType["SYSTEM_DASHBOARD"] = "system_dashboard";
|
|
11
|
-
AppType["BACKGROUND"] = "background";
|
|
12
|
-
AppType["STANDARD"] = "standard";
|
|
13
|
-
})(AppType || (exports.AppType = AppType = {}));
|
|
14
|
-
/**
|
|
15
|
-
* Types of layouts for displaying content
|
|
16
|
-
*/
|
|
17
|
-
var LayoutType;
|
|
18
|
-
(function (LayoutType) {
|
|
19
|
-
LayoutType["TEXT_WALL"] = "text_wall";
|
|
20
|
-
LayoutType["DOUBLE_TEXT_WALL"] = "double_text_wall";
|
|
21
|
-
LayoutType["DASHBOARD_CARD"] = "dashboard_card";
|
|
22
|
-
LayoutType["REFERENCE_CARD"] = "reference_card";
|
|
23
|
-
LayoutType["BITMAP_VIEW"] = "bitmap_view";
|
|
24
|
-
LayoutType["BITMAP_ANIMATION"] = "bitmap_animation";
|
|
25
|
-
LayoutType["CLEAR_VIEW"] = "clear_view";
|
|
26
|
-
})(LayoutType || (exports.LayoutType = LayoutType = {}));
|
|
27
|
-
/**
|
|
28
|
-
* Types of views for displaying content
|
|
29
|
-
*/
|
|
30
|
-
var ViewType;
|
|
31
|
-
(function (ViewType) {
|
|
32
|
-
ViewType["DASHBOARD"] = "dashboard";
|
|
33
|
-
// ALWAYS_ON = "always_on", // Persistent overlay dashboard
|
|
34
|
-
ViewType["MAIN"] = "main";
|
|
35
|
-
})(ViewType || (exports.ViewType = ViewType = {}));
|
|
36
|
-
// Types for AppSettings
|
|
37
|
-
var AppSettingType;
|
|
38
|
-
(function (AppSettingType) {
|
|
39
|
-
AppSettingType["TOGGLE"] = "toggle";
|
|
40
|
-
AppSettingType["TEXT"] = "text";
|
|
41
|
-
AppSettingType["SELECT"] = "select";
|
|
42
|
-
AppSettingType["SLIDER"] = "slider";
|
|
43
|
-
AppSettingType["GROUP"] = "group";
|
|
44
|
-
AppSettingType["TEXT_NO_SAVE_BUTTON"] = "text_no_save_button";
|
|
45
|
-
AppSettingType["SELECT_WITH_SEARCH"] = "select_with_search";
|
|
46
|
-
AppSettingType["MULTISELECT"] = "multiselect";
|
|
47
|
-
AppSettingType["TITLE_VALUE"] = "titleValue";
|
|
48
|
-
AppSettingType["NUMERIC_INPUT"] = "numeric_input";
|
|
49
|
-
AppSettingType["TIME_PICKER"] = "time_picker";
|
|
50
|
-
})(AppSettingType || (exports.AppSettingType = AppSettingType = {}));
|
|
51
|
-
// | { type: "toggle"; key: string; label: string; defaultValue: boolean }
|
|
52
|
-
// | { type: "text"; key: string; label: string; defaultValue?: string }
|
|
53
|
-
// | { type: "select"; key: string; label: string; options: { label: string; value: string }[]; defaultValue?: string };
|
|
54
|
-
/**
|
|
55
|
-
* Types of hardware components that apps can require
|
|
56
|
-
*/
|
|
57
|
-
var HardwareType;
|
|
58
|
-
(function (HardwareType) {
|
|
59
|
-
HardwareType["CAMERA"] = "CAMERA";
|
|
60
|
-
HardwareType["DISPLAY"] = "DISPLAY";
|
|
61
|
-
HardwareType["MICROPHONE"] = "MICROPHONE";
|
|
62
|
-
HardwareType["SPEAKER"] = "SPEAKER";
|
|
63
|
-
HardwareType["IMU"] = "IMU";
|
|
64
|
-
HardwareType["BUTTON"] = "BUTTON";
|
|
65
|
-
HardwareType["LIGHT"] = "LIGHT";
|
|
66
|
-
HardwareType["WIFI"] = "WIFI";
|
|
67
|
-
})(HardwareType || (exports.HardwareType = HardwareType = {}));
|
|
68
|
-
/**
|
|
69
|
-
* Levels of hardware requirements
|
|
70
|
-
*/
|
|
71
|
-
var HardwareRequirementLevel;
|
|
72
|
-
(function (HardwareRequirementLevel) {
|
|
73
|
-
HardwareRequirementLevel["REQUIRED"] = "REQUIRED";
|
|
74
|
-
HardwareRequirementLevel["OPTIONAL"] = "OPTIONAL";
|
|
75
|
-
})(HardwareRequirementLevel || (exports.HardwareRequirementLevel = HardwareRequirementLevel = {}));
|