/// import { EventEmitter } from 'events'; import { DiagnosticError } from './errors'; import { AudioElement, SubsetRequired, TimeMeasurement } from './types'; export declare interface AudioOutputTest { /** * This event is emitted when the test ends. * @param event [[AudioOutputTest.Events.End]] * @param report A summary of the test. * @private */ emit(event: AudioOutputTest.Events.End, report: AudioOutputTest.Report): boolean; /** * This event is emitted when the test encounters an error, fatal or not. * @param event [[AudioOutputTest.Events.Error]] * @param error An error that was encountered during the run time of the test. * @private */ emit(event: AudioOutputTest.Events.Error, error: DiagnosticError): boolean; /** * This event is emitted by the test after succesfully starting, and emits * the volume of the audio source every [[AudioOutputTest.Options.volumeEventIntervalMs]] * milliseconds. * @param event [[AudioOutputTest.Events.Volume]] * @param value The volume of the audio source. * @private */ emit(event: AudioOutputTest.Events.Volume, value: number): boolean; /** * Raised when the test ends. The stop condition depends on if the option * to loop was set to `true` or `false`. If `false`, then the test ends either * when the audio file is finished playing, or when a time has elapsed * greater than [[AudioOutputTest.Options.duration]]. * @event * @param event [[AudioOutputTest.Events.End]] * @param listener A listener function that expects the following parameters * when the event is raised: * - A [[AudioOutputTest.Report]] that summarizes the run time of the test. * @returns This [[AudioOutputTest]] instance. */ on(event: AudioOutputTest.Events.End, listener: (report: AudioOutputTest.Report) => any): this; /** * Raised when the test has run into an error, fatal or not. * @event * @param event [[AudioOutputTest.Events.Error]] * @param listener A listener function that expects the following parameters * when the event is raised: * - The [[DiagnosticError]]. * @returns This [[AudioOutputTest]] instance. */ on(event: AudioOutputTest.Events.Error, listener: (error: DiagnosticError) => any): this; /** * Raised every [[AudioOutputTest.Options.volumeEventIntervalMs]] after the test * starts successfully. Will have a `number` parameter representing the * current volume of the audio file. * @event * @param event [[AudioOutputTest.Events.Volume]] * @param listener A listener function that expects the following parameters * when the event is raised: * - A number representing the volume of the audio source. * @returns This [[AudioOutputTest]] instance. */ on(event: AudioOutputTest.Events.Volume, listener: (value: number) => any): this; } /** * [[AudioOutputTest]] class that parses options and starts an audio output device * test. * * Please see [[testAudioOutputDevice]] for details and recommended practices. */ export declare class AudioOutputTest extends EventEmitter { /** * The name of the test. */ static readonly testName: string; /** * Default options for the [[AudioOutputTest]]. Overwritten by any option passed * during the construction of the test. */ private static defaultOptions; /** * Holds `AudioElement`s that are attached to the DOM to load and play audio. */ private _audio; /** * An `AudioContext` that is used to process the audio source. */ private _audioContext; /** * The default media devices when starting the test. */ private _defaultDevices; /** * A timestamp of when the test ends. */ private _endTime; /** * An array of errors encountered by the test during its run time. */ private readonly _errors; /** * Options passed to and set in the constructor to be used during the run * time of the test. */ private _options; /** * A timestamp of when the test starts. This is set in the constructor and not * when the test succesfully starts. */ private _startTime; /** * Volume values generated by the test over its run time. */ private readonly _values; /** * Timeout created by `setTimeout`, used to loop the volume logic. */ private _volumeTimeout; /** * Sets up several things for the [[AudioOutputTest]] to run later in the * `_startTest` function. * @param options Optional settings to pass to the test. */ constructor(options?: AudioOutputTest.Options); /** * Stops the test. */ stop(): void; /** * Cleanup the test. */ private _cleanup; /** * Error event handler. Adds the error to the internal list of errors that is * forwarded in the report. * @param error */ private _onError; /** * Volume event handler, adds the value to the list `_values` and emits it * under the event `volume`. * @param volume */ private _onVolume; /** * Warning event handler. * @param warning */ private _onWarning; /** * Entry point of the test, called after setup in the constructor. * Emits the volume levels of the audio. * * @event [[AudioOutputTest.Events.Volume]] */ private _startTest; } export declare namespace AudioOutputTest { /** * Events that the [[AudioOutputTest]] will emit as it runs. * Please see [[AudioOutputTest.on]] for how to listen to these * events. */ enum Events { End = "end", Error = "error", Volume = "volume" } /** * Options passed to [[AudioOutputTest]] constructor. */ interface Options { /** * An `AudioContext` to be used by the test. * @private */ audioContextFactory?: typeof window.AudioContext; /** * A constuctor that is used to create an [[AudioElement]], useful for * mocks. * @private */ audioElementFactory?: new (...args: any[]) => AudioElement; /** * Whether or not to log debug statements to the console. * @private */ debug?: boolean; /** * The `deviceId` of the audio device to attempt to play audio out of. * This option is directly passed to [HTMLMediaElement.setSinkId](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId). */ deviceId?: string; /** * Whether or not to loop the audio. * See [[AudioOutputTest]] for details on the behavior of "timing out". * @default true */ doLoop?: boolean; /** * Duration in milliseconds to run the test for. If this amount of time elapses, the test * is considered "timed out". * See [[AudioOutputTest]] for details on the behavior of "timing out". * @default Infinity */ duration?: number; /** * Used to mock the call to `enumerateDevices`. * @private */ enumerateDevices?: typeof navigator.mediaDevices.enumerateDevices; /** * The URI of the audio file to use for the test. */ testURI?: string; /** * The interval between emissions of volume events in milliseconds. * @default 100 */ volumeEventIntervalMs?: number; } /** * Represents the report generated from an [[AudioOutputTest]]. */ interface Report { /** * The `deviceId` of the audio device used to play audio out of. */ deviceId: string | undefined; /** * Any errors that occurred during the run-time of the [[AudioOutputTest]]. */ errors: DiagnosticError[]; /** * Name of the test, set to [[AudioOutputTest.testName]]. */ testName: typeof AudioOutputTest.testName; /** * Time measurements of test run time. */ testTiming: TimeMeasurement; /** * The URI of the audio file used during the test. */ testURI?: string; /** * The volume values emitted by the test during its run-time. */ values: number[]; } /** * Option typing after initialization, so we can have type guarantees. * @private */ type InternalOptions = SubsetRequired; } /** * [[AudioOutputTest]] tests audio output capabilities. It serves to help diagnose * potential audio device issues that would prevent a user from being able to * hear audio. * * --- * * The [[AudioOutputTest]] class is an `EventEmitter` (please see [[AudioOutputTest.on]] for * events and their details) and helps to diagnose issues by playing a sound clip * (by default the sound clip is the ringing tone from the `twilio-client.js` * SDK) and emitting volume events of the sound clip as it plays. * ```ts * import { AudioOutputTest, testAudioOutputDevice } from '@twilio/rtc-diagnostics'; * const options: AudioOutputTest.Options = { ... }; * // `options` may be left `undefined` to use default option values * const audioOutputTest: AudioOutputTest = testAudioOutputDevice(options); * ``` * The application can use the volume events to show in its UI that audio is * playing and that the end-user should be hearing something. * ```ts * audioOutputTest.on(AudioOutputTest.Events.Volume, (volume: number) => { * ui.updateVolume(volume); // Update your UI with the volume value here. * }); * ``` * * The application should ask the end-user to confirm that the sound being played * can be heard. The application should call [[AudioOutputTest.stop]] with `true` if * the end-user hears the sound, and `false` if not. * ```ts * // If the user was able to hear the audio, the UI should indicate they should * // click this button... * const passButton = ...; * passButton.on('click', () => { * audioOutputTest.stop(); * // display a confirmation dialog to the user * }); * * // ...conversely, if they were not able to hear the audio, they should click * // this one. * const failButton = ...; * failButton.on('click', () => { * audioOutputTest.stop(); * // display a warning to the user * }); * ``` * Caling [[AudioOutputTest.stop]] will immediately end the test. * * --- * * The [[AudioOutputTest]] object will always emit a [[AudioOutputTest.Report]] with * the [[AudioOutputTest.Events.End]] event, regardless of the occurence of errors * during the runtime of the test. * * Fatal errors will immediately end the test and emit a report such that the * value of [[AudioOutputTest.Report.errors]] will contain the fatal error. * * Non-fatal errors will not end the test, but will be included in the value of * [[AudioOutputTest.Report.errors]] upon completion of the test. * * If the data at `testURI` is unable to be loaded, meaning the error event is * raised on the audio element, a fatal error has occurred. * * If `doLoop` is set to `false`, then the test will run for either the option * `duration`, or the full duration of the audio file, which ever is shorter. * If `doLoop` is set to `true`, it will only run as long as the `duration` * option. * * --- * * The function [[testAudioOutputDevice]] serves as factory function that accepts * [[AudioOutputTest.Options]] as its only parameter and will instantiate an * [[AudioOutputTest]] object with those options. * ```ts * import { AudioOutputTest, testAudioOutputDevice } from '@twilio/rtc-diagnostics'; * const options: AudioOutputTest.Options = { ... }; * const audioOutputTest: AudioOutputTest = testAudioOutputDevice(options); * ``` * @param options Options to pass to the [[AudioOutputTest]] constructor. */ export declare function testAudioOutputDevice(options?: AudioOutputTest.Options): AudioOutputTest;