camstreamerlib 4.0.0-beta.120 → 4.0.0-beta.122

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.
@@ -2870,7 +2870,13 @@ export declare class CamStreamerAPI<Client extends IClient<TResponse, any>> exte
2870
2870
  streamIdentifier?: string | undefined;
2871
2871
  }>;
2872
2872
  setStream(streamId: string, streamData: TStream, options?: THttpRequestOptions): Promise<void>;
2873
- isStreaming(streamId: string, options?: THttpRequestOptions): Promise<boolean>;
2873
+ getStreamStats(streamId: number, options?: THttpRequestOptions): Promise<{
2874
+ net_stats: string;
2875
+ stream_bytes_time_ms: number;
2876
+ stream_bytes: number;
2877
+ start_count: number;
2878
+ is_streaming: number;
2879
+ }>;
2874
2880
  setStreamEnabled(streamId: string, enabled: boolean, options?: THttpRequestOptions): Promise<void>;
2875
2881
  setStreamActive(streamId: string, active: boolean, options?: THttpRequestOptions): Promise<void>;
2876
2882
  listFiles(options?: THttpRequestOptions): Promise<{
@@ -91,9 +91,9 @@ class CamStreamerAPI extends BasicAPI_1.BasicAPI {
91
91
  stream_id: streamId,
92
92
  }, options);
93
93
  }
94
- async isStreaming(streamId, options) {
94
+ async getStreamStats(streamId, options) {
95
95
  const res = await this._getJson(`${BASE_PATH}/get_streamstat.cgi`, { stream_id: streamId }, options);
96
- return res.data.is_streaming === 1;
96
+ return CamStreamerAPI_1.streamStatsSchema.parse(res.data);
97
97
  }
98
98
  async setStreamEnabled(streamId, enabled, options) {
99
99
  await this._postUrlEncoded(`${BASE_PATH}/set_stream_enabled.cgi`, { stream_id: streamId, enabled: enabled ? 1 : 0 }, options);
package/cjs/VapixAPI.d.ts CHANGED
@@ -1,17 +1,13 @@
1
- import { IClient, TParameters, TResponse } from './internal/types';
1
+ import { IClient, TResponse } from './internal/types';
2
2
  import { TAudioDevice, TPortSetSchema, TPortSequenceStateSchema } from './types/VapixAPI';
3
- import { ProxyClient } from './internal/ProxyClient';
4
- import { TCameraImageConfig, THttpRequestOptions, TProxyParams } from './types/common';
5
- export declare class VapixAPI<Client extends IClient<TResponse, any>> {
6
- private client;
3
+ import { TCameraImageConfig, THttpRequestOptions } from './types/common';
4
+ import { BasicAPI } from './internal/BasicAPI';
5
+ export declare class VapixAPI<Client extends IClient<TResponse, any>> extends BasicAPI<Client> {
7
6
  private CustomFormData;
8
7
  constructor(client: Client, CustomFormData?: {
9
8
  new (form?: HTMLFormElement | undefined, submitter?: HTMLElement | null | undefined): FormData;
10
9
  prototype: FormData;
11
10
  });
12
- getClient(proxyParams?: TProxyParams): Client | ProxyClient<Client>;
13
- postUrlEncoded(path: string, parameters?: TParameters, headers?: Record<string, string>, options?: THttpRequestOptions): Promise<TResponse>;
14
- postJson(path: string, jsonData: Record<string, any>, headers?: Record<string, string>, options?: THttpRequestOptions): Promise<TResponse>;
15
11
  getCameraImage(parameters: TCameraImageConfig, options?: THttpRequestOptions): Promise<ReturnType<Client["get"]>>;
16
12
  getEventDeclarations(options?: THttpRequestOptions): Promise<string>;
17
13
  getSupportedAudioSampleRate(options?: THttpRequestOptions): Promise<{
@@ -28,7 +24,7 @@ export declare class VapixAPI<Client extends IClient<TResponse, any>> {
28
24
  unmountSDCard(options?: THttpRequestOptions): Promise<number>;
29
25
  private _doSDCardMountAction;
30
26
  fetchSDCardJobProgress(jobId: number, options?: THttpRequestOptions): Promise<number>;
31
- downloadCameraReport(options?: THttpRequestOptions): Promise<TResponse>;
27
+ downloadCameraReport(options?: THttpRequestOptions): Promise<string>;
32
28
  getSystemLog(options?: THttpRequestOptions): Promise<TResponse>;
33
29
  getMaxFps(channel: number, options?: THttpRequestOptions): Promise<number>;
34
30
  getTimezone(options?: THttpRequestOptions): Promise<string>;
package/cjs/VapixAPI.js CHANGED
@@ -4,39 +4,15 @@ exports.VapixAPI = void 0;
4
4
  const utils_1 = require("./internal/utils");
5
5
  const VapixAPI_1 = require("./types/VapixAPI");
6
6
  const errors_1 = require("./errors/errors");
7
- const ProxyClient_1 = require("./internal/ProxyClient");
8
7
  const zod_1 = require("zod");
9
8
  const fast_xml_parser_1 = require("fast-xml-parser");
10
- class VapixAPI {
11
- client;
9
+ const BasicAPI_1 = require("./internal/BasicAPI");
10
+ class VapixAPI extends BasicAPI_1.BasicAPI {
12
11
  CustomFormData;
13
12
  constructor(client, CustomFormData = FormData) {
14
- this.client = client;
13
+ super(client);
15
14
  this.CustomFormData = CustomFormData;
16
15
  }
17
- getClient(proxyParams) {
18
- return proxyParams ? new ProxyClient_1.ProxyClient(this.client, proxyParams) : this.client;
19
- }
20
- async postUrlEncoded(path, parameters, headers, options) {
21
- const data = (0, utils_1.paramToUrl)(parameters);
22
- const head = { ...headers, 'Content-Type': 'application/x-www-form-urlencoded' };
23
- const agent = this.getClient(options?.proxyParams);
24
- const res = await agent.post({ path, data, headers: head, timeout: options?.timeout });
25
- if (!res.ok) {
26
- throw new errors_1.ErrorWithResponse(res);
27
- }
28
- return res;
29
- }
30
- async postJson(path, jsonData, headers, options) {
31
- const data = JSON.stringify(jsonData);
32
- const head = { ...headers, 'Content-Type': 'application/json' };
33
- const agent = this.getClient(options?.proxyParams);
34
- const res = await agent.post({ path, data, headers: head, timeout: options?.timeout });
35
- if (!res.ok) {
36
- throw new errors_1.ErrorWithResponse(res);
37
- }
38
- return res;
39
- }
40
16
  async getCameraImage(parameters, options) {
41
17
  const agent = this.getClient(options?.proxyParams);
42
18
  return (await agent.get({
@@ -66,7 +42,7 @@ class VapixAPI {
66
42
  async getSupportedAudioSampleRate(options) {
67
43
  const path = '/axis-cgi/audio/streamingcapabilities.cgi';
68
44
  const jsonData = { apiVersion: '1.0', method: 'list' };
69
- const res = await this.postJson(path, jsonData, undefined, options);
45
+ const res = await this._postJsonEncoded(path, jsonData, undefined, options);
70
46
  const encoders = VapixAPI_1.audioSampleRatesResponseSchema.parse(await res.json()).data.encoders;
71
47
  const data = encoders.aac ?? encoders.AAC ?? [];
72
48
  return data.map((item) => {
@@ -89,19 +65,19 @@ class VapixAPI {
89
65
  ],
90
66
  },
91
67
  };
92
- await this.postJson('/axis-cgi/opticscontrol.cgi', data, undefined, options);
68
+ await this._postJsonEncoded('/axis-cgi/opticscontrol.cgi', data, undefined, options);
93
69
  }
94
70
  catch (err) {
95
- await this.postUrlEncoded('/axis-cgi/opticssetup.cgi', {
71
+ await this._postUrlEncoded('/axis-cgi/opticssetup.cgi', {
96
72
  autofocus: 'perform',
97
73
  source: '1',
98
- }, undefined, options);
74
+ }, options);
99
75
  }
100
76
  }
101
77
  async checkSDCard(options) {
102
- const res = await this.postUrlEncoded('/axis-cgi/disks/list.cgi', {
78
+ const res = await this._postUrlEncoded('/axis-cgi/disks/list.cgi', {
103
79
  diskid: 'SD_DISK',
104
- }, undefined, options);
80
+ }, options);
105
81
  const xmlText = await res.text();
106
82
  const parser = new fast_xml_parser_1.XMLParser({
107
83
  ignoreAttributes: false,
@@ -123,10 +99,10 @@ class VapixAPI {
123
99
  return this._doSDCardMountAction('UNMOUNT', options);
124
100
  }
125
101
  async _doSDCardMountAction(action, options) {
126
- const res = await this.postUrlEncoded('/axis-cgi/disks/mount.cgi', {
102
+ const res = await this._postUrlEncoded('/axis-cgi/disks/mount.cgi', {
127
103
  action: action,
128
104
  diskid: 'SD_DISK',
129
- }, undefined, options);
105
+ }, options);
130
106
  const textXml = await res.text();
131
107
  const parser = new fast_xml_parser_1.XMLParser({
132
108
  ignoreAttributes: false,
@@ -141,10 +117,10 @@ class VapixAPI {
141
117
  return Number(job.jobid);
142
118
  }
143
119
  async fetchSDCardJobProgress(jobId, options) {
144
- const res = await this.postUrlEncoded('/disks/job.cgi', {
120
+ const res = await this._postUrlEncoded('/disks/job.cgi', {
145
121
  jobid: String(jobId),
146
122
  diskid: 'SD_DISK',
147
- }, undefined, options);
123
+ }, options);
148
124
  const textXml = await res.text();
149
125
  const parser = new fast_xml_parser_1.XMLParser({
150
126
  ignoreAttributes: false,
@@ -158,14 +134,14 @@ class VapixAPI {
158
134
  return Number(job.progress);
159
135
  }
160
136
  downloadCameraReport(options) {
161
- return this.postUrlEncoded('/axis-cgi/serverreport.cgi', { mode: 'text' }, undefined, options);
137
+ return this._getText('/axis-cgi/serverreport.cgi', { mode: 'text' }, options);
162
138
  }
163
139
  getSystemLog(options) {
164
- return this.postUrlEncoded('/axis-cgi/admin/systemlog.cgi', undefined, undefined, options);
140
+ return this._postUrlEncoded('/axis-cgi/admin/systemlog.cgi', {}, options);
165
141
  }
166
142
  async getMaxFps(channel, options) {
167
143
  const data = { apiVersion: '1.0', method: 'getCaptureModes' };
168
- const res = await this.postJson('/axis-cgi/capturemode.cgi', data, undefined, options);
144
+ const res = await this._postJsonEncoded('/axis-cgi/capturemode.cgi', data, undefined, options);
169
145
  const response = VapixAPI_1.maxFpsResponseSchema.parse(await res.json());
170
146
  const channels = response.data;
171
147
  if (channels === undefined) {
@@ -211,12 +187,12 @@ class VapixAPI {
211
187
  }
212
188
  async getDateTimeInfo(options) {
213
189
  const data = { apiVersion: '1.0', method: 'getDateTimeInfo' };
214
- const res = await this.postJson('/axis-cgi/time.cgi', data, undefined, options);
190
+ const res = await this._postJsonEncoded('/axis-cgi/time.cgi', data, undefined, options);
215
191
  return VapixAPI_1.dateTimeinfoSchema.parse(await res.json());
216
192
  }
217
193
  async getDevicesSettings(options) {
218
194
  const data = { apiVersion: '1.0', method: 'getDevicesSettings' };
219
- const res = await this.postJson('/axis-cgi/audiodevicecontrol.cgi', data, undefined, options);
195
+ const res = await this._postJsonEncoded('/axis-cgi/audiodevicecontrol.cgi', data, undefined, options);
220
196
  const result = VapixAPI_1.audioDeviceRequestSchema.parse(await res.json());
221
197
  return result.data.devices.map((device) => ({
222
198
  ...device,
@@ -225,7 +201,7 @@ class VapixAPI {
225
201
  }));
226
202
  }
227
203
  async fetchRemoteDeviceInfo(payload, options) {
228
- const res = await this.postJson('/axis-cgi/basicdeviceinfo.cgi', payload, undefined, options);
204
+ const res = await this._postJsonEncoded('/axis-cgi/basicdeviceinfo.cgi', payload, undefined, options);
229
205
  const json = await res.json();
230
206
  if ((0, utils_1.isNullish)(json.data)) {
231
207
  throw new errors_1.NoDeviceInfoError();
@@ -234,25 +210,25 @@ class VapixAPI {
234
210
  }
235
211
  async getHeaders(options) {
236
212
  const data = { apiVersion: '1.0', method: 'list' };
237
- const res = await this.postJson('/axis-cgi/customhttpheader.cgi', data, undefined, options);
213
+ const res = await this._postJsonEncoded('/axis-cgi/customhttpheader.cgi', data, undefined, options);
238
214
  return zod_1.z.object({ data: zod_1.z.record(zod_1.z.string()) }).parse(await res.json()).data;
239
215
  }
240
216
  async setHeaders(headers, options) {
241
217
  const data = { apiVersion: '1.0', method: 'set', params: headers };
242
- return this.postJson('/axis-cgi/customhttpheader.cgi', data, undefined, options);
218
+ return this._postJsonEncoded('/axis-cgi/customhttpheader.cgi', data, undefined, options);
243
219
  }
244
220
  async getParameter(paramNames, options) {
245
- const response = await this.postUrlEncoded('/axis-cgi/param.cgi', {
221
+ const response = await this._postUrlEncoded('/axis-cgi/param.cgi', {
246
222
  action: 'list',
247
223
  group: (0, utils_1.arrayToUrl)(paramNames),
248
- }, undefined, options);
224
+ }, options);
249
225
  return VapixAPI.parseParameters(await response.text());
250
226
  }
251
227
  async setParameter(params, options) {
252
- const res = await this.postUrlEncoded('/axis-cgi/param.cgi', {
228
+ const res = await this._postUrlEncoded('/axis-cgi/param.cgi', {
253
229
  ...params,
254
230
  action: 'update',
255
- }, undefined, options);
231
+ }, options);
256
232
  const responseText = await res.text();
257
233
  if (responseText.startsWith('# Error')) {
258
234
  throw new errors_1.SettingParameterError(responseText);
@@ -300,10 +276,10 @@ class VapixAPI {
300
276
  return this.setParameter(params, options);
301
277
  }
302
278
  async getPTZPresetList(channel, options) {
303
- const res = await this.postUrlEncoded('/axis-cgi/com/ptz.cgi', {
279
+ const res = await this._postUrlEncoded('/axis-cgi/com/ptz.cgi', {
304
280
  query: 'presetposcam',
305
281
  camera: channel,
306
- }, undefined, options);
282
+ }, options);
307
283
  const text = await res.text();
308
284
  const lines = text.split(/[\r\n]/);
309
285
  const positions = [];
@@ -320,11 +296,11 @@ class VapixAPI {
320
296
  }
321
297
  async listPTZ(camera, options) {
322
298
  const url = `/axis-cgi/com/ptz.cgi`;
323
- const response = await this.postUrlEncoded(url, {
299
+ const response = await this._postUrlEncoded(url, {
324
300
  camera,
325
301
  query: 'presetposcamdata',
326
302
  format: 'json',
327
- }, undefined, options);
303
+ }, options);
328
304
  const text = await response.text();
329
305
  if (text === '') {
330
306
  throw new errors_1.PtzNotSupportedError();
@@ -332,10 +308,10 @@ class VapixAPI {
332
308
  return VapixAPI.parseCameraPtzResponse(text)[camera] ?? [];
333
309
  }
334
310
  async listPtzVideoSourceOverview(options) {
335
- const response = await this.postUrlEncoded('/axis-cgi/com/ptz.cgi', {
311
+ const response = await this._postUrlEncoded('/axis-cgi/com/ptz.cgi', {
336
312
  query: 'presetposall',
337
313
  format: 'json',
338
- }, undefined, options);
314
+ }, options);
339
315
  const text = await response.text();
340
316
  if (text === '') {
341
317
  throw new errors_1.PtzNotSupportedError();
@@ -353,16 +329,16 @@ class VapixAPI {
353
329
  return VapixAPI_1.ptzOverviewSchema.parse(res);
354
330
  }
355
331
  goToPreset(channel, presetName, options) {
356
- return this.postUrlEncoded('/axis-cgi/com/ptz.cgi', {
332
+ return this._postUrlEncoded('/axis-cgi/com/ptz.cgi', {
357
333
  camera: channel.toString(),
358
334
  gotoserverpresetname: presetName,
359
- }, undefined, options);
335
+ }, options);
360
336
  }
361
337
  async getPtzPosition(camera, options) {
362
- const res = await this.postUrlEncoded('/axis-cgi/com/ptz.cgi', {
338
+ const res = await this._postUrlEncoded('/axis-cgi/com/ptz.cgi', {
363
339
  query: 'position',
364
340
  camera: camera.toString(),
365
- }, undefined, options);
341
+ }, options);
366
342
  const params = VapixAPI.parseParameters(await res.text());
367
343
  return VapixAPI_1.cameraPTZItemDataSchema.parse({
368
344
  pan: Number(params.pan),
@@ -371,7 +347,7 @@ class VapixAPI {
371
347
  });
372
348
  }
373
349
  async getPorts(options) {
374
- const res = await this.postJson('/axis-cgi/io/portmanagement.cgi', {
350
+ const res = await this._postJsonEncoded('/axis-cgi/io/portmanagement.cgi', {
375
351
  apiVersion: '1.0',
376
352
  context: '',
377
353
  method: 'getPorts',
@@ -380,7 +356,7 @@ class VapixAPI {
380
356
  return portResponseParsed.data.items;
381
357
  }
382
358
  async setPorts(ports, options) {
383
- await this.postJson('/axis-cgi/io/portmanagement.cgi', {
359
+ await this._postJsonEncoded('/axis-cgi/io/portmanagement.cgi', {
384
360
  apiVersion: '1.0',
385
361
  context: '',
386
362
  method: 'setPorts',
@@ -388,7 +364,7 @@ class VapixAPI {
388
364
  }, undefined, options);
389
365
  }
390
366
  async setPortStateSequence(port, sequence, options) {
391
- await this.postJson('/axis-cgi/io/portmanagement.cgi', {
367
+ await this._postJsonEncoded('/axis-cgi/io/portmanagement.cgi', {
392
368
  apiVersion: '1.0',
393
369
  context: '',
394
370
  method: 'setStateSequence',
@@ -396,27 +372,27 @@ class VapixAPI {
396
372
  }, undefined, options);
397
373
  }
398
374
  async addCameraUser(username, pass, sgrp, comment, options) {
399
- return await this.postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
375
+ return await this._postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
400
376
  action: 'add',
401
377
  user: username,
402
378
  pwd: pass,
403
379
  grp: 'users',
404
380
  sgrp,
405
381
  comment,
406
- }, undefined, options);
382
+ }, options);
407
383
  }
408
384
  async getCameraUsers(options) {
409
- const res = await this.postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
385
+ const res = await this._postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
410
386
  action: 'get',
411
- }, undefined, options);
387
+ }, options);
412
388
  return await res.text();
413
389
  }
414
390
  async editCameraUser(username, pass, options) {
415
- return await this.postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
391
+ return await this._postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
416
392
  action: 'update',
417
393
  user: username,
418
394
  pwd: pass,
419
- }, undefined, options);
395
+ }, options);
420
396
  }
421
397
  async getApplicationList(options) {
422
398
  const agent = this.getClient(options?.proxyParams);
@@ -67,7 +67,7 @@ class BasicAPI {
67
67
  path,
68
68
  data: jsonData,
69
69
  parameters,
70
- headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
70
+ headers: { 'Content-Type': 'application/json' },
71
71
  timeout: options?.timeout,
72
72
  });
73
73
  if (res.ok) {
@@ -20256,3 +20256,23 @@ export declare const audioLocalSchema: z.ZodObject<{
20256
20256
  storage: "flash" | "SD0";
20257
20257
  }>;
20258
20258
  export type TAudioLocalType = z.infer<typeof audioLocalSchema>;
20259
+ export declare const streamStatsSchema: z.ZodObject<{
20260
+ net_stats: z.ZodString;
20261
+ stream_bytes_time_ms: z.ZodNumber;
20262
+ stream_bytes: z.ZodNumber;
20263
+ start_count: z.ZodNumber;
20264
+ is_streaming: z.ZodNumber;
20265
+ }, "strip", z.ZodTypeAny, {
20266
+ net_stats: string;
20267
+ stream_bytes_time_ms: number;
20268
+ stream_bytes: number;
20269
+ start_count: number;
20270
+ is_streaming: number;
20271
+ }, {
20272
+ net_stats: string;
20273
+ stream_bytes_time_ms: number;
20274
+ stream_bytes: number;
20275
+ start_count: number;
20276
+ is_streaming: number;
20277
+ }>;
20278
+ export type TStreamStats = z.infer<typeof streamStatsSchema>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.audioLocalSchema = exports.audioUrlSchema = exports.audioFileListSchema = exports.audioFileSchema = exports.storageListSchema = exports.audioFileStorageTypeSchema = exports.AudioType = exports.isYoutubeRtmpStream = exports.isGameChangerStream = exports.isMicrosoftStream = exports.isMicrosoftAzureStream = exports.isIbmStream = exports.isDailymotionStream = exports.isWowzaStream = exports.isHlsPushStream = exports.isHlsPullStream = exports.isDaCastStream = exports.isSrtStream = exports.isChurchStream = exports.isTwitchStream = exports.isVimeoStream = exports.isYouTubeStream = exports.isWindyStream = exports.isSdCardStream = exports.isRtmpStream = exports.isMpegDvbStream = exports.isFacebookStream = exports.streamListSchema = exports.streamSchema = void 0;
3
+ exports.streamStatsSchema = exports.audioLocalSchema = exports.audioUrlSchema = exports.audioFileListSchema = exports.audioFileSchema = exports.storageListSchema = exports.audioFileStorageTypeSchema = exports.AudioType = exports.isYoutubeRtmpStream = exports.isGameChangerStream = exports.isMicrosoftStream = exports.isMicrosoftAzureStream = exports.isIbmStream = exports.isDailymotionStream = exports.isWowzaStream = exports.isHlsPushStream = exports.isHlsPullStream = exports.isDaCastStream = exports.isSrtStream = exports.isChurchStream = exports.isTwitchStream = exports.isVimeoStream = exports.isYouTubeStream = exports.isWindyStream = exports.isSdCardStream = exports.isRtmpStream = exports.isMpegDvbStream = exports.isFacebookStream = exports.streamListSchema = exports.streamSchema = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const facebookSchema_1 = require("./facebookSchema");
6
6
  const windySchema_1 = require("./windySchema");
@@ -142,3 +142,10 @@ exports.audioLocalSchema = zod_1.z.object({
142
142
  name: zod_1.z.string(),
143
143
  storage: zod_1.z.enum(['flash', 'SD0']),
144
144
  });
145
+ exports.streamStatsSchema = zod_1.z.object({
146
+ net_stats: zod_1.z.string(),
147
+ stream_bytes_time_ms: zod_1.z.number(),
148
+ stream_bytes: zod_1.z.number(),
149
+ start_count: zod_1.z.number(),
150
+ is_streaming: zod_1.z.number(),
151
+ });
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { audioFileListSchema, storageListSchema, streamSchema, } from './types/CamStreamerAPI/CamStreamerAPI';
2
+ import { audioFileListSchema, storageListSchema, streamSchema, streamStatsSchema, } from './types/CamStreamerAPI/CamStreamerAPI';
3
3
  import { UtcTimeFetchError, WsAuthorizationError, MigrationError } from './errors/errors';
4
4
  import { oldStringStreamSchema, oldStringStreamSchemaWithId, } from './types/CamStreamerAPI/oldStreamSchema';
5
5
  import { BasicAPI } from './internal/BasicAPI';
@@ -88,9 +88,9 @@ export class CamStreamerAPI extends BasicAPI {
88
88
  stream_id: streamId,
89
89
  }, options);
90
90
  }
91
- async isStreaming(streamId, options) {
91
+ async getStreamStats(streamId, options) {
92
92
  const res = await this._getJson(`${BASE_PATH}/get_streamstat.cgi`, { stream_id: streamId }, options);
93
- return res.data.is_streaming === 1;
93
+ return streamStatsSchema.parse(res.data);
94
94
  }
95
95
  async setStreamEnabled(streamId, enabled, options) {
96
96
  await this._postUrlEncoded(`${BASE_PATH}/set_stream_enabled.cgi`, { stream_id: streamId, enabled: enabled ? 1 : 0 }, options);
package/esm/VapixAPI.js CHANGED
@@ -1,39 +1,15 @@
1
- import { arrayToUrl, isNullish, paramToUrl } from './internal/utils';
1
+ import { arrayToUrl, isNullish } from './internal/utils';
2
2
  import { sdCardWatchedStatuses, APP_IDS, maxFpsResponseSchema, dateTimeinfoSchema, audioDeviceRequestSchema, audioSampleRatesResponseSchema, timeZoneSchema, getPortsResponseSchema, guardTourSchema, ptzOverviewSchema, cameraPTZItemDataSchema, applicationListSchema, sdCardInfoSchema, } from './types/VapixAPI';
3
3
  import { ApplicationAPIError, MaxFPSError, NoDeviceInfoError, PtzNotSupportedError, ErrorWithResponse, SDCardActionError, SDCardJobError, SettingParameterError, TimezoneFetchError, TimezoneNotSetupError, } from './errors/errors';
4
- import { ProxyClient } from './internal/ProxyClient';
5
4
  import { z } from 'zod';
6
5
  import { XMLParser } from 'fast-xml-parser';
7
- export class VapixAPI {
8
- client;
6
+ import { BasicAPI } from './internal/BasicAPI';
7
+ export class VapixAPI extends BasicAPI {
9
8
  CustomFormData;
10
9
  constructor(client, CustomFormData = FormData) {
11
- this.client = client;
10
+ super(client);
12
11
  this.CustomFormData = CustomFormData;
13
12
  }
14
- getClient(proxyParams) {
15
- return proxyParams ? new ProxyClient(this.client, proxyParams) : this.client;
16
- }
17
- async postUrlEncoded(path, parameters, headers, options) {
18
- const data = paramToUrl(parameters);
19
- const head = { ...headers, 'Content-Type': 'application/x-www-form-urlencoded' };
20
- const agent = this.getClient(options?.proxyParams);
21
- const res = await agent.post({ path, data, headers: head, timeout: options?.timeout });
22
- if (!res.ok) {
23
- throw new ErrorWithResponse(res);
24
- }
25
- return res;
26
- }
27
- async postJson(path, jsonData, headers, options) {
28
- const data = JSON.stringify(jsonData);
29
- const head = { ...headers, 'Content-Type': 'application/json' };
30
- const agent = this.getClient(options?.proxyParams);
31
- const res = await agent.post({ path, data, headers: head, timeout: options?.timeout });
32
- if (!res.ok) {
33
- throw new ErrorWithResponse(res);
34
- }
35
- return res;
36
- }
37
13
  async getCameraImage(parameters, options) {
38
14
  const agent = this.getClient(options?.proxyParams);
39
15
  return (await agent.get({
@@ -63,7 +39,7 @@ export class VapixAPI {
63
39
  async getSupportedAudioSampleRate(options) {
64
40
  const path = '/axis-cgi/audio/streamingcapabilities.cgi';
65
41
  const jsonData = { apiVersion: '1.0', method: 'list' };
66
- const res = await this.postJson(path, jsonData, undefined, options);
42
+ const res = await this._postJsonEncoded(path, jsonData, undefined, options);
67
43
  const encoders = audioSampleRatesResponseSchema.parse(await res.json()).data.encoders;
68
44
  const data = encoders.aac ?? encoders.AAC ?? [];
69
45
  return data.map((item) => {
@@ -86,19 +62,19 @@ export class VapixAPI {
86
62
  ],
87
63
  },
88
64
  };
89
- await this.postJson('/axis-cgi/opticscontrol.cgi', data, undefined, options);
65
+ await this._postJsonEncoded('/axis-cgi/opticscontrol.cgi', data, undefined, options);
90
66
  }
91
67
  catch (err) {
92
- await this.postUrlEncoded('/axis-cgi/opticssetup.cgi', {
68
+ await this._postUrlEncoded('/axis-cgi/opticssetup.cgi', {
93
69
  autofocus: 'perform',
94
70
  source: '1',
95
- }, undefined, options);
71
+ }, options);
96
72
  }
97
73
  }
98
74
  async checkSDCard(options) {
99
- const res = await this.postUrlEncoded('/axis-cgi/disks/list.cgi', {
75
+ const res = await this._postUrlEncoded('/axis-cgi/disks/list.cgi', {
100
76
  diskid: 'SD_DISK',
101
- }, undefined, options);
77
+ }, options);
102
78
  const xmlText = await res.text();
103
79
  const parser = new XMLParser({
104
80
  ignoreAttributes: false,
@@ -120,10 +96,10 @@ export class VapixAPI {
120
96
  return this._doSDCardMountAction('UNMOUNT', options);
121
97
  }
122
98
  async _doSDCardMountAction(action, options) {
123
- const res = await this.postUrlEncoded('/axis-cgi/disks/mount.cgi', {
99
+ const res = await this._postUrlEncoded('/axis-cgi/disks/mount.cgi', {
124
100
  action: action,
125
101
  diskid: 'SD_DISK',
126
- }, undefined, options);
102
+ }, options);
127
103
  const textXml = await res.text();
128
104
  const parser = new XMLParser({
129
105
  ignoreAttributes: false,
@@ -138,10 +114,10 @@ export class VapixAPI {
138
114
  return Number(job.jobid);
139
115
  }
140
116
  async fetchSDCardJobProgress(jobId, options) {
141
- const res = await this.postUrlEncoded('/disks/job.cgi', {
117
+ const res = await this._postUrlEncoded('/disks/job.cgi', {
142
118
  jobid: String(jobId),
143
119
  diskid: 'SD_DISK',
144
- }, undefined, options);
120
+ }, options);
145
121
  const textXml = await res.text();
146
122
  const parser = new XMLParser({
147
123
  ignoreAttributes: false,
@@ -155,14 +131,14 @@ export class VapixAPI {
155
131
  return Number(job.progress);
156
132
  }
157
133
  downloadCameraReport(options) {
158
- return this.postUrlEncoded('/axis-cgi/serverreport.cgi', { mode: 'text' }, undefined, options);
134
+ return this._getText('/axis-cgi/serverreport.cgi', { mode: 'text' }, options);
159
135
  }
160
136
  getSystemLog(options) {
161
- return this.postUrlEncoded('/axis-cgi/admin/systemlog.cgi', undefined, undefined, options);
137
+ return this._postUrlEncoded('/axis-cgi/admin/systemlog.cgi', {}, options);
162
138
  }
163
139
  async getMaxFps(channel, options) {
164
140
  const data = { apiVersion: '1.0', method: 'getCaptureModes' };
165
- const res = await this.postJson('/axis-cgi/capturemode.cgi', data, undefined, options);
141
+ const res = await this._postJsonEncoded('/axis-cgi/capturemode.cgi', data, undefined, options);
166
142
  const response = maxFpsResponseSchema.parse(await res.json());
167
143
  const channels = response.data;
168
144
  if (channels === undefined) {
@@ -208,12 +184,12 @@ export class VapixAPI {
208
184
  }
209
185
  async getDateTimeInfo(options) {
210
186
  const data = { apiVersion: '1.0', method: 'getDateTimeInfo' };
211
- const res = await this.postJson('/axis-cgi/time.cgi', data, undefined, options);
187
+ const res = await this._postJsonEncoded('/axis-cgi/time.cgi', data, undefined, options);
212
188
  return dateTimeinfoSchema.parse(await res.json());
213
189
  }
214
190
  async getDevicesSettings(options) {
215
191
  const data = { apiVersion: '1.0', method: 'getDevicesSettings' };
216
- const res = await this.postJson('/axis-cgi/audiodevicecontrol.cgi', data, undefined, options);
192
+ const res = await this._postJsonEncoded('/axis-cgi/audiodevicecontrol.cgi', data, undefined, options);
217
193
  const result = audioDeviceRequestSchema.parse(await res.json());
218
194
  return result.data.devices.map((device) => ({
219
195
  ...device,
@@ -222,7 +198,7 @@ export class VapixAPI {
222
198
  }));
223
199
  }
224
200
  async fetchRemoteDeviceInfo(payload, options) {
225
- const res = await this.postJson('/axis-cgi/basicdeviceinfo.cgi', payload, undefined, options);
201
+ const res = await this._postJsonEncoded('/axis-cgi/basicdeviceinfo.cgi', payload, undefined, options);
226
202
  const json = await res.json();
227
203
  if (isNullish(json.data)) {
228
204
  throw new NoDeviceInfoError();
@@ -231,25 +207,25 @@ export class VapixAPI {
231
207
  }
232
208
  async getHeaders(options) {
233
209
  const data = { apiVersion: '1.0', method: 'list' };
234
- const res = await this.postJson('/axis-cgi/customhttpheader.cgi', data, undefined, options);
210
+ const res = await this._postJsonEncoded('/axis-cgi/customhttpheader.cgi', data, undefined, options);
235
211
  return z.object({ data: z.record(z.string()) }).parse(await res.json()).data;
236
212
  }
237
213
  async setHeaders(headers, options) {
238
214
  const data = { apiVersion: '1.0', method: 'set', params: headers };
239
- return this.postJson('/axis-cgi/customhttpheader.cgi', data, undefined, options);
215
+ return this._postJsonEncoded('/axis-cgi/customhttpheader.cgi', data, undefined, options);
240
216
  }
241
217
  async getParameter(paramNames, options) {
242
- const response = await this.postUrlEncoded('/axis-cgi/param.cgi', {
218
+ const response = await this._postUrlEncoded('/axis-cgi/param.cgi', {
243
219
  action: 'list',
244
220
  group: arrayToUrl(paramNames),
245
- }, undefined, options);
221
+ }, options);
246
222
  return VapixAPI.parseParameters(await response.text());
247
223
  }
248
224
  async setParameter(params, options) {
249
- const res = await this.postUrlEncoded('/axis-cgi/param.cgi', {
225
+ const res = await this._postUrlEncoded('/axis-cgi/param.cgi', {
250
226
  ...params,
251
227
  action: 'update',
252
- }, undefined, options);
228
+ }, options);
253
229
  const responseText = await res.text();
254
230
  if (responseText.startsWith('# Error')) {
255
231
  throw new SettingParameterError(responseText);
@@ -297,10 +273,10 @@ export class VapixAPI {
297
273
  return this.setParameter(params, options);
298
274
  }
299
275
  async getPTZPresetList(channel, options) {
300
- const res = await this.postUrlEncoded('/axis-cgi/com/ptz.cgi', {
276
+ const res = await this._postUrlEncoded('/axis-cgi/com/ptz.cgi', {
301
277
  query: 'presetposcam',
302
278
  camera: channel,
303
- }, undefined, options);
279
+ }, options);
304
280
  const text = await res.text();
305
281
  const lines = text.split(/[\r\n]/);
306
282
  const positions = [];
@@ -317,11 +293,11 @@ export class VapixAPI {
317
293
  }
318
294
  async listPTZ(camera, options) {
319
295
  const url = `/axis-cgi/com/ptz.cgi`;
320
- const response = await this.postUrlEncoded(url, {
296
+ const response = await this._postUrlEncoded(url, {
321
297
  camera,
322
298
  query: 'presetposcamdata',
323
299
  format: 'json',
324
- }, undefined, options);
300
+ }, options);
325
301
  const text = await response.text();
326
302
  if (text === '') {
327
303
  throw new PtzNotSupportedError();
@@ -329,10 +305,10 @@ export class VapixAPI {
329
305
  return VapixAPI.parseCameraPtzResponse(text)[camera] ?? [];
330
306
  }
331
307
  async listPtzVideoSourceOverview(options) {
332
- const response = await this.postUrlEncoded('/axis-cgi/com/ptz.cgi', {
308
+ const response = await this._postUrlEncoded('/axis-cgi/com/ptz.cgi', {
333
309
  query: 'presetposall',
334
310
  format: 'json',
335
- }, undefined, options);
311
+ }, options);
336
312
  const text = await response.text();
337
313
  if (text === '') {
338
314
  throw new PtzNotSupportedError();
@@ -350,16 +326,16 @@ export class VapixAPI {
350
326
  return ptzOverviewSchema.parse(res);
351
327
  }
352
328
  goToPreset(channel, presetName, options) {
353
- return this.postUrlEncoded('/axis-cgi/com/ptz.cgi', {
329
+ return this._postUrlEncoded('/axis-cgi/com/ptz.cgi', {
354
330
  camera: channel.toString(),
355
331
  gotoserverpresetname: presetName,
356
- }, undefined, options);
332
+ }, options);
357
333
  }
358
334
  async getPtzPosition(camera, options) {
359
- const res = await this.postUrlEncoded('/axis-cgi/com/ptz.cgi', {
335
+ const res = await this._postUrlEncoded('/axis-cgi/com/ptz.cgi', {
360
336
  query: 'position',
361
337
  camera: camera.toString(),
362
- }, undefined, options);
338
+ }, options);
363
339
  const params = VapixAPI.parseParameters(await res.text());
364
340
  return cameraPTZItemDataSchema.parse({
365
341
  pan: Number(params.pan),
@@ -368,7 +344,7 @@ export class VapixAPI {
368
344
  });
369
345
  }
370
346
  async getPorts(options) {
371
- const res = await this.postJson('/axis-cgi/io/portmanagement.cgi', {
347
+ const res = await this._postJsonEncoded('/axis-cgi/io/portmanagement.cgi', {
372
348
  apiVersion: '1.0',
373
349
  context: '',
374
350
  method: 'getPorts',
@@ -377,7 +353,7 @@ export class VapixAPI {
377
353
  return portResponseParsed.data.items;
378
354
  }
379
355
  async setPorts(ports, options) {
380
- await this.postJson('/axis-cgi/io/portmanagement.cgi', {
356
+ await this._postJsonEncoded('/axis-cgi/io/portmanagement.cgi', {
381
357
  apiVersion: '1.0',
382
358
  context: '',
383
359
  method: 'setPorts',
@@ -385,7 +361,7 @@ export class VapixAPI {
385
361
  }, undefined, options);
386
362
  }
387
363
  async setPortStateSequence(port, sequence, options) {
388
- await this.postJson('/axis-cgi/io/portmanagement.cgi', {
364
+ await this._postJsonEncoded('/axis-cgi/io/portmanagement.cgi', {
389
365
  apiVersion: '1.0',
390
366
  context: '',
391
367
  method: 'setStateSequence',
@@ -393,27 +369,27 @@ export class VapixAPI {
393
369
  }, undefined, options);
394
370
  }
395
371
  async addCameraUser(username, pass, sgrp, comment, options) {
396
- return await this.postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
372
+ return await this._postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
397
373
  action: 'add',
398
374
  user: username,
399
375
  pwd: pass,
400
376
  grp: 'users',
401
377
  sgrp,
402
378
  comment,
403
- }, undefined, options);
379
+ }, options);
404
380
  }
405
381
  async getCameraUsers(options) {
406
- const res = await this.postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
382
+ const res = await this._postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
407
383
  action: 'get',
408
- }, undefined, options);
384
+ }, options);
409
385
  return await res.text();
410
386
  }
411
387
  async editCameraUser(username, pass, options) {
412
- return await this.postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
388
+ return await this._postUrlEncoded('/axis-cgi/pwdgrp.cgi', {
413
389
  action: 'update',
414
390
  user: username,
415
391
  pwd: pass,
416
- }, undefined, options);
392
+ }, options);
417
393
  }
418
394
  async getApplicationList(options) {
419
395
  const agent = this.getClient(options?.proxyParams);
@@ -64,7 +64,7 @@ export class BasicAPI {
64
64
  path,
65
65
  data: jsonData,
66
66
  parameters,
67
- headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
67
+ headers: { 'Content-Type': 'application/json' },
68
68
  timeout: options?.timeout,
69
69
  });
70
70
  if (res.ok) {
@@ -119,3 +119,10 @@ export const audioLocalSchema = z.object({
119
119
  name: z.string(),
120
120
  storage: z.enum(['flash', 'SD0']),
121
121
  });
122
+ export const streamStatsSchema = z.object({
123
+ net_stats: z.string(),
124
+ stream_bytes_time_ms: z.number(),
125
+ stream_bytes: z.number(),
126
+ start_count: z.number(),
127
+ is_streaming: z.number(),
128
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstreamerlib",
3
- "version": "4.0.0-beta.120",
3
+ "version": "4.0.0-beta.122",
4
4
  "description": "Helper library for CamStreamer ACAP applications.",
5
5
  "prettier": "@camstreamer/prettier-config",
6
6
  "engine": {
@@ -2870,7 +2870,13 @@ export declare class CamStreamerAPI<Client extends IClient<TResponse, any>> exte
2870
2870
  streamIdentifier?: string | undefined;
2871
2871
  }>;
2872
2872
  setStream(streamId: string, streamData: TStream, options?: THttpRequestOptions): Promise<void>;
2873
- isStreaming(streamId: string, options?: THttpRequestOptions): Promise<boolean>;
2873
+ getStreamStats(streamId: number, options?: THttpRequestOptions): Promise<{
2874
+ net_stats: string;
2875
+ stream_bytes_time_ms: number;
2876
+ stream_bytes: number;
2877
+ start_count: number;
2878
+ is_streaming: number;
2879
+ }>;
2874
2880
  setStreamEnabled(streamId: string, enabled: boolean, options?: THttpRequestOptions): Promise<void>;
2875
2881
  setStreamActive(streamId: string, active: boolean, options?: THttpRequestOptions): Promise<void>;
2876
2882
  listFiles(options?: THttpRequestOptions): Promise<{
@@ -1,17 +1,13 @@
1
- import { IClient, TParameters, TResponse } from './internal/types';
1
+ import { IClient, TResponse } from './internal/types';
2
2
  import { TAudioDevice, TPortSetSchema, TPortSequenceStateSchema } from './types/VapixAPI';
3
- import { ProxyClient } from './internal/ProxyClient';
4
- import { TCameraImageConfig, THttpRequestOptions, TProxyParams } from './types/common';
5
- export declare class VapixAPI<Client extends IClient<TResponse, any>> {
6
- private client;
3
+ import { TCameraImageConfig, THttpRequestOptions } from './types/common';
4
+ import { BasicAPI } from './internal/BasicAPI';
5
+ export declare class VapixAPI<Client extends IClient<TResponse, any>> extends BasicAPI<Client> {
7
6
  private CustomFormData;
8
7
  constructor(client: Client, CustomFormData?: {
9
8
  new (form?: HTMLFormElement | undefined, submitter?: HTMLElement | null | undefined): FormData;
10
9
  prototype: FormData;
11
10
  });
12
- getClient(proxyParams?: TProxyParams): Client | ProxyClient<Client>;
13
- postUrlEncoded(path: string, parameters?: TParameters, headers?: Record<string, string>, options?: THttpRequestOptions): Promise<TResponse>;
14
- postJson(path: string, jsonData: Record<string, any>, headers?: Record<string, string>, options?: THttpRequestOptions): Promise<TResponse>;
15
11
  getCameraImage(parameters: TCameraImageConfig, options?: THttpRequestOptions): Promise<ReturnType<Client["get"]>>;
16
12
  getEventDeclarations(options?: THttpRequestOptions): Promise<string>;
17
13
  getSupportedAudioSampleRate(options?: THttpRequestOptions): Promise<{
@@ -28,7 +24,7 @@ export declare class VapixAPI<Client extends IClient<TResponse, any>> {
28
24
  unmountSDCard(options?: THttpRequestOptions): Promise<number>;
29
25
  private _doSDCardMountAction;
30
26
  fetchSDCardJobProgress(jobId: number, options?: THttpRequestOptions): Promise<number>;
31
- downloadCameraReport(options?: THttpRequestOptions): Promise<TResponse>;
27
+ downloadCameraReport(options?: THttpRequestOptions): Promise<string>;
32
28
  getSystemLog(options?: THttpRequestOptions): Promise<TResponse>;
33
29
  getMaxFps(channel: number, options?: THttpRequestOptions): Promise<number>;
34
30
  getTimezone(options?: THttpRequestOptions): Promise<string>;
@@ -20256,3 +20256,23 @@ export declare const audioLocalSchema: z.ZodObject<{
20256
20256
  storage: "flash" | "SD0";
20257
20257
  }>;
20258
20258
  export type TAudioLocalType = z.infer<typeof audioLocalSchema>;
20259
+ export declare const streamStatsSchema: z.ZodObject<{
20260
+ net_stats: z.ZodString;
20261
+ stream_bytes_time_ms: z.ZodNumber;
20262
+ stream_bytes: z.ZodNumber;
20263
+ start_count: z.ZodNumber;
20264
+ is_streaming: z.ZodNumber;
20265
+ }, "strip", z.ZodTypeAny, {
20266
+ net_stats: string;
20267
+ stream_bytes_time_ms: number;
20268
+ stream_bytes: number;
20269
+ start_count: number;
20270
+ is_streaming: number;
20271
+ }, {
20272
+ net_stats: string;
20273
+ stream_bytes_time_ms: number;
20274
+ stream_bytes: number;
20275
+ start_count: number;
20276
+ is_streaming: number;
20277
+ }>;
20278
+ export type TStreamStats = z.infer<typeof streamStatsSchema>;