Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@twilio/rtc-diagnostics

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@twilio/rtc-diagnostics - npm Package Compare versions

Comparing version 1.0.0-preview3 to 1.0.0

credentials.example.json

6

.release.json

@@ -26,3 +26,3 @@ {

"git rebase HEAD ${BRANCH}",
"git push origin ${BRANCH} --tags",
"git push origin ${BRANCH} --tags &> /dev/null && echo \"Push to origin successful\" || (echo \"Push to origin failed\" 1>&2 && exit 1)",
"git fetch --all",

@@ -53,3 +53,5 @@ "git checkout ${RELEASE_VERSION}",

"commands": [
"echo \"publish command not implemented\""
"git checkout ${RELEASE_VERSION}",
"echo \"//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}\" >~/.npmrc",
"npm publish"
]

@@ -56,0 +58,0 @@ }

@@ -0,1 +1,196 @@

1.0.0 (Nov 3, 2020)
===================
1.0.0-beta2 has been promoted to 1.0.0 GA. RTC Diagnostics SDK will use [Semantic Versioning 2.0.0](https://semver.org/#semantic-versioning-200) for all future changes.
1.0.0-beta2 (Sept 25, 2020)
=========================
New Features
------------
* Support for Video Diagnostics is introduced with the addition of `VideoInputTest` and `testVideoInputDevice`. This test helps to diagnose possible issues with video input devices by capturing a video stream from a user and displaying it on a video element for the user to confirm. See the [API Docs](https://twilio.github.io/rtc-diagnostics/classes/videoinputtest.html) for details.
**Example Usage**
```ts
import {
DiagnosticError,
testVideoInputDevice,
VideoInputTest,
} from '@twilio/rtc-diagnostics';
const videoEl: HTMLMediaElement = document.getElementById(...);
const test: VideoInputTest = testVideoInputDevice({
element: videoEl,
});
test.on(VideoInputTest.Events.End, (report: VideoInputTest.Report) => { ... });
test.on(VideoInputTest.Events.Error, (error: DiagnosticError) => { ... });
```
As soon as the test object is instantiated, an attempt to capture the user video stream will be performed and if successful then the stream will be bound to the video element. When the test is stopped, either by timeout or manually, then the video element is paused and the stream is removed from it.
Changes
-------
* The audio device tests `InputTest` and `OutputTest` no longer perform any analysis on volume data. With this change, `InputTest.Report.didPass` and `OutputTest.Report.didPass` are no longer available and `InputTest.stop()` and `OutputTest.stop()` no longer accept a `pass: boolean` parameter. Your application will need to analyze the volume levels in the `Report.values` property to determine whether or not the volume levels are acceptable.
* The following classes and methods have been changed
| Old | New |
|:-------------------|:-----------------------------|
| `InputTest` | `AudioInputTest` |
| `OutputTest` | `AudioOutputTest` |
| `BitrateTest` | `MediaConnectionBitrateTest` |
| `testInputDevice` | `testAudioInputDevice` |
| `testOutputDevice` | `testAudioOutputDevice` |
| `testBitrate` | `testMediaConnectionBitrate` |
* `MediaConnectionBitrateTest` now uses TURN server on only one of the Peer Connections. With this change, you need to provide a STUN server in addition to the TURN server configurations. See `MediaConnectionBitrateTest.Options.iceServers` for details.
* `MediaConnectionBitrateTest` no longer perform any analysis on bitrate data and `MediaConnectionBitrateTest.Report.didPass` is no longer available. Your application will need to analyze the bitrate values in `MediaConnectionBitrateTest.Report.values` and `MediaConnectionBitrateTest.Report.averageBitrate` properties to determine whether or not the values are acceptable.
* `MediaConnectionBitrateTest` now emits warnings when certain criteria are met. See [WarningNames](https://twilio.github.io/rtc-diagnostics/enums/warningname.html) and [minBitrateThreshold](https://twilio.github.io/rtc-diagnostics/interfaces/mediaconnectionbitratetest.options.html#minbitratethreshold) for details.
Example usage:
```ts
import { MediaConnectionBitrateTest, testMediaConnectionBitrate, WarningName } from '@twilio/rtc-diagnostics';
const test = testMediaConnectionBitrate({ iceServers: [...], minBitrateThreshold: 500 });
test.on(MediaConnectionBitrateTest.Events.Warning, (warningName: WarningName) => {
// The application can listen for specific warnings...
if (warningName === WarningName.LowBitrate) {
// update the ui
}
// ...or access all active warnings.
test.activeWarnings.values().forEach(...);
});
test.on(MediaConnectionBitrateTest.Events.WarningCleared, (warningName: WarningName) => {
// The application can listen for specific warnings...
if (warningName === WarningName.LowBitrate) {
// update the ui
}
// ...or access all active warnings.
test.activeWarnings.values().forEach(...);
});
```
* `DiagnosticError` can now be imported directly. Example:
```ts
import {
DiagnosticError,
MediaConnectionBitrateTest,
testMediaConnectionBitrate,
} from '@twilio/rtc-diagnostics';
const test = testMediaConnectionBitrate(...);
test.on(MediaConnectionBitrateTest.Events.Error, (error: DiagnosticError) => {
console.log(error);
});
```
* Updated test names to `audio-input-test`, `audio-output-test`, and `media-connection-bitrate-test` for consistency.
* Removed unused `promise-timed-out` and `invalid-option` error.
1.0.0-beta1 (July 29, 2020)
============================
New Features
-------------
### Audio recording feature in `InputTest`.
`InputTest` now supports the ability to record the audio captured from the input device, and provides a recording URL which can be used to play back audio. This feature is disabled by default and can be enabled by setting [InputTest.Options.enableRecording](https://twilio.github.io/rtc-diagnostics/interfaces/inputtest.options.html#enablerecording) to `true`. When enabled, the recording URL is available via [InputTest.Report.recordingUrl](https://twilio.github.io/rtc-diagnostics/interfaces/inputtest.report.html#recordingurl) property.
Example usage:
```ts
const inputTest: InputTest = testInputDevice({ enableRecording: true });
inputTest.on(InputTest.Events.End, (report: InputTest.Report) => {
const audioEl = new Audio();
audioEl.src = report.recordingUrl;
audioEl.play();
// Revoke the url if no longer needed
URL.revokeObjectURL(report.recordingUrl);
});
```
### `LowAudioLevel` detection and warning in `InputTest`.
During the runtime of the test, if low audio levels are detected from the captured input device, the test will emit a `warning` event. The test will emit a `warning-cleared` event when nominal audio levels are detected only after the `low-audio-level` `warning` has been fired.
After the `low-audio-level` warning has been raised, it will not be raised again until it has been cleared.
Example usage:
```ts
import { InputTest, testInputDevice, WarningName } from '@twilio/rtc-diagnostics';
const inputDeviceTest = testInputDevice();
inputDeviceTest.on(InputTest.Events.Warning, (warningName: WarningName) => {
// The application can listen for specific warnings...
if (warningName === WarningName.LowAudioLevel) {
// update the ui to show the input device may not be working
}
// ...or access all active warnings.
inputDeviceTest.activeWarnings.values().forEach(...);
});
inputDeviceTest.on(InputTest.Events.WarningCleared, (warningName: WarningName) => {
// The application can listen for specific warnings...
if (warningName === WarningName.LowAudioLevel) {
// update the ui to show that the input device may be working again
}
// ...or access all active warnings.
inputDeviceTest.activeWarnings.values().forEach(...);
});
```
Changes
-------
* Added a new DiagnosticError, `TimeoutError`, which is emitted when a BitrateTest times out (15 seconds).
* Added ICE Candidate related statistics in the [BitrateTest.Report](https://twilio.github.io/rtc-diagnostics/interfaces/bitratetest.report.html) object.
**Example Usage**
```ts
bitrateTest.on(BitrateTest.Events.End, (report: BitrateTest.Report) => {
console.log(report);
});
```
**Example Report Data**
```js
{
"iceCandidateStats": [...],
"selectedIceCandidatePairStats": {
"localCandidate": {...},
"remoteCandidate": {...}
},
// Other report properties...
}
```
* Removed network related timings and warnings. It is recommended to use `twilio-client.js` [preflight timing APIs](https://github.com/twilio/twilio-client.js/blob/preflight/PREFLIGHT.md) instead for more accurate timing information. With this change, the following are no longer available:
- `bitrateTest.on('warning', handler(warning))`
- `BitrateTest.Report.warnings`
- `BitrateTest.Report.networkTiming`
Bug Fixes
---------
* Fixed an issue where output device test doesn't fail after providing a deviceId on browsers that doesn't support [setSinkId](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId);
1.0.0-preview3 (June 17, 2020)

@@ -2,0 +197,0 @@ ==============================

/**
* @private
* Parameters passed to our audio encoder
* buffer size, input channels, output channes
*/
export declare const ENCODER_PARAMS: number[];
/**
* @private
* Max number of packets to send to data channel for bitrate test

@@ -14,2 +20,14 @@ */

* @private
* Minimum bitrate samples required to emit warnings.
* See [[WarningName.LowBitrate]]
*/
export declare const MIN_BITRATE_SAMPLE_COUNT = 5;
/**
* @private
* Minimum number of failing bitrate values before emitting a warning.
* See [[WarningName.LowBitrate]]
*/
export declare const MIN_BITRATE_FAIL_COUNT = 3;
/**
* @private
* Data channel buffered amount

@@ -30,7 +48,52 @@ */

* @private
* Test names.
* The number of milliseconds to wait to receive data in bitrate test before timing out.
*/
export declare enum TestNames {
InputAudioDevice = "input-volume",
OutputAudioDevice = "output-volume"
export declare const BITRATE_TEST_TIMEOUT_MS: number;
/**
* All of the expected error names to be thrown by the diagnostics tests.
* These names are set in the error objects as the `.name` member.
*/
export declare enum ErrorName {
AlreadyStoppedError = "already-stopped",
DiagnosticError = "diagnostic",
InvalidOptionsError = "invalid-options",
InvalidStateError = "invalid-state",
UnsupportedError = "unsupported"
}
/**
* All of the expected warnings raised by the diagnostics tests.
* A `warning-cleared` event is raised if there is an active warning
* and if the criteria of the warning are no longer met.
*
* Example:
*
* ```ts
* test.on(AudioInputTest.Events.Warning, (warningName: WarningName) => {
* console.log(`Warning detected: ${warningName}`);
* });
*
* test.on(AudioInputTest.Events.WarningCleared, (warningName: WarningName) => {
* console.log(`Warning cleared: ${warningName}`);
* });
* ```
*
*/
export declare enum WarningName {
/**
* Raised by the [[AudioInputTest]] when the volume events recorded are both low and constant.
* The criteria for raising this warning are:
* - If there are at least three seconds worth of audio samples.
* - The standard deviation of those samples is less than 1% of the max
* possible volume value (255).
* - The average of those samples is less than 1% of the max possible volume
* value (255).
*/
LowAudioLevel = "low-audio-level",
/**
* Raised by the [[MediaConnectionBitrateTest]] when the recorded bitrates are consistently lower than a certain threshold.
* The criteria for raising this warning are:
* - At least 5 seconds worth of bitrate values have been recorded.
* - 3 out of last 5 bitrate values are less than [[MediaConnectionBitrateTest.Options.minBitrateThreshold]].
*/
LowBitrate = "low-bitrate"
}

@@ -6,2 +6,8 @@ "use strict";

* @private
* Parameters passed to our audio encoder
* buffer size, input channels, output channes
*/
exports.ENCODER_PARAMS = [2048, 1, 1];
/**
* @private
* Max number of packets to send to data channel for bitrate test

@@ -18,2 +24,14 @@ */

* @private
* Minimum bitrate samples required to emit warnings.
* See [[WarningName.LowBitrate]]
*/
exports.MIN_BITRATE_SAMPLE_COUNT = 5;
/**
* @private
* Minimum number of failing bitrate values before emitting a warning.
* See [[WarningName.LowBitrate]]
*/
exports.MIN_BITRATE_FAIL_COUNT = 3;
/**
* @private
* Data channel buffered amount

@@ -34,9 +52,55 @@ */

* @private
* Test names.
* The number of milliseconds to wait to receive data in bitrate test before timing out.
*/
var TestNames;
(function (TestNames) {
TestNames["InputAudioDevice"] = "input-volume";
TestNames["OutputAudioDevice"] = "output-volume";
})(TestNames = exports.TestNames || (exports.TestNames = {}));
exports.BITRATE_TEST_TIMEOUT_MS = 15000;
/**
* All of the expected error names to be thrown by the diagnostics tests.
* These names are set in the error objects as the `.name` member.
*/
var ErrorName;
(function (ErrorName) {
ErrorName["AlreadyStoppedError"] = "already-stopped";
ErrorName["DiagnosticError"] = "diagnostic";
ErrorName["InvalidOptionsError"] = "invalid-options";
ErrorName["InvalidStateError"] = "invalid-state";
ErrorName["UnsupportedError"] = "unsupported";
})(ErrorName = exports.ErrorName || (exports.ErrorName = {}));
/**
* All of the expected warnings raised by the diagnostics tests.
* A `warning-cleared` event is raised if there is an active warning
* and if the criteria of the warning are no longer met.
*
* Example:
*
* ```ts
* test.on(AudioInputTest.Events.Warning, (warningName: WarningName) => {
* console.log(`Warning detected: ${warningName}`);
* });
*
* test.on(AudioInputTest.Events.WarningCleared, (warningName: WarningName) => {
* console.log(`Warning cleared: ${warningName}`);
* });
* ```
*
*/
var WarningName;
(function (WarningName) {
/**
* Raised by the [[AudioInputTest]] when the volume events recorded are both low and constant.
* The criteria for raising this warning are:
* - If there are at least three seconds worth of audio samples.
* - The standard deviation of those samples is less than 1% of the max
* possible volume value (255).
* - The average of those samples is less than 1% of the max possible volume
* value (255).
*/
WarningName["LowAudioLevel"] = "low-audio-level";
/**
* Raised by the [[MediaConnectionBitrateTest]] when the recorded bitrates are consistently lower than a certain threshold.
* The criteria for raising this warning are:
* - At least 5 seconds worth of bitrate values have been recorded.
* - 3 out of last 5 bitrate values are less than [[MediaConnectionBitrateTest.Options.minBitrateThreshold]].
*/
WarningName["LowBitrate"] = "low-bitrate";
})(WarningName = exports.WarningName || (exports.WarningName = {}));
//# sourceMappingURL=constants.js.map

@@ -1,4 +0,8 @@

import { BitrateTest, testBitrate } from './BitrateTest';
import { InputTest, testInputDevice } from './InputTest';
import { OutputTest, testOutputDevice } from './OutputTest';
import { AudioInputTest, testAudioInputDevice } from './AudioInputTest';
import { AudioOutputTest, testAudioOutputDevice } from './AudioOutputTest';
import { ErrorName, WarningName } from './constants';
import { DiagnosticError } from './errors/DiagnosticError';
import { MediaConnectionBitrateTest, testMediaConnectionBitrate } from './MediaConnectionBitrateTest';
import { VideoResolution } from './types';
import { testVideoInputDevice, VideoInputTest } from './VideoInputTest';
/**

@@ -19,2 +23,2 @@ * @internalapi

*/
export { BitrateTest, InputTest, OutputTest, testBitrate, testInputDevice, testOutputDevice, };
export { AudioInputTest, AudioOutputTest, DiagnosticError, MediaConnectionBitrateTest, ErrorName, testAudioInputDevice, testAudioOutputDevice, testMediaConnectionBitrate, testVideoInputDevice, VideoInputTest, VideoResolution, WarningName, };

@@ -14,11 +14,19 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var BitrateTest_1 = require("./BitrateTest");
exports.BitrateTest = BitrateTest_1.BitrateTest;
exports.testBitrate = BitrateTest_1.testBitrate;
var InputTest_1 = require("./InputTest");
exports.InputTest = InputTest_1.InputTest;
exports.testInputDevice = InputTest_1.testInputDevice;
var OutputTest_1 = require("./OutputTest");
exports.OutputTest = OutputTest_1.OutputTest;
exports.testOutputDevice = OutputTest_1.testOutputDevice;
var AudioInputTest_1 = require("./AudioInputTest");
exports.AudioInputTest = AudioInputTest_1.AudioInputTest;
exports.testAudioInputDevice = AudioInputTest_1.testAudioInputDevice;
var AudioOutputTest_1 = require("./AudioOutputTest");
exports.AudioOutputTest = AudioOutputTest_1.AudioOutputTest;
exports.testAudioOutputDevice = AudioOutputTest_1.testAudioOutputDevice;
var constants_1 = require("./constants");
exports.ErrorName = constants_1.ErrorName;
exports.WarningName = constants_1.WarningName;
var DiagnosticError_1 = require("./errors/DiagnosticError");
exports.DiagnosticError = DiagnosticError_1.DiagnosticError;
var MediaConnectionBitrateTest_1 = require("./MediaConnectionBitrateTest");
exports.MediaConnectionBitrateTest = MediaConnectionBitrateTest_1.MediaConnectionBitrateTest;
exports.testMediaConnectionBitrate = MediaConnectionBitrateTest_1.testMediaConnectionBitrate;
var VideoInputTest_1 = require("./VideoInputTest");
exports.testVideoInputDevice = VideoInputTest_1.testVideoInputDevice;
exports.VideoInputTest = VideoInputTest_1.VideoInputTest;
/**

@@ -31,5 +39,6 @@ * If the `Twilio` object does not exist, make it.

window.Twilio = window.Twilio || {};
window.Twilio.Diagnostics = __assign(__assign({}, window.Twilio.Diagnostics), { testBitrate: BitrateTest_1.testBitrate,
testInputDevice: InputTest_1.testInputDevice,
testOutputDevice: OutputTest_1.testOutputDevice });
window.Twilio.Diagnostics = __assign(__assign({}, window.Twilio.Diagnostics), { testAudioInputDevice: AudioInputTest_1.testAudioInputDevice,
testAudioOutputDevice: AudioOutputTest_1.testAudioOutputDevice,
testMediaConnectionBitrate: MediaConnectionBitrateTest_1.testMediaConnectionBitrate,
testVideoInputDevice: VideoInputTest_1.testVideoInputDevice });
//# sourceMappingURL=diagnostics.js.map

@@ -16,2 +16,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var constants_1 = require("../constants");
var InvalidStateError_1 = require("./InvalidStateError");

@@ -28,3 +29,3 @@ /**

'Tests should not be run multiple times, instead start a new one.') || this;
_this.name = 'AlreadyStoppedError';
_this.name = constants_1.ErrorName.AlreadyStoppedError;
return _this;

@@ -31,0 +32,0 @@ }

@@ -0,1 +1,2 @@

import { ErrorName } from '../constants';
/**

@@ -11,2 +12,9 @@ * @internalapi

/**
* The name of the error.
*
* This overrides the typing of the `Error.name` superclass member from
* `string` to the specific enumeration of error names.
*/
name: ErrorName;
/**
* The timestamp of the occurrence of this error.

@@ -13,0 +21,0 @@ */

@@ -16,2 +16,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var constants_1 = require("../constants");
/**

@@ -33,3 +34,3 @@ * @internalapi

Object.setPrototypeOf(_this, DiagnosticError.prototype);
_this.name = 'DiagnosticError';
_this.name = constants_1.ErrorName.DiagnosticError;
return _this;

@@ -36,0 +37,0 @@ }

export { AlreadyStoppedError } from './AlreadyStoppedError';
export { DiagnosticError } from './DiagnosticError';
export { InvalidOptionsError } from './InvalidOptionsError';
export { InvalidStateError } from './InvalidStateError';
export { PromiseTimedOutError } from './PromiseTimedOutError';
export { UnsupportedError } from './UnsupportedError';
export { InvalidOptionError } from './InvalidOptionError';
export { InvalidOptionsError } from './InvalidOptionsError';

@@ -7,12 +7,8 @@ "use strict";

exports.DiagnosticError = DiagnosticError_1.DiagnosticError;
var InvalidOptionsError_1 = require("./InvalidOptionsError");
exports.InvalidOptionsError = InvalidOptionsError_1.InvalidOptionsError;
var InvalidStateError_1 = require("./InvalidStateError");
exports.InvalidStateError = InvalidStateError_1.InvalidStateError;
var PromiseTimedOutError_1 = require("./PromiseTimedOutError");
exports.PromiseTimedOutError = PromiseTimedOutError_1.PromiseTimedOutError;
var UnsupportedError_1 = require("./UnsupportedError");
exports.UnsupportedError = UnsupportedError_1.UnsupportedError;
var InvalidOptionError_1 = require("./InvalidOptionError");
exports.InvalidOptionError = InvalidOptionError_1.InvalidOptionError;
var InvalidOptionsError_1 = require("./InvalidOptionsError");
exports.InvalidOptionsError = InvalidOptionsError_1.InvalidOptionsError;
//# sourceMappingURL=index.js.map

@@ -16,2 +16,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var constants_1 = require("../constants");
var DiagnosticError_1 = require("./DiagnosticError");

@@ -28,3 +29,3 @@ /**

_this.reasons = reasons;
_this.name = 'InvalidOptionsError';
_this.name = constants_1.ErrorName.InvalidOptionsError;
return _this;

@@ -31,0 +32,0 @@ }

@@ -16,2 +16,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var constants_1 = require("../constants");
var DiagnosticError_1 = require("./DiagnosticError");

@@ -31,3 +32,3 @@ /**

var _this = _super.call(this, undefined, message) || this;
_this.name = 'InvalidStateError';
_this.name = constants_1.ErrorName.InvalidStateError;
return _this;

@@ -34,0 +35,0 @@ }

import { DiagnosticError } from './DiagnosticError';
/**
* @internalapi
* Error for when a browser-provided feature isn't available, such as
* `getUserMedia`.
*/

@@ -5,0 +7,0 @@ export declare class UnsupportedError extends DiagnosticError {

@@ -16,5 +16,8 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var constants_1 = require("../constants");
var DiagnosticError_1 = require("./DiagnosticError");
/**
* @internalapi
* Error for when a browser-provided feature isn't available, such as
* `getUserMedia`.
*/

@@ -25,3 +28,3 @@ var UnsupportedError = /** @class */ (function (_super) {

var _this = _super.call(this, undefined, message) || this;
_this.name = 'UnsupportedError';
_this.name = constants_1.ErrorName.UnsupportedError;
return _this;

@@ -28,0 +31,0 @@ }

@@ -10,6 +10,16 @@ /**

* @internalapi
* Timing measurements that provides operational milestones.
*/
export interface TimeMeasurement {
duration: number;
end: number;
/**
* Number in milliseconds elapsed for this measurement.
*/
duration?: number;
/**
* A millisecond timestamp that represents the end of a process.
*/
end?: number;
/**
* A millisecond timestamp that represents the start of a process.
*/
start: number;

@@ -23,1 +33,48 @@ }

export declare type SubsetRequired<T, K extends keyof T> = T & Required<Pick<T, K>>;
/**
* @internalapi
* Volume statistics to track in the audio device tests.
*/
export interface VolumeStats {
/**
* The maximum volume value recorded during the test.
*/
max?: number;
/**
* The smallest non-zero volume value encountered.
*/
min?: number;
/**
* The timestamps of the recorded values. For example, the 0th indexed
* timestamp correlates to when the 0th indexed volume value was recorded.
*/
timestamps: number[];
/**
* The recorded volume values encountered during the test.
*/
values: number[];
}
/**
* Native MediaStream Recording APIs definitions
* @private
*/
export declare namespace MediaStreamRecorder {
type AudioData = any;
interface DataEvent {
data: AudioData;
}
interface MediaRecorder {
ondataavailable: Function;
onstop: Function;
start: Function;
stop: Function;
}
}
/**
* Description of a video resolution.
* @internalapi
*/
export interface VideoResolution {
height: number;
width: number;
}

@@ -87,3 +87,11 @@ /**

* @internalapi
* Validate input options to the [[InputTest]].
* Validate that an option is a `boolean`.
* @param option The option to check.
* @returns A possibly undefined string, if the option is valid it will return
* `undefined`, otherwise a string representing why the option is invalid
*/
export declare function validateBoolean(option: any): Validity;
/**
* @internalapi
* Validate input options to the [[AudioInputTest]].
* @param inputOptions The options to validate.

@@ -90,0 +98,0 @@ * @param config A record of option names to either a single

@@ -134,3 +134,3 @@ "use strict";

function validateDeviceId(option) {
if (option && typeof option !== 'string') {
if (!(['string', 'undefined'].includes(typeof option) || option === null)) {
return 'If "deviceId" is defined, it must be a "string".';

@@ -189,3 +189,16 @@ }

* @internalapi
* Validate input options to the [[InputTest]].
* Validate that an option is a `boolean`.
* @param option The option to check.
* @returns A possibly undefined string, if the option is valid it will return
* `undefined`, otherwise a string representing why the option is invalid
*/
function validateBoolean(option) {
if (typeof option !== 'boolean') {
return "Option must be \"boolean\".";
}
}
exports.validateBoolean = validateBoolean;
/**
* @internalapi
* Validate input options to the [[AudioInputTest]].
* @param inputOptions The options to validate.

@@ -192,0 +205,0 @@ * @param config A record of option names to either a single

@@ -31,8 +31,9 @@ export declare const name: string;

"@types/mocha": string;
"@types/request": string;
"@types/sinon": string;
"browserify": string;
"coverage": string;
"is-docker": string;
"karma": string;
"karma-chrome-launcher": string;
"karma-env-preprocessor": string;
"karma-firefox-launcher": string;

@@ -45,3 +46,3 @@ "karma-mocha": string;

"nyc": string;
"twilio-release-tool": string;
"request": string;
"sinon": string;

@@ -53,2 +54,3 @@ "travis-multirunner": string;

"twilio": string;
"twilio-release-tool": string;
"typedoc": string;

@@ -55,0 +57,0 @@ "typedoc-plugin-as-member-of": string;

{
"name": "@twilio/rtc-diagnostics",
"version": "1.0.0-preview3",
"version": "1.0.0",
"description": "Various diagnostics functions to help analyze connections to Twilio",

@@ -20,3 +20,3 @@ "main": "./es5/lib/diagnostics.js",

"test:unit": "nyc mocha -r ts-node/register ./tests/unit/index.ts",
"test:integration": "karma start"
"test:integration": "node ./scripts/env.js && karma start"
},

@@ -44,8 +44,9 @@ "contributors": [

"@types/mocha": "5.2.7",
"@types/sinon": "7.5.1",
"@types/request": "^2.48.5",
"@types/sinon": "9.0.4",
"browserify": "16.5.0",
"coverage": "0.4.1",
"is-docker": "2.0.0",
"karma": "4.4.1",
"karma-chrome-launcher": "3.1.0",
"karma-env-preprocessor": "^0.1.1",
"karma-firefox-launcher": "1.2.0",

@@ -58,4 +59,4 @@ "karma-mocha": "1.3.0",

"nyc": "15.0.0",
"twilio-release-tool": "1.0.1",
"sinon": "7.5.0",
"request": "^2.88.2",
"sinon": "9.0.2",
"travis-multirunner": "4.6.0",

@@ -66,2 +67,3 @@ "ts-node": "8.5.2",

"twilio": "3.39.1",
"twilio-release-tool": "1.0.1",
"typedoc": "0.16.11",

@@ -68,0 +70,0 @@ "typedoc-plugin-as-member-of": "1.0.2",

@@ -42,4 +42,10 @@ // Karma configuration

'./**/*.ts': 'karma-typescript',
'./tests/integration/*.ts': 'env',
},
envPreprocessor: [
'ACCOUNTSID',
'AUTHTOKEN',
],
// test results reporter to use

@@ -46,0 +52,0 @@ // possible values: 'dots', 'progress'

@@ -5,2 +5,9 @@ import * as pack from '../package.json';

* @private
* Parameters passed to our audio encoder
* buffer size, input channels, output channes
*/
export const ENCODER_PARAMS = [2048, 1, 1];
/**
* @private
* Max number of packets to send to data channel for bitrate test

@@ -19,2 +26,16 @@ */

* @private
* Minimum bitrate samples required to emit warnings.
* See [[WarningName.LowBitrate]]
*/
export const MIN_BITRATE_SAMPLE_COUNT = 5;
/**
* @private
* Minimum number of failing bitrate values before emitting a warning.
* See [[WarningName.LowBitrate]]
*/
export const MIN_BITRATE_FAIL_COUNT = 3;
/**
* @private
* Data channel buffered amount

@@ -39,7 +60,55 @@ */

* @private
* Test names.
* The number of milliseconds to wait to receive data in bitrate test before timing out.
*/
export enum TestNames {
InputAudioDevice = 'input-volume',
OutputAudioDevice = 'output-volume',
export const BITRATE_TEST_TIMEOUT_MS: number = 15000;
/**
* All of the expected error names to be thrown by the diagnostics tests.
* These names are set in the error objects as the `.name` member.
*/
export enum ErrorName {
AlreadyStoppedError = 'already-stopped',
DiagnosticError = 'diagnostic',
InvalidOptionsError = 'invalid-options',
InvalidStateError = 'invalid-state',
UnsupportedError = 'unsupported',
}
/**
* All of the expected warnings raised by the diagnostics tests.
* A `warning-cleared` event is raised if there is an active warning
* and if the criteria of the warning are no longer met.
*
* Example:
*
* ```ts
* test.on(AudioInputTest.Events.Warning, (warningName: WarningName) => {
* console.log(`Warning detected: ${warningName}`);
* });
*
* test.on(AudioInputTest.Events.WarningCleared, (warningName: WarningName) => {
* console.log(`Warning cleared: ${warningName}`);
* });
* ```
*
*/
export enum WarningName {
/**
* Raised by the [[AudioInputTest]] when the volume events recorded are both low and constant.
* The criteria for raising this warning are:
* - If there are at least three seconds worth of audio samples.
* - The standard deviation of those samples is less than 1% of the max
* possible volume value (255).
* - The average of those samples is less than 1% of the max possible volume
* value (255).
*/
LowAudioLevel = 'low-audio-level',
/**
* Raised by the [[MediaConnectionBitrateTest]] when the recorded bitrates are consistently lower than a certain threshold.
* The criteria for raising this warning are:
* - At least 5 seconds worth of bitrate values have been recorded.
* - 3 out of last 5 bitrate values are less than [[MediaConnectionBitrateTest.Options.minBitrateThreshold]].
*/
LowBitrate = 'low-bitrate',
}

@@ -1,4 +0,8 @@

import { BitrateTest, testBitrate } from './BitrateTest';
import { InputTest, testInputDevice } from './InputTest';
import { OutputTest, testOutputDevice } from './OutputTest';
import { AudioInputTest, testAudioInputDevice } from './AudioInputTest';
import { AudioOutputTest, testAudioOutputDevice } from './AudioOutputTest';
import { ErrorName, WarningName } from './constants';
import { DiagnosticError } from './errors/DiagnosticError';
import { MediaConnectionBitrateTest, testMediaConnectionBitrate } from './MediaConnectionBitrateTest';
import { VideoResolution } from './types';
import { testVideoInputDevice, VideoInputTest } from './VideoInputTest';

@@ -25,5 +29,6 @@ /**

...window.Twilio.Diagnostics,
testBitrate,
testInputDevice,
testOutputDevice,
testAudioInputDevice,
testAudioOutputDevice,
testMediaConnectionBitrate,
testVideoInputDevice,
};

@@ -35,8 +40,14 @@

export {
BitrateTest,
InputTest,
OutputTest,
testBitrate,
testInputDevice,
testOutputDevice,
AudioInputTest,
AudioOutputTest,
DiagnosticError,
MediaConnectionBitrateTest,
ErrorName,
testAudioInputDevice,
testAudioOutputDevice,
testMediaConnectionBitrate,
testVideoInputDevice,
VideoInputTest,
VideoResolution,
WarningName,
};

@@ -0,1 +1,2 @@

import { ErrorName } from '../constants';
import { InvalidStateError } from './InvalidStateError';

@@ -15,4 +16,4 @@

this.name = 'AlreadyStoppedError';
this.name = ErrorName.AlreadyStoppedError;
}
}

@@ -0,1 +1,3 @@

import { ErrorName } from '../constants';
/**

@@ -11,2 +13,9 @@ * @internalapi

/**
* The name of the error.
*
* This overrides the typing of the `Error.name` superclass member from
* `string` to the specific enumeration of error names.
*/
name: ErrorName;
/**
* The timestamp of the occurrence of this error.

@@ -28,4 +37,4 @@ */

this.name = 'DiagnosticError';
this.name = ErrorName.DiagnosticError;
}
}
export { AlreadyStoppedError } from './AlreadyStoppedError';
export { DiagnosticError } from './DiagnosticError';
export { InvalidOptionsError } from './InvalidOptionsError';
export { InvalidStateError } from './InvalidStateError';
export { PromiseTimedOutError } from './PromiseTimedOutError';
export { UnsupportedError } from './UnsupportedError';
export { InvalidOptionError } from './InvalidOptionError';
export { InvalidOptionsError } from './InvalidOptionsError';

@@ -0,1 +1,2 @@

import { ErrorName } from '../constants';
import { DiagnosticError } from './DiagnosticError';

@@ -19,4 +20,4 @@

this.reasons = reasons;
this.name = 'InvalidOptionsError';
this.name = ErrorName.InvalidOptionsError;
}
}

@@ -0,1 +1,2 @@

import { ErrorName } from '../constants';
import { DiagnosticError } from './DiagnosticError';

@@ -16,4 +17,4 @@

this.name = 'InvalidStateError';
this.name = ErrorName.InvalidStateError;
}
}

@@ -0,1 +1,2 @@

import { ErrorName } from '../constants';
import { DiagnosticError } from './DiagnosticError';

@@ -5,2 +6,4 @@

* @internalapi
* Error for when a browser-provided feature isn't available, such as
* `getUserMedia`.
*/

@@ -11,4 +14,4 @@ export class UnsupportedError extends DiagnosticError {

this.name = 'UnsupportedError';
this.name = ErrorName.UnsupportedError;
}
}

@@ -13,6 +13,18 @@ // Typescript doesn't yet support `setSinkId`, so we want to add it to the

* @internalapi
* Timing measurements that provides operational milestones.
*/
export interface TimeMeasurement {
duration: number;
end: number;
/**
* Number in milliseconds elapsed for this measurement.
*/
duration?: number;
/**
* A millisecond timestamp that represents the end of a process.
*/
end?: number;
/**
* A millisecond timestamp that represents the start of a process.
*/
start: number;

@@ -27,1 +39,51 @@ }

export type SubsetRequired<T, K extends keyof T> = T & Required<Pick<T, K>>;
/**
* @internalapi
* Volume statistics to track in the audio device tests.
*/
export interface VolumeStats {
/**
* The maximum volume value recorded during the test.
*/
max?: number;
/**
* The smallest non-zero volume value encountered.
*/
min?: number;
/**
* The timestamps of the recorded values. For example, the 0th indexed
* timestamp correlates to when the 0th indexed volume value was recorded.
*/
timestamps: number[];
/**
* The recorded volume values encountered during the test.
*/
values: number[];
}
/**
* Native MediaStream Recording APIs definitions
* @private
*/
export namespace MediaStreamRecorder {
export type AudioData = any;
export interface DataEvent {
data: AudioData;
}
export interface MediaRecorder {
ondataavailable: Function;
onstop: Function;
start: Function;
stop: Function;
}
}
/**
* Description of a video resolution.
* @internalapi
*/
export interface VideoResolution {
height: number;
width: number;
}

@@ -134,3 +134,3 @@ import {

export function validateDeviceId(option: any): Validity {
if (option && typeof option !== 'string') {
if (!(['string', 'undefined'].includes(typeof option) || option === null)) {
return 'If "deviceId" is defined, it must be a "string".';

@@ -191,3 +191,16 @@ }

* @internalapi
* Validate input options to the [[InputTest]].
* Validate that an option is a `boolean`.
* @param option The option to check.
* @returns A possibly undefined string, if the option is valid it will return
* `undefined`, otherwise a string representing why the option is invalid
*/
export function validateBoolean(option: any): Validity {
if (typeof option !== 'boolean') {
return `Option must be "boolean".`;
}
}
/**
* @internalapi
* Validate input options to the [[AudioInputTest]].
* @param inputOptions The options to validate.

@@ -194,0 +207,0 @@ * @param config A record of option names to either a single

{
"name": "@twilio/rtc-diagnostics",
"version": "1.0.0-preview3",
"version": "1.0.0",
"description": "Various diagnostics functions to help analyze connections to Twilio",

@@ -20,3 +20,3 @@ "main": "./es5/lib/diagnostics.js",

"test:unit": "nyc mocha -r ts-node/register ./tests/unit/index.ts",
"test:integration": "karma start"
"test:integration": "node ./scripts/env.js && karma start"
},

@@ -44,8 +44,9 @@ "contributors": [

"@types/mocha": "5.2.7",
"@types/sinon": "7.5.1",
"@types/request": "^2.48.5",
"@types/sinon": "9.0.4",
"browserify": "16.5.0",
"coverage": "0.4.1",
"is-docker": "2.0.0",
"karma": "4.4.1",
"karma-chrome-launcher": "3.1.0",
"karma-env-preprocessor": "^0.1.1",
"karma-firefox-launcher": "1.2.0",

@@ -58,4 +59,4 @@ "karma-mocha": "1.3.0",

"nyc": "15.0.0",
"twilio-release-tool": "1.0.1",
"sinon": "7.5.0",
"request": "^2.88.2",
"sinon": "9.0.2",
"travis-multirunner": "4.6.0",

@@ -66,2 +67,3 @@ "ts-node": "8.5.2",

"twilio": "3.39.1",
"twilio-release-tool": "1.0.1",
"typedoc": "0.16.11",

@@ -68,0 +70,0 @@ "typedoc-plugin-as-member-of": "1.0.2",

@@ -1,9 +0,10 @@

# Voice Diagnostics SDK
The Voice Diagnostics SDK provides functions to test input and output audio devices, and the functionality to test network bandwidth requirements towards Twilio’s servers.
# RTC Diagnostics SDK
The RTC Diagnostics SDK provides functions to test input and output devices (microphone, speaker, camera) as well as functionality to confirm that you meet the network bandwidth requirements required to make a voice call or join a video room.
This SDK requires the use of Twilio NTS to perform the network tests. Using NTS will incur charges as per [NTS pricing](https://www.twilio.com/stun-turn/pricing).
This SDK requires the use of Twilio NTS or your own STUN/TURN servers to perform the network tests. Using Twilio NTS will mirror how Twilio uses STUN/TURN in Programmable Video when connecting to a Twilio Video Room and will incur charges as per [NTS pricing](https://www.twilio.com/stun-turn/pricing).
## Features
* Input audio device tests include volume calculation
* Output audio device tests are done by playing a sound file to the selected device
* Input audio device tests
* Input video device tests
* Output audio device tests
* Bandwidth requirements tests

@@ -13,3 +14,3 @@

* A Twilio account. Sign up for free [here](https://www.twilio.com/try-twilio)
* Node.js v10+
* Node.js v12+
* NPM v6+ (comes installed with newer Node versions)

@@ -33,2 +34,5 @@

In order to run integration tests, you'll need to copy over the `credentials.example.json` file
to `credentials.json` in the same folder, and replace the empty fields with valid values.
### NPM

@@ -47,3 +51,3 @@ You can install directly from npm.

```ts
import { testBitrate } from '@twilio/rtc-diagnostics';
import { testMediaConnectionBitrate } from '@twilio/rtc-diagnostics';
```

@@ -59,3 +63,3 @@

```ts
const { testBitrate } = Twilio.Diagnostics;
const { testMediaConnectionBitrate } = Twilio.Diagnostics;
```

@@ -66,7 +70,7 @@

### BitrateTest Example
### MediaConnectionBitrateTest Example
```ts
import { testBitrate } from '@twilio/rtc-diagnostics';
import { testMediaConnectionBitrate } from '@twilio/rtc-diagnostics';
const bitrateTest = testBitrate({
const mediaConnectionBitrateTest = testMediaConnectionBitrate({
iceServers: [{

@@ -79,11 +83,11 @@ credential: 'bar',

bitrateTest.on('bitrate', (bitrate) => {
mediaConnectionBitrateTest.on('bitrate', (bitrate) => {
console.log(bitrate);
});
bitrateTest.on('error', (error) => {
mediaConnectionBitrateTest.on('error', (error) => {
console.log(error);
});
bitrateTest.on('end', (report) => {
mediaConnectionBitrateTest.on('end', (report) => {
console.log(report);

@@ -93,24 +97,24 @@ });

setTimeout(() => {
bitrateTest.stop();
mediaConnectionBitrateTest.stop();
}, 10000);
```
See `BitrateTest.Options` for more information for how to obtain the `urls values`
See `MediaConnectionBitrateTest.Options` for more information for how to obtain the `urls values`
### InputTest Example
### AudioInputTest Example
```ts
import { testInputDevice, InputTest } from '@twilio/rtc-diagnostics';
import { testAudioInputDevice, AudioInputTest } from '@twilio/rtc-diagnostics';
const outputDeviceTest = testInputDevice({
const audioInputDeviceTest = testAudioInputDevice({
deviceId: ...,
});
inputDeviceTest.on(InputTest.Events.Volume, (volume) => {
audioInputDeviceTest.on(AudioInputTest.Events.Volume, (volume) => {
console.log(volume);
});
inputDeviceTest.on(InputTest.Events.Error, (error) => {
audioInputDeviceTest.on(AudioInputTest.Events.Error, (error) => {
console.error(error);
});
inputDeviceTest.on(InputTest.Events.End, (report) => {
audioInputDeviceTest.on(AudioInputTest.Events.End, (report) => {
console.log(report);

@@ -120,23 +124,42 @@ });

setTimeout(() => {
inputDeviceTest.stop();
audioInputDeviceTest.stop();
}, 10000);
```
### OutputTest Example
### VideoInputTest Example
```ts
import { testOutputDevice, OutputTest } from '@twilio/rtc-diagnostics';
import { testVideoInputDevice, VideoInputTest } from '@twilio/rtc-diagnostics';
const outputDeviceTest = testOutputDevice({
const videoInputDeviceTest = testVideoInputDevice({ element: videoElement });
videoInputDeviceTest.on(VideoInputTest.Events.Error, (error) => {
console.error(error);
});
videoInputDeviceTest.on(VideoInputTest.Events.End, (report) => {
console.log(report);
});
setTimeout(() => {
videoInputDeviceTest.stop();
}, 10000);
```
### AudioOutputTest Example
```ts
import { testAudioOutputDevice, AudioOutputTest } from '@twilio/rtc-diagnostics';
const audioOutputDeviceTest = testAudioOutputDevice({
deviceId: ...,
});
outputDeviceTest.on(InputTest.Events.Volume, (volume) => {
audioOutputDeviceTest.on(AudioOutputTest.Events.Volume, (volume) => {
console.log(volume);
});
outputDeviceTest.on(InputTest.Events.Error, (error) => {
audioOutputDeviceTest.on(AudioOutputTest.Events.Error, (error) => {
console.error(error);
});
outputDeviceTest.on(InputTest.Events.End, (report) => {
audioOutputDeviceTest.on(AudioOutputTest.Events.End, (report) => {
console.log(report);

@@ -146,3 +169,3 @@ });

setTimeout(() => {
outputDeviceTest.stop();
audioOutputDeviceTest.stop();
}, 10000);

@@ -152,4 +175,18 @@ ```

## Related
### Testing Voice and Video calling readiness
* [Twilio Voice Client JS Preflight Test](https://github.com/twilio/twilio-client.js/blob/preflight/PREFLIGHT.md)
* [Twilio Video JS Preflight Test](https://github.com/twilio/twilio-video.js/blob/preflight_api/CHANGELOG.md#280-beta1-september-28-2020)
### Applications using Diagnostics and Preflight tests
* [Twilio Voice Diagnostics Tool](https://github.com/twilio/rtc-diagnostics-react-app)
* [Twilio Video JS React App](https://github.com/twilio/twilio-video-app-react)
### Voice and Video JS SDKs
* [Twilio Voice Client JS SDK](https://github.com/twilio/twilio-client.js)
* [Twilio Voice Client JS Quickstart](https://github.com/TwilioDevEd/client-quickstart-js)
* [Twilio Video JS SDK](https://github.com/twilio/twilio-video.js)
* [Twilio Video JS Quickstart](https://github.com/twilio/video-quickstart-js)
### Connectivity requirements
* [Twilio Client connectivity requirements](https://www.twilio.com/docs/voice/client/javascript/voice-client-js-and-mobile-sdks-network-connectivity-requirements)

@@ -156,0 +193,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc