diff --git a/CHANGELOG.md b/CHANGELOG.md index 86b4dfba3..1ba8693e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ The Twilio Programmable Video SDKs use [Semantic Versioning](http://www.semver.o **Version 1.x reached End of Life on September 8th, 2021.** See the changelog entry [here](https://www.twilio.com/changelog/end-of-life-complete-for-unsupported-versions-of-the-programmable-video-sdk). Support for the 1.x version ended on December 4th, 2020. +2.26.1 (January 31, 2023) +========================= + +Bug Fixes +--------- + +- Fixed a bug that manifests on Chrome versions 112+ where `Room.getStats()` rejects the returned Promise due to a + TypeError caused by trying to read from the now-removed `RTCMediaStreamTrackStats`. Instead, the SDK now reads from + the `RTCMediaSourceStats`. (VIDEO-12411) +- Fixed an error in the type definition for the `attach()` method of `AudioTrack` and `VideoTrack`. (VIDEO-12242) +- Fixed an error in the type definition for `createLocalAudioTrack()`. (VIDEO-12383) + 2.26.0 (December 14, 2022) ========================== diff --git a/README.md b/README.md index 2fbe9d539..e90531dd5 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Releases of twilio-video.js are hosted on a CDN, and you can include these directly in your web app using a <script> tag. ```html - + ``` Using this method, twilio-video.js will set a browser global: diff --git a/lib/webrtc/getstats.js b/lib/webrtc/getstats.js index 453ba6572..68c4092ed 100644 --- a/lib/webrtc/getstats.js +++ b/lib/webrtc/getstats.js @@ -53,9 +53,7 @@ function _getStats(peerConnection, options) { [remoteVideoTracks, 'remoteVideoTrackStats', true] ], ([tracks, statsArrayName, isRemote]) => { return tracks.map(track => { - return getTrackStats(peerConnection, track, Object.assign({ - isRemote: isRemote - }, options)).then(trackStatsArray => { + return getTrackStats(peerConnection, track, Object.assign({ isRemote }, options)).then(trackStatsArray => { trackStatsArray.forEach(trackStats => { trackStats.trackId = track.id; statsResponse[statsArrayName].push(trackStats); @@ -470,7 +468,7 @@ function standardizeChromeOrSafariStats(response) { } }); - const isRemote = track && track.remoteSource; + const isRemote = track ? track.remoteSource : !localMedia; const mainSources = isRemote ? [inbound] : outbound; const stats = []; const remoteSource = isRemote ? remoteOutbound : remoteInbound; // remote rtp stats @@ -523,7 +521,7 @@ function standardizeChromeOrSafariStats(response) { standardizedStats.frameWidthReceived = frameWidth; } else { standardizedStats.frameWidthSent = frameWidth; - standardizedStats.frameWidthInput = track.frameWidth; + standardizedStats.frameWidthInput = track ? track.frameWidth : localMedia.width; } } @@ -533,7 +531,7 @@ function standardizeChromeOrSafariStats(response) { standardizedStats.frameHeightReceived = frameHeight; } else { standardizedStats.frameHeightSent = frameHeight; - standardizedStats.frameHeightInput = track.frameHeight; + standardizedStats.frameHeightInput = track ? track.frameHeight : localMedia.height; } } diff --git a/test/integration/spec/webrtc/getstats.js b/test/integration/spec/webrtc/getstats.js index d090f411c..b77dd6c83 100644 --- a/test/integration/spec/webrtc/getstats.js +++ b/test/integration/spec/webrtc/getstats.js @@ -96,6 +96,10 @@ const sdpFormat = getSdpFormat(); assert(trackStats, `expected to have property: ${stats}.${trackType}[0]`); [ + { key: 'frameWidthInput', type: 'number' }, + { key: 'frameHeightInput', type: 'number' }, + { key: 'frameWidthSent', type: 'number' }, + { key: 'frameHeightSent', type: 'number' }, { key: 'ssrc', type: 'string' }, { key: 'timestamp', type: 'number' }, { key: 'bytesReceived', type: 'number' }, diff --git a/tsdef/AudioTrack.d.ts b/tsdef/AudioTrack.d.ts index 7a89a9209..53e0b7f01 100644 --- a/tsdef/AudioTrack.d.ts +++ b/tsdef/AudioTrack.d.ts @@ -1,16 +1,5 @@ -import { Track } from './Track'; +import { MediaTrack } from './MediaTrack'; -export class AudioTrack extends Track { - isStarted: boolean; - isEnabled: boolean; +export class AudioTrack extends MediaTrack { kind: 'audio'; - mediaStreamTrack: MediaStreamTrack; - - attach(element?: HTMLMediaElement | string): HTMLMediaElement; - detach(element?: HTMLMediaElement | string): HTMLMediaElement[]; - - on(event: 'disabled', listener: (track: this) => void): this; - on(event: 'enabled', listener: (track: this) => void): this; - on(event: 'started', listener: (track: this) => void): this; - on(event: string, listener: (...args: any[]) => void): this; } diff --git a/tsdef/MediaTrack.d.ts b/tsdef/MediaTrack.d.ts new file mode 100644 index 000000000..d0d75d5ac --- /dev/null +++ b/tsdef/MediaTrack.d.ts @@ -0,0 +1,16 @@ +import { Track } from './Track'; + +export class MediaTrack extends Track { + isStarted: boolean; + isEnabled: boolean; + mediaStreamTrack: MediaStreamTrack; + + attach(element?: HTMLMediaElement | string): HTMLMediaElement; + detach(element: HTMLMediaElement | string): HTMLMediaElement; + detach(): HTMLMediaElement[]; + + on(event: 'disabled', listener: (track: this) => void): this; + on(event: 'enabled', listener: (track: this) => void): this; + on(event: 'started', listener: (track: this) => void): this; + on(event: string, listener: (...args: any[]) => void): this; +} diff --git a/tsdef/VideoTrack.d.ts b/tsdef/VideoTrack.d.ts index 7e169f4f6..2c419decc 100644 --- a/tsdef/VideoTrack.d.ts +++ b/tsdef/VideoTrack.d.ts @@ -1,4 +1,4 @@ -import { Track } from './Track'; +import { MediaTrack } from './MediaTrack'; import { VideoProcessor } from './VideoProcessor'; export namespace VideoTrack { @@ -8,22 +8,12 @@ export namespace VideoTrack { } } -export class VideoTrack extends Track { - isStarted: boolean; - isEnabled: boolean; +export class VideoTrack extends MediaTrack { dimensions: VideoTrack.Dimensions; kind: 'video'; processor: VideoProcessor | null; - mediaStreamTrack: MediaStreamTrack; processedTrack: MediaStreamTrack | null; addProcessor(processor: VideoProcessor): this; removeProcessor(processor: VideoProcessor): this; - attach(element?: HTMLMediaElement | string): HTMLVideoElement; - detach(element?: HTMLMediaElement | string): HTMLVideoElement[]; - - on(event: 'disabled', listener: (track: this) => void): this; - on(event: 'enabled', listener: (track: this) => void): this; - on(event: 'started', listener: (track: this) => void): this; - on(event: string, listener: (...args: any[]) => void): this; } diff --git a/tsdef/index.d.ts b/tsdef/index.d.ts index db94c6d1a..2def27966 100644 --- a/tsdef/index.d.ts +++ b/tsdef/index.d.ts @@ -12,7 +12,7 @@ export const isSupported: boolean; export const version:string; export const Logger: Log.RootLogger; export function connect(token: string, options?: ConnectOptions): CancelablePromise; -export function createLocalAudioTrack(options?: CreateLocalTracksOptions|CreateLocalAudioTrackOptions): Promise; +export function createLocalAudioTrack(options?: CreateLocalTrackOptions|CreateLocalAudioTrackOptions): Promise; export function createLocalTracks(options?: CreateLocalTracksOptions): Promise; export function createLocalVideoTrack(options?: CreateLocalTrackOptions): Promise; export function runPreflight(token: string, options?: PreflightOptions): PreflightTest; @@ -43,6 +43,9 @@ export { Room } from './Room'; export { Track } from './Track'; export { TrackPublication } from './TrackPublication'; export { TwilioError } from './TwilioError'; +export { VideoProcessor } from './VideoProcessor'; +export { VideoTrack } from './VideoTrack'; + export { AudioCodec, AudioCodecSettings, @@ -93,5 +96,3 @@ export { VideoTrackPublication, VP8CodecSettings } from './types'; -export { VideoProcessor } from './VideoProcessor'; -export { VideoTrack } from './VideoTrack'; diff --git a/tsdef/twilio-video-tests.ts b/tsdef/twilio-video-tests.ts index ef3d65806..e354e1bf6 100644 --- a/tsdef/twilio-video-tests.ts +++ b/tsdef/twilio-video-tests.ts @@ -346,6 +346,9 @@ function trackSubscribed(track: Video.VideoTrack | Video.AudioTrack) { } function trackUnsubscribed(track: Video.VideoTrack | Video.AudioTrack) { + const element = document.createElement(track.kind); + track.detach('#foo').remove(); + track.detach(element).remove(); track.detach().forEach(element => element.remove()); }