@camstack/addon-go2rtc 0.1.14 → 0.1.16

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.
@@ -1,41 +1,14 @@
1
1
  "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/go2rtc.addon.ts
21
- var go2rtc_addon_exports = {};
22
- __export(go2rtc_addon_exports, {
23
- Go2rtcAddon: () => Go2rtcAddon
24
- });
25
- module.exports = __toCommonJS(go2rtc_addon_exports);
26
- var import_node_child_process = require("child_process");
27
- var import_node_fs = require("fs");
28
- var import_node_path = require("path");
29
- var import_types2 = require("@camstack/types");
30
-
31
- // src/go2rtc-engine.ts
32
- var import_types = require("@camstack/types");
33
- var Go2rtcEngine = class {
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const node_child_process = require("node:child_process");
4
+ const node_fs = require("node:fs");
5
+ const node_path = require("node:path");
6
+ const types = require("@camstack/types");
7
+ class Go2rtcEngine {
34
8
  constructor(config) {
35
9
  this.config = config;
36
10
  this.baseUrl = `http://127.0.0.1:${config.apiPort}`;
37
11
  }
38
- config;
39
12
  baseUrl;
40
13
  streams = /* @__PURE__ */ new Map();
41
14
  async initialize(_config) {
@@ -46,7 +19,7 @@ var Go2rtcEngine = class {
46
19
  }
47
20
  } catch (err) {
48
21
  throw new Error(
49
- `Failed to reach go2rtc at ${this.baseUrl}: ${(0, import_types.errMsg)(err)}`,
22
+ `Failed to reach go2rtc at ${this.baseUrl}: ${types.errMsg(err)}`,
50
23
  { cause: err }
51
24
  );
52
25
  }
@@ -108,9 +81,7 @@ var Go2rtcEngine = class {
108
81
  if (!this.streams.has(streamId)) return null;
109
82
  return { active: true, viewers: 0 };
110
83
  }
111
- };
112
-
113
- // src/go2rtc-config-generator.ts
84
+ }
114
85
  function generateGo2rtcConfig(config) {
115
86
  const yaml = `
116
87
  api:
@@ -127,10 +98,8 @@ streams: {}
127
98
  `;
128
99
  return yaml.trim();
129
100
  }
130
-
131
- // src/go2rtc-downloader.ts
132
- var GO2RTC_VERSION = "1.9.14";
133
- var BASE_URL = `https://github.com/AlexxIT/go2rtc/releases/download/v${GO2RTC_VERSION}`;
101
+ const GO2RTC_VERSION = "1.9.14";
102
+ const BASE_URL = `https://github.com/AlexxIT/go2rtc/releases/download/v${GO2RTC_VERSION}`;
134
103
  function getGo2rtcDownloadUrl() {
135
104
  const os = process.platform;
136
105
  const rawArch = process.arch;
@@ -171,9 +140,7 @@ async function ensureGo2rtcBinary(deps) {
171
140
  archiveFormat
172
141
  });
173
142
  }
174
-
175
- // src/go2rtc.addon.ts
176
- var Go2rtcAddon = class extends import_types2.BaseAddon {
143
+ class Go2rtcAddon extends types.BaseAddon {
177
144
  /** IRestreamer identity */
178
145
  id = "go2rtc";
179
146
  name = "go2rtc Restreamer";
@@ -193,10 +160,10 @@ var Go2rtcAddon = class extends import_types2.BaseAddon {
193
160
  binaryPath: resolvedBinaryPath
194
161
  };
195
162
  const configYaml = generateGo2rtcConfig(processConfig);
196
- const configPath = (0, import_node_path.join)(dataPath, "go2rtc.yaml");
197
- (0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(configPath), { recursive: true });
198
- (0, import_node_fs.writeFileSync)(configPath, configYaml);
199
- this.childProc = (0, import_node_child_process.spawn)(processConfig.binaryPath, ["-config", configPath], {
163
+ const configPath = node_path.join(dataPath, "go2rtc.yaml");
164
+ node_fs.mkdirSync(node_path.dirname(configPath), { recursive: true });
165
+ node_fs.writeFileSync(configPath, configYaml);
166
+ this.childProc = node_child_process.spawn(processConfig.binaryPath, ["-config", configPath], {
200
167
  stdio: ["pipe", "pipe", "pipe"]
201
168
  });
202
169
  this.childProc.on("exit", (code, signal) => {
@@ -224,9 +191,9 @@ var Go2rtcAddon = class extends import_types2.BaseAddon {
224
191
  meta: { pid: this.childProc.pid, apiPort: processConfig.apiPort }
225
192
  });
226
193
  return [
227
- { capability: import_types2.streamingEngineCapability, provider: this.engine },
228
- { capability: import_types2.restreamerCapability, provider: this },
229
- { capability: import_types2.webrtcCapability, provider: this }
194
+ { capability: types.streamingEngineCapability, provider: this.engine },
195
+ { capability: types.restreamerCapability, provider: this },
196
+ { capability: types.webrtcCapability, provider: this }
230
197
  ];
231
198
  }
232
199
  async onShutdown() {
@@ -245,7 +212,7 @@ var Go2rtcAddon = class extends import_types2.BaseAddon {
245
212
  // --- IRestreamer implementation ---
246
213
  async registerDevice(deviceId, streams) {
247
214
  if (!this.engine) {
248
- throw new Error("go2rtc not initialized \u2014 cannot register device");
215
+ throw new Error("go2rtc not initialized cannot register device");
249
216
  }
250
217
  const streamIds = [];
251
218
  for (const stream of streams) {
@@ -310,7 +277,7 @@ var Go2rtcAddon = class extends import_types2.BaseAddon {
310
277
  }
311
278
  async proxyWhepOffer(streamId, sdpOffer) {
312
279
  if (!this.engine) {
313
- throw new Error("go2rtc not initialized \u2014 cannot proxy WHEP");
280
+ throw new Error("go2rtc not initialized cannot proxy WHEP");
314
281
  }
315
282
  return this.engine.proxyWhepOffer(streamId, sdpOffer);
316
283
  }
@@ -318,7 +285,7 @@ var Go2rtcAddon = class extends import_types2.BaseAddon {
318
285
  // --- IWebRtcProvider implementation ---
319
286
  async handleOffer(streamId, sdpOffer) {
320
287
  if (!this.engine) {
321
- throw new Error("go2rtc not initialized \u2014 cannot handle WebRTC offer");
288
+ throw new Error("go2rtc not initialized cannot handle WebRTC offer");
322
289
  }
323
290
  return this.engine.proxyWhepOffer(streamId, sdpOffer);
324
291
  }
@@ -436,9 +403,8 @@ var Go2rtcAddon = class extends import_types2.BaseAddon {
436
403
  ]
437
404
  });
438
405
  }
439
- };
440
- // Annotate the CommonJS export names for ESM import in node:
441
- 0 && (module.exports = {
442
- Go2rtcAddon
443
- });
444
- //# sourceMappingURL=go2rtc.addon.js.map
406
+ }
407
+ exports.Go2rtcAddon = Go2rtcAddon;
408
+ exports.Go2rtcEngine = Go2rtcEngine;
409
+ exports.generateGo2rtcConfig = generateGo2rtcConfig;
410
+ //# sourceMappingURL=go2rtc.addon.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/go2rtc.addon.ts","../src/go2rtc-engine.ts","../src/go2rtc-config-generator.ts","../src/go2rtc-downloader.ts"],"sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { join, dirname } from 'node:path'\nimport type {\n ProviderRegistration,\n IRestreamer,\n RegisteredStream,\n RestreamerExposedResource as ExposedResource,\n EncodedPacket,\n} from '@camstack/types'\nimport { BaseAddon, streamingEngineCapability, restreamerCapability, webrtcCapability } from '@camstack/types'\nimport type { IWebRtcProvider } from '@camstack/types'\nimport { Go2rtcEngine } from './go2rtc-engine'\nimport type { Go2rtcConfig } from './go2rtc-engine'\nimport { generateGo2rtcConfig } from './go2rtc-config-generator'\nimport { ensureGo2rtcBinary } from './go2rtc-downloader'\n\nexport interface Go2rtcProcessConfig {\n readonly apiPort: number\n readonly rtspPort: number\n readonly webrtcPort: number\n readonly binaryPath: string\n}\n\ninterface DeviceRegistration {\n readonly deviceId: number\n readonly streams: readonly RegisteredStream[]\n /** The original source URL registered with go2rtc (for cleanup) */\n readonly streamIds: readonly string[]\n}\n\nexport class Go2rtcAddon extends BaseAddon<Go2rtcProcessConfig> implements IRestreamer, IWebRtcProvider {\n /** IRestreamer identity */\n readonly id = 'go2rtc'\n readonly name = 'go2rtc Restreamer'\n\n private engine: Go2rtcEngine | null = null\n private childProc: ChildProcess | null = null\n private readonly registeredDevices = new Map<number, DeviceRegistration>()\n\n constructor() {\n super({ apiPort: 1984, rtspPort: 8554, webrtcPort: 8555, binaryPath: 'go2rtc' })\n }\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n const dataPath = await this.ctx.api.storage.resolve.query({ location: 'data', relativePath: '' })\n .catch(() => 'camstack-data')\n\n const resolvedBinaryPath = await ensureGo2rtcBinary(this.ctx.deps)\n\n const processConfig: Go2rtcProcessConfig = {\n apiPort: this.config.apiPort,\n rtspPort: this.config.rtspPort,\n webrtcPort: this.config.webrtcPort,\n binaryPath: resolvedBinaryPath,\n }\n\n // Generate config file\n const configYaml = generateGo2rtcConfig(processConfig)\n const configPath = join(dataPath, 'go2rtc.yaml')\n mkdirSync(dirname(configPath), { recursive: true })\n writeFileSync(configPath, configYaml)\n\n // Start go2rtc as a child process\n this.childProc = spawn(processConfig.binaryPath, ['-config', configPath], {\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n this.childProc.on('exit', (code, signal) => {\n this.ctx.logger.warn('go2rtc process exited', { meta: { code, signal } })\n })\n\n this.childProc.stderr?.on('data', (data: Buffer) => {\n const msg = data.toString().trim()\n if (msg) this.ctx.logger.debug('go2rtc stderr', { meta: { line: msg } })\n })\n\n this.childProc.stdout?.on('data', (data: Buffer) => {\n const msg = data.toString().trim()\n if (msg) this.ctx.logger.debug('go2rtc stdout', { meta: { line: msg } })\n })\n\n // Wait for API to be ready\n const apiUrl = `http://127.0.0.1:${processConfig.apiPort}/api/streams`\n await this.waitForReady(apiUrl, 10_000)\n\n // Create engine\n const engineConfig: Go2rtcConfig = {\n apiPort: processConfig.apiPort,\n rtspPort: processConfig.rtspPort,\n webrtcPort: processConfig.webrtcPort,\n binaryPath: processConfig.binaryPath,\n }\n this.engine = new Go2rtcEngine(engineConfig)\n await this.engine.initialize()\n\n this.ctx.logger.info('go2rtc started', {\n meta: { pid: this.childProc.pid, apiPort: processConfig.apiPort },\n })\n\n return [\n { capability: streamingEngineCapability, provider: this.engine },\n { capability: restreamerCapability, provider: this },\n { capability: webrtcCapability, provider: this },\n ]\n }\n\n protected async onShutdown(): Promise<void> {\n await this.engine?.shutdown()\n this.engine = null\n this.registeredDevices.clear()\n\n if (this.childProc) {\n this.childProc.kill('SIGTERM')\n this.childProc = null\n }\n }\n\n getEngine(): Go2rtcEngine {\n if (!this.engine) throw new Error('go2rtc not initialized')\n return this.engine\n }\n\n // --- IRestreamer implementation ---\n\n async registerDevice(deviceId: number, streams: readonly RegisteredStream[]): Promise<void> {\n if (!this.engine) {\n throw new Error('go2rtc not initialized — cannot register device')\n }\n\n const streamIds: string[] = []\n\n for (const stream of streams) {\n streamIds.push(stream.streamId)\n\n // Register the stream with go2rtc using the broker's local TCP URL.\n // The broker is the sole reader from the camera; go2rtc consumes the\n // broker's TCP pipe instead of connecting to the camera directly.\n if (stream.sourceUrl) {\n await this.engine.registerStream(stream.streamId, {\n url: `ffmpeg:${stream.sourceUrl}#video=${stream.codec}`,\n protocol: 'rtsp',\n deviceId: `${deviceId}`,\n providerId: 'broker',\n })\n }\n }\n\n this.registeredDevices.set(deviceId, {\n deviceId,\n streams,\n streamIds,\n })\n }\n\n pushPacket(_streamId: string, _packet: EncodedPacket): void {\n // Packet push from the broker is a no-op — go2rtc reads directly from\n // the broker's local TCP pipe server instead.\n }\n\n async unregisterDevice(deviceId: number): Promise<void> {\n const registration = this.registeredDevices.get(deviceId)\n if (!registration) {\n return\n }\n\n if (this.engine) {\n for (const streamId of registration.streamIds) {\n try {\n await this.engine.unregisterStream(streamId)\n } catch {\n // Best-effort cleanup\n }\n }\n }\n\n this.registeredDevices.delete(deviceId)\n }\n\n getExposedResources(deviceId: number): readonly ExposedResource[] {\n const registration = this.registeredDevices.get(deviceId)\n if (!registration || !this.engine) {\n return []\n }\n\n const resources: ExposedResource[] = []\n\n for (const streamId of registration.streamIds) {\n const webrtcUrl = this.engine.getStreamUrl(streamId, 'webrtc')\n if (webrtcUrl) {\n resources.push({ type: 'url', format: 'webrtc', value: webrtcUrl })\n }\n\n const hlsUrl = this.engine.getStreamUrl(streamId, 'hls')\n if (hlsUrl) {\n resources.push({ type: 'url', format: 'hls', value: hlsUrl })\n }\n\n const mjpegUrl = this.engine.getStreamUrl(streamId, 'mjpeg')\n if (mjpegUrl) {\n resources.push({ type: 'url', format: 'mjpeg', value: mjpegUrl })\n }\n\n const rtspUrl = this.engine.getStreamUrl(streamId, 'rtsp')\n if (rtspUrl) {\n resources.push({ type: 'url', format: 'rtsp', value: rtspUrl })\n }\n }\n\n return resources\n }\n\n async proxyWhepOffer(streamId: string, sdpOffer: string): Promise<string> {\n if (!this.engine) {\n throw new Error('go2rtc not initialized — cannot proxy WHEP')\n }\n return this.engine.proxyWhepOffer(streamId, sdpOffer)\n }\n\n // --- End IRestreamer ---\n\n // --- IWebRtcProvider implementation ---\n\n async handleOffer(streamId: string, sdpOffer: string): Promise<string> {\n if (!this.engine) {\n throw new Error('go2rtc not initialized — cannot handle WebRTC offer')\n }\n return this.engine.proxyWhepOffer(streamId, sdpOffer)\n }\n\n supportsStream(streamId: string): boolean {\n const prefix = streamId.split('/')[0]\n if (!prefix) return false\n const deviceId = Number(prefix)\n return Number.isFinite(deviceId) && this.registeredDevices.has(deviceId)\n }\n\n async registerStream(streamId: string, _codec: string): Promise<void> {\n // Stream registration is handled via registerDevice (IRestreamer).\n // This is a no-op since go2rtc manages streams through its own API.\n const prefix = streamId.split('/')[0]\n if (!prefix) return\n const deviceId = Number(prefix)\n if (!Number.isFinite(deviceId)) return\n if (!this.registeredDevices.has(deviceId)) {\n this.registeredDevices.set(deviceId, {\n deviceId,\n streams: [{ streamId, label: streamId, codec: _codec, type: 'video' }],\n streamIds: [streamId],\n })\n }\n }\n\n async unregisterStream(streamId: string): Promise<void> {\n if (!this.engine) {\n return\n }\n try {\n await this.engine.unregisterStream(streamId)\n } catch {\n // Best-effort cleanup\n }\n }\n\n /**\n * go2rtc does not implement adaptive bitrate — it proxies the source\n * stream at its native resolution/bitrate. Use addon-webrtc-adaptive\n * for clients that need dynamic quality adjustment.\n */\n hasAdaptiveBitrate(_streamId: string): boolean {\n return false\n }\n\n // --- End IWebRtcProvider ---\n\n /** Exposed for testing */\n async waitForReady(url: string, timeoutMs: number): Promise<void> {\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n try {\n const res = await fetch(url)\n if (res.ok) return\n } catch {\n // Not ready yet\n }\n await new Promise((r) => setTimeout(r, 500))\n }\n throw new Error(`go2rtc did not become ready within ${timeoutMs}ms`)\n }\n\n protected globalSettingsSchema() {\n return this.schema({\n sections: [\n {\n id: 'go2rtc-info',\n title: 'go2rtc',\n fields: [\n {\n type: 'info' as const,\n key: 'binary-info',\n label: 'Binary',\n content: 'go2rtc is automatically downloaded on first boot.',\n variant: 'info' as const,\n },\n ],\n },\n {\n id: 'go2rtc-ports',\n title: 'Network Ports',\n description: 'Port configuration. Changes require a restart.',\n columns: 3,\n fields: [\n {\n type: 'info' as const,\n key: 'restart-note',\n label: 'Restart required',\n content: 'Port changes require restarting go2rtc.',\n variant: 'warning' as const,\n },\n this.field({\n type: 'number', key: 'apiPort', label: 'API Port',\n description: 'go2rtc HTTP API', min: 1024, max: 65535, step: 1, default: 1984,\n }),\n this.field({\n type: 'number', key: 'rtspPort', label: 'RTSP Port',\n description: 'RTSP restream output', min: 1024, max: 65535, step: 1, default: 8554,\n }),\n this.field({\n type: 'number', key: 'webrtcPort', label: 'WebRTC Port',\n description: 'WebRTC UDP/TCP', min: 1024, max: 65535, step: 1, default: 8555,\n }),\n ],\n },\n ],\n })\n }\n\n}\n","import { errMsg } from '@camstack/types'\nimport type {\n IStreamingEngine,\n StreamFormat,\n StreamInfo,\n StreamingSource,\n StreamStatus,\n} from '@camstack/types'\n\nexport interface Go2rtcConfig {\n readonly apiPort: number\n readonly rtspPort: number\n readonly webrtcPort: number\n readonly binaryPath?: string\n}\n\nexport class Go2rtcEngine implements IStreamingEngine {\n private readonly baseUrl: string\n private readonly streams = new Map<string, StreamingSource>()\n\n constructor(private readonly config: Go2rtcConfig) {\n this.baseUrl = `http://127.0.0.1:${config.apiPort}`\n }\n\n async initialize(_config?: Record<string, unknown>): Promise<void> {\n try {\n const res = await fetch(`${this.baseUrl}/api/streams`)\n if (!res.ok) {\n throw new Error(`go2rtc API returned ${res.status}`)\n }\n } catch (err) {\n throw new Error(\n `Failed to reach go2rtc at ${this.baseUrl}: ${errMsg(err)}`,\n { cause: err },\n )\n }\n }\n\n async shutdown(): Promise<void> {\n this.streams.clear()\n }\n\n async registerStream(streamId: string, source: StreamingSource): Promise<void> {\n const url = `${this.baseUrl}/api/streams?src=${encodeURIComponent(streamId)}&url=${encodeURIComponent(source.url)}`\n const res = await fetch(url, { method: 'PUT' })\n if (!res.ok) {\n throw new Error(`go2rtc registerStream failed: ${res.status}`)\n }\n this.streams.set(streamId, source)\n }\n\n async unregisterStream(streamId: string): Promise<void> {\n const url = `${this.baseUrl}/api/streams?src=${encodeURIComponent(streamId)}`\n const res = await fetch(url, { method: 'DELETE' })\n if (!res.ok) {\n throw new Error(`go2rtc unregisterStream failed: ${res.status}`)\n }\n this.streams.delete(streamId)\n }\n\n getStreamUrl(streamId: string, format: StreamFormat): string | null {\n const encoded = encodeURIComponent(streamId)\n switch (format) {\n case 'webrtc':\n return `${this.baseUrl}/api/webrtc?src=${encoded}`\n case 'hls':\n return `${this.baseUrl}/api/stream.m3u8?src=${encoded}`\n case 'mjpeg':\n return `${this.baseUrl}/api/frame.jpeg?src=${encoded}`\n case 'rtsp':\n return `rtsp://127.0.0.1:${this.config.rtspPort}/${streamId}`\n default:\n return null\n }\n }\n\n async proxyWhepOffer(streamId: string, sdpOffer: string): Promise<string> {\n const url = `${this.baseUrl}/api/webrtc?src=${encodeURIComponent(streamId)}`\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/sdp' },\n body: sdpOffer,\n })\n if (!res.ok) {\n throw new Error(`go2rtc WHEP failed: ${res.status}`)\n }\n return res.text()\n }\n\n listStreams(): StreamInfo[] {\n return [...this.streams.entries()].map(([id, source]) => ({\n streamId: id,\n source,\n formats: ['webrtc', 'hls', 'mjpeg', 'rtsp'] as StreamFormat[],\n }))\n }\n\n getStreamStatus(streamId: string): StreamStatus | null {\n if (!this.streams.has(streamId)) return null\n return { active: true, viewers: 0 }\n }\n}\n","export interface Go2rtcGeneratedConfig {\n api: { listen: string }\n rtsp: { listen: string }\n webrtc: { listen: string }\n streams: Record<string, string[]>\n}\n\nexport function generateGo2rtcConfig(config: {\n apiPort: number\n rtspPort: number\n webrtcPort: number\n}): string {\n const yaml = `\napi:\n listen: \":${config.apiPort}\"\n\nrtsp:\n listen: \":${config.rtspPort}\"\n\nwebrtc:\n listen: \":${config.webrtcPort}\"\n ice_servers: []\n\nstreams: {}\n`\n return yaml.trim()\n}\n","/**\n * Auto-download go2rtc binary for the current platform.\n * Uses IAddonDepsManager (ctx.deps) for binary management.\n */\nimport type { IAddonDepsManager } from '@camstack/types'\n\nconst GO2RTC_VERSION = '1.9.14'\nconst BASE_URL = `https://github.com/AlexxIT/go2rtc/releases/download/v${GO2RTC_VERSION}`\n\nfunction getGo2rtcDownloadUrl(): { url: string; isArchive: boolean; archiveFormat?: 'zip' } {\n const os = process.platform\n const rawArch = process.arch\n\n let arch: string\n switch (rawArch) {\n case 'x64': arch = 'amd64'; break\n case 'arm64': arch = 'arm64'; break\n case 'arm': arch = 'arm'; break\n case 'ia32': arch = 'i386'; break\n default: throw new Error(`Unsupported architecture: ${rawArch}`)\n }\n\n switch (os) {\n case 'darwin':\n return { url: `${BASE_URL}/go2rtc_mac_${arch}.zip`, isArchive: true, archiveFormat: 'zip' }\n case 'linux':\n return { url: `${BASE_URL}/go2rtc_linux_${arch}`, isArchive: false }\n case 'win32':\n return { url: `${BASE_URL}/go2rtc_win_${arch}.zip`, isArchive: true, archiveFormat: 'zip' }\n default:\n throw new Error(`Unsupported platform: ${os}`)\n }\n}\n\n/**\n * Ensure go2rtc binary is available.\n * Returns the absolute path to the binary.\n */\nexport async function ensureGo2rtcBinary(deps: IAddonDepsManager): Promise<string> {\n const { url, isArchive, archiveFormat } = getGo2rtcDownloadUrl()\n\n return deps.ensureBinary({\n name: 'go2rtc',\n downloadUrl: url,\n isArchive,\n archiveFormat,\n })\n}\n"],"mappings":"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","names":["import_types"]}
1
+ {"version":3,"file":"go2rtc.addon.js","sources":["../src/go2rtc-engine.ts","../src/go2rtc-config-generator.ts","../src/go2rtc-downloader.ts","../src/go2rtc.addon.ts"],"sourcesContent":["import { errMsg } from '@camstack/types'\nimport type {\n IStreamingEngine,\n StreamFormat,\n StreamInfo,\n StreamingSource,\n StreamStatus,\n} from '@camstack/types'\n\nexport interface Go2rtcConfig {\n readonly apiPort: number\n readonly rtspPort: number\n readonly webrtcPort: number\n readonly binaryPath?: string\n}\n\nexport class Go2rtcEngine implements IStreamingEngine {\n private readonly baseUrl: string\n private readonly streams = new Map<string, StreamingSource>()\n\n constructor(private readonly config: Go2rtcConfig) {\n this.baseUrl = `http://127.0.0.1:${config.apiPort}`\n }\n\n async initialize(_config?: Record<string, unknown>): Promise<void> {\n try {\n const res = await fetch(`${this.baseUrl}/api/streams`)\n if (!res.ok) {\n throw new Error(`go2rtc API returned ${res.status}`)\n }\n } catch (err) {\n throw new Error(\n `Failed to reach go2rtc at ${this.baseUrl}: ${errMsg(err)}`,\n { cause: err },\n )\n }\n }\n\n async shutdown(): Promise<void> {\n this.streams.clear()\n }\n\n async registerStream(streamId: string, source: StreamingSource): Promise<void> {\n const url = `${this.baseUrl}/api/streams?src=${encodeURIComponent(streamId)}&url=${encodeURIComponent(source.url)}`\n const res = await fetch(url, { method: 'PUT' })\n if (!res.ok) {\n throw new Error(`go2rtc registerStream failed: ${res.status}`)\n }\n this.streams.set(streamId, source)\n }\n\n async unregisterStream(streamId: string): Promise<void> {\n const url = `${this.baseUrl}/api/streams?src=${encodeURIComponent(streamId)}`\n const res = await fetch(url, { method: 'DELETE' })\n if (!res.ok) {\n throw new Error(`go2rtc unregisterStream failed: ${res.status}`)\n }\n this.streams.delete(streamId)\n }\n\n getStreamUrl(streamId: string, format: StreamFormat): string | null {\n const encoded = encodeURIComponent(streamId)\n switch (format) {\n case 'webrtc':\n return `${this.baseUrl}/api/webrtc?src=${encoded}`\n case 'hls':\n return `${this.baseUrl}/api/stream.m3u8?src=${encoded}`\n case 'mjpeg':\n return `${this.baseUrl}/api/frame.jpeg?src=${encoded}`\n case 'rtsp':\n return `rtsp://127.0.0.1:${this.config.rtspPort}/${streamId}`\n default:\n return null\n }\n }\n\n async proxyWhepOffer(streamId: string, sdpOffer: string): Promise<string> {\n const url = `${this.baseUrl}/api/webrtc?src=${encodeURIComponent(streamId)}`\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/sdp' },\n body: sdpOffer,\n })\n if (!res.ok) {\n throw new Error(`go2rtc WHEP failed: ${res.status}`)\n }\n return res.text()\n }\n\n listStreams(): StreamInfo[] {\n return [...this.streams.entries()].map(([id, source]) => ({\n streamId: id,\n source,\n formats: ['webrtc', 'hls', 'mjpeg', 'rtsp'] as StreamFormat[],\n }))\n }\n\n getStreamStatus(streamId: string): StreamStatus | null {\n if (!this.streams.has(streamId)) return null\n return { active: true, viewers: 0 }\n }\n}\n","export interface Go2rtcGeneratedConfig {\n api: { listen: string }\n rtsp: { listen: string }\n webrtc: { listen: string }\n streams: Record<string, string[]>\n}\n\nexport function generateGo2rtcConfig(config: {\n apiPort: number\n rtspPort: number\n webrtcPort: number\n}): string {\n const yaml = `\napi:\n listen: \":${config.apiPort}\"\n\nrtsp:\n listen: \":${config.rtspPort}\"\n\nwebrtc:\n listen: \":${config.webrtcPort}\"\n ice_servers: []\n\nstreams: {}\n`\n return yaml.trim()\n}\n","/**\n * Auto-download go2rtc binary for the current platform.\n * Uses IAddonDepsManager (ctx.deps) for binary management.\n */\nimport type { IAddonDepsManager } from '@camstack/types'\n\nconst GO2RTC_VERSION = '1.9.14'\nconst BASE_URL = `https://github.com/AlexxIT/go2rtc/releases/download/v${GO2RTC_VERSION}`\n\nfunction getGo2rtcDownloadUrl(): { url: string; isArchive: boolean; archiveFormat?: 'zip' } {\n const os = process.platform\n const rawArch = process.arch\n\n let arch: string\n switch (rawArch) {\n case 'x64': arch = 'amd64'; break\n case 'arm64': arch = 'arm64'; break\n case 'arm': arch = 'arm'; break\n case 'ia32': arch = 'i386'; break\n default: throw new Error(`Unsupported architecture: ${rawArch}`)\n }\n\n switch (os) {\n case 'darwin':\n return { url: `${BASE_URL}/go2rtc_mac_${arch}.zip`, isArchive: true, archiveFormat: 'zip' }\n case 'linux':\n return { url: `${BASE_URL}/go2rtc_linux_${arch}`, isArchive: false }\n case 'win32':\n return { url: `${BASE_URL}/go2rtc_win_${arch}.zip`, isArchive: true, archiveFormat: 'zip' }\n default:\n throw new Error(`Unsupported platform: ${os}`)\n }\n}\n\n/**\n * Ensure go2rtc binary is available.\n * Returns the absolute path to the binary.\n */\nexport async function ensureGo2rtcBinary(deps: IAddonDepsManager): Promise<string> {\n const { url, isArchive, archiveFormat } = getGo2rtcDownloadUrl()\n\n return deps.ensureBinary({\n name: 'go2rtc',\n downloadUrl: url,\n isArchive,\n archiveFormat,\n })\n}\n","import { spawn, type ChildProcess } from 'node:child_process'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { join, dirname } from 'node:path'\nimport type {\n ProviderRegistration,\n IRestreamer,\n RegisteredStream,\n RestreamerExposedResource as ExposedResource,\n EncodedPacket,\n} from '@camstack/types'\nimport { BaseAddon, streamingEngineCapability, restreamerCapability, webrtcCapability } from '@camstack/types'\nimport type { IWebRtcProvider } from '@camstack/types'\nimport { Go2rtcEngine } from './go2rtc-engine'\nimport type { Go2rtcConfig } from './go2rtc-engine'\nimport { generateGo2rtcConfig } from './go2rtc-config-generator'\nimport { ensureGo2rtcBinary } from './go2rtc-downloader'\n\nexport interface Go2rtcProcessConfig {\n readonly apiPort: number\n readonly rtspPort: number\n readonly webrtcPort: number\n readonly binaryPath: string\n}\n\ninterface DeviceRegistration {\n readonly deviceId: number\n readonly streams: readonly RegisteredStream[]\n /** The original source URL registered with go2rtc (for cleanup) */\n readonly streamIds: readonly string[]\n}\n\nexport class Go2rtcAddon extends BaseAddon<Go2rtcProcessConfig> implements IRestreamer, IWebRtcProvider {\n /** IRestreamer identity */\n readonly id = 'go2rtc'\n readonly name = 'go2rtc Restreamer'\n\n private engine: Go2rtcEngine | null = null\n private childProc: ChildProcess | null = null\n private readonly registeredDevices = new Map<number, DeviceRegistration>()\n\n constructor() {\n super({ apiPort: 1984, rtspPort: 8554, webrtcPort: 8555, binaryPath: 'go2rtc' })\n }\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n const dataPath = await this.ctx.api.storage.resolve.query({ location: 'data', relativePath: '' })\n .catch(() => 'camstack-data')\n\n const resolvedBinaryPath = await ensureGo2rtcBinary(this.ctx.deps)\n\n const processConfig: Go2rtcProcessConfig = {\n apiPort: this.config.apiPort,\n rtspPort: this.config.rtspPort,\n webrtcPort: this.config.webrtcPort,\n binaryPath: resolvedBinaryPath,\n }\n\n // Generate config file\n const configYaml = generateGo2rtcConfig(processConfig)\n const configPath = join(dataPath, 'go2rtc.yaml')\n mkdirSync(dirname(configPath), { recursive: true })\n writeFileSync(configPath, configYaml)\n\n // Start go2rtc as a child process\n this.childProc = spawn(processConfig.binaryPath, ['-config', configPath], {\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n this.childProc.on('exit', (code, signal) => {\n this.ctx.logger.warn('go2rtc process exited', { meta: { code, signal } })\n })\n\n this.childProc.stderr?.on('data', (data: Buffer) => {\n const msg = data.toString().trim()\n if (msg) this.ctx.logger.debug('go2rtc stderr', { meta: { line: msg } })\n })\n\n this.childProc.stdout?.on('data', (data: Buffer) => {\n const msg = data.toString().trim()\n if (msg) this.ctx.logger.debug('go2rtc stdout', { meta: { line: msg } })\n })\n\n // Wait for API to be ready\n const apiUrl = `http://127.0.0.1:${processConfig.apiPort}/api/streams`\n await this.waitForReady(apiUrl, 10_000)\n\n // Create engine\n const engineConfig: Go2rtcConfig = {\n apiPort: processConfig.apiPort,\n rtspPort: processConfig.rtspPort,\n webrtcPort: processConfig.webrtcPort,\n binaryPath: processConfig.binaryPath,\n }\n this.engine = new Go2rtcEngine(engineConfig)\n await this.engine.initialize()\n\n this.ctx.logger.info('go2rtc started', {\n meta: { pid: this.childProc.pid, apiPort: processConfig.apiPort },\n })\n\n return [\n { capability: streamingEngineCapability, provider: this.engine },\n { capability: restreamerCapability, provider: this },\n { capability: webrtcCapability, provider: this },\n ]\n }\n\n protected async onShutdown(): Promise<void> {\n await this.engine?.shutdown()\n this.engine = null\n this.registeredDevices.clear()\n\n if (this.childProc) {\n this.childProc.kill('SIGTERM')\n this.childProc = null\n }\n }\n\n getEngine(): Go2rtcEngine {\n if (!this.engine) throw new Error('go2rtc not initialized')\n return this.engine\n }\n\n // --- IRestreamer implementation ---\n\n async registerDevice(deviceId: number, streams: readonly RegisteredStream[]): Promise<void> {\n if (!this.engine) {\n throw new Error('go2rtc not initialized — cannot register device')\n }\n\n const streamIds: string[] = []\n\n for (const stream of streams) {\n streamIds.push(stream.streamId)\n\n // Register the stream with go2rtc using the broker's local TCP URL.\n // The broker is the sole reader from the camera; go2rtc consumes the\n // broker's TCP pipe instead of connecting to the camera directly.\n if (stream.sourceUrl) {\n await this.engine.registerStream(stream.streamId, {\n url: `ffmpeg:${stream.sourceUrl}#video=${stream.codec}`,\n protocol: 'rtsp',\n deviceId: `${deviceId}`,\n providerId: 'broker',\n })\n }\n }\n\n this.registeredDevices.set(deviceId, {\n deviceId,\n streams,\n streamIds,\n })\n }\n\n pushPacket(_streamId: string, _packet: EncodedPacket): void {\n // Packet push from the broker is a no-op — go2rtc reads directly from\n // the broker's local TCP pipe server instead.\n }\n\n async unregisterDevice(deviceId: number): Promise<void> {\n const registration = this.registeredDevices.get(deviceId)\n if (!registration) {\n return\n }\n\n if (this.engine) {\n for (const streamId of registration.streamIds) {\n try {\n await this.engine.unregisterStream(streamId)\n } catch {\n // Best-effort cleanup\n }\n }\n }\n\n this.registeredDevices.delete(deviceId)\n }\n\n getExposedResources(deviceId: number): readonly ExposedResource[] {\n const registration = this.registeredDevices.get(deviceId)\n if (!registration || !this.engine) {\n return []\n }\n\n const resources: ExposedResource[] = []\n\n for (const streamId of registration.streamIds) {\n const webrtcUrl = this.engine.getStreamUrl(streamId, 'webrtc')\n if (webrtcUrl) {\n resources.push({ type: 'url', format: 'webrtc', value: webrtcUrl })\n }\n\n const hlsUrl = this.engine.getStreamUrl(streamId, 'hls')\n if (hlsUrl) {\n resources.push({ type: 'url', format: 'hls', value: hlsUrl })\n }\n\n const mjpegUrl = this.engine.getStreamUrl(streamId, 'mjpeg')\n if (mjpegUrl) {\n resources.push({ type: 'url', format: 'mjpeg', value: mjpegUrl })\n }\n\n const rtspUrl = this.engine.getStreamUrl(streamId, 'rtsp')\n if (rtspUrl) {\n resources.push({ type: 'url', format: 'rtsp', value: rtspUrl })\n }\n }\n\n return resources\n }\n\n async proxyWhepOffer(streamId: string, sdpOffer: string): Promise<string> {\n if (!this.engine) {\n throw new Error('go2rtc not initialized — cannot proxy WHEP')\n }\n return this.engine.proxyWhepOffer(streamId, sdpOffer)\n }\n\n // --- End IRestreamer ---\n\n // --- IWebRtcProvider implementation ---\n\n async handleOffer(streamId: string, sdpOffer: string): Promise<string> {\n if (!this.engine) {\n throw new Error('go2rtc not initialized — cannot handle WebRTC offer')\n }\n return this.engine.proxyWhepOffer(streamId, sdpOffer)\n }\n\n supportsStream(streamId: string): boolean {\n const prefix = streamId.split('/')[0]\n if (!prefix) return false\n const deviceId = Number(prefix)\n return Number.isFinite(deviceId) && this.registeredDevices.has(deviceId)\n }\n\n async registerStream(streamId: string, _codec: string): Promise<void> {\n // Stream registration is handled via registerDevice (IRestreamer).\n // This is a no-op since go2rtc manages streams through its own API.\n const prefix = streamId.split('/')[0]\n if (!prefix) return\n const deviceId = Number(prefix)\n if (!Number.isFinite(deviceId)) return\n if (!this.registeredDevices.has(deviceId)) {\n this.registeredDevices.set(deviceId, {\n deviceId,\n streams: [{ streamId, label: streamId, codec: _codec, type: 'video' }],\n streamIds: [streamId],\n })\n }\n }\n\n async unregisterStream(streamId: string): Promise<void> {\n if (!this.engine) {\n return\n }\n try {\n await this.engine.unregisterStream(streamId)\n } catch {\n // Best-effort cleanup\n }\n }\n\n /**\n * go2rtc does not implement adaptive bitrate — it proxies the source\n * stream at its native resolution/bitrate. Use addon-webrtc-adaptive\n * for clients that need dynamic quality adjustment.\n */\n hasAdaptiveBitrate(_streamId: string): boolean {\n return false\n }\n\n // --- End IWebRtcProvider ---\n\n /** Exposed for testing */\n async waitForReady(url: string, timeoutMs: number): Promise<void> {\n const start = Date.now()\n while (Date.now() - start < timeoutMs) {\n try {\n const res = await fetch(url)\n if (res.ok) return\n } catch {\n // Not ready yet\n }\n await new Promise((r) => setTimeout(r, 500))\n }\n throw new Error(`go2rtc did not become ready within ${timeoutMs}ms`)\n }\n\n protected globalSettingsSchema() {\n return this.schema({\n sections: [\n {\n id: 'go2rtc-info',\n title: 'go2rtc',\n fields: [\n {\n type: 'info' as const,\n key: 'binary-info',\n label: 'Binary',\n content: 'go2rtc is automatically downloaded on first boot.',\n variant: 'info' as const,\n },\n ],\n },\n {\n id: 'go2rtc-ports',\n title: 'Network Ports',\n description: 'Port configuration. Changes require a restart.',\n columns: 3,\n fields: [\n {\n type: 'info' as const,\n key: 'restart-note',\n label: 'Restart required',\n content: 'Port changes require restarting go2rtc.',\n variant: 'warning' as const,\n },\n this.field({\n type: 'number', key: 'apiPort', label: 'API Port',\n description: 'go2rtc HTTP API', min: 1024, max: 65535, step: 1, default: 1984,\n }),\n this.field({\n type: 'number', key: 'rtspPort', label: 'RTSP Port',\n description: 'RTSP restream output', min: 1024, max: 65535, step: 1, default: 8554,\n }),\n this.field({\n type: 'number', key: 'webrtcPort', label: 'WebRTC Port',\n description: 'WebRTC UDP/TCP', min: 1024, max: 65535, step: 1, default: 8555,\n }),\n ],\n },\n ],\n })\n }\n\n}\n"],"names":["errMsg","BaseAddon","join","mkdirSync","dirname","writeFileSync","spawn","streamingEngineCapability","restreamerCapability","webrtcCapability"],"mappings":"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"}