@reactoo/watchtogether-sdk-js 2.7.85 → 2.7.86-beta.1
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.
- package/dist/watchtogether-sdk.js +221 -124
- package/dist/watchtogether-sdk.js.map +1 -1
- package/dist/watchtogether-sdk.min.js +2 -2
- package/package.json +1 -1
- package/src/modules/wt-room.js +228 -95
package/package.json
CHANGED
package/src/modules/wt-room.js
CHANGED
|
@@ -264,11 +264,11 @@ class RoomSession {
|
|
|
264
264
|
this.isVideoEnabled = false;
|
|
265
265
|
this.isAudioEnabed = false;
|
|
266
266
|
this._statsMaxLength = 31;
|
|
267
|
-
this._upStatsLength =
|
|
268
|
-
this._downStatsLength =
|
|
267
|
+
this._upStatsLength = 10;
|
|
268
|
+
this._downStatsLength = 2;
|
|
269
269
|
this._statsTimeoutStopped = true;
|
|
270
270
|
this._statsTimeoutId = null;
|
|
271
|
-
this._statsInterval =
|
|
271
|
+
this._statsInterval = 3000;
|
|
272
272
|
this._aqInterval = 2500;
|
|
273
273
|
this._aqIntervalCounter = 0;
|
|
274
274
|
this._aqIntervalDivisor = 4;
|
|
@@ -1641,16 +1641,13 @@ class RoomSession {
|
|
|
1641
1641
|
}
|
|
1642
1642
|
this._statsTimeoutStopped = false;
|
|
1643
1643
|
const loop = () => {
|
|
1644
|
-
let startTime = performance.now();
|
|
1645
|
-
let endTime = null;
|
|
1646
1644
|
this._getStats('video')
|
|
1647
1645
|
.then(participantsStats => {
|
|
1648
|
-
endTime = performance.now();
|
|
1649
1646
|
this._parseVideoStats(participantsStats);
|
|
1650
1647
|
})
|
|
1651
1648
|
.finally(() => {
|
|
1652
1649
|
if (!this._statsTimeoutStopped) {
|
|
1653
|
-
this._statsTimeoutId = setTimeout(loop, this._statsInterval
|
|
1650
|
+
this._statsTimeoutId = setTimeout(loop, this._statsInterval);
|
|
1654
1651
|
}
|
|
1655
1652
|
})
|
|
1656
1653
|
};
|
|
@@ -1789,106 +1786,242 @@ class RoomSession {
|
|
|
1789
1786
|
return medianStats;
|
|
1790
1787
|
}
|
|
1791
1788
|
|
|
1789
|
+
|
|
1792
1790
|
_parseVideoStats(participantsStats) {
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1791
|
+
for (const sourceStats of participantsStats) {
|
|
1792
|
+
|
|
1793
|
+
for (const participantStats of sourceStats) {
|
|
1794
|
+
|
|
1795
|
+
if (!participantStats?.handleId || participantStats.handleId === this.handleId) continue;
|
|
1796
|
+
|
|
1797
|
+
const handle = this._getHandle(participantStats.handleId);
|
|
1798
|
+
if (!handle) continue;
|
|
1799
|
+
|
|
1800
|
+
const mid = participantStats.mid;
|
|
1801
|
+
handle.webrtcStuff.stats[mid] ??= [];
|
|
1802
|
+
|
|
1803
|
+
const lastStats = handle.webrtcStuff.stats[mid][handle.webrtcStuff.stats[mid].length - 1];
|
|
1804
|
+
|
|
1805
|
+
const stats = {
|
|
1806
|
+
framesPerSecond: null,
|
|
1807
|
+
framesDropped: null,
|
|
1808
|
+
totalFreezesDuration: null,
|
|
1809
|
+
freezeDurationSinceLast: null,
|
|
1810
|
+
freezeCount: null,
|
|
1811
|
+
freezeCountSinceLast: null,
|
|
1812
|
+
jitter: null,
|
|
1813
|
+
packetsLost: null,
|
|
1814
|
+
nackCount: null,
|
|
1815
|
+
roundTripTime: null,
|
|
1816
|
+
width: null,
|
|
1817
|
+
height: null,
|
|
1818
|
+
networkType: null,
|
|
1819
|
+
powerEfficientDecoder: null,
|
|
1820
|
+
selectedSubstream: null,
|
|
1821
|
+
desiredSubstream: null,
|
|
1822
|
+
simulcastMode: null
|
|
1823
|
+
};
|
|
1802
1824
|
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
stats.totalFreezesDuration = report.totalFreezesDuration || 0;
|
|
1828
|
-
stats.freezeDurationSinceLast = (report.totalFreezesDuration || 0) - (handle.webrtcStuff.stats?.[participantStats.mid]?.[handle.webrtcStuff.stats?.[participantStats.mid]?.length - 1]?.totalFreezesDuration || 0);
|
|
1829
|
-
stats.freezeCount = report.freezeCount || 0;
|
|
1830
|
-
stats.freezeCountSinceLast = (report.freezeCount || 0) - (handle.webrtcStuff.stats?.[participantStats.mid]?.[handle.webrtcStuff.stats?.[participantStats.mid]?.length - 1]?.freezeCount || 0);
|
|
1831
|
-
stats.jitter = report.jitter;
|
|
1832
|
-
stats.packetsLost = report.packetsLost;
|
|
1833
|
-
stats.nackCount = report.nackCount;
|
|
1834
|
-
stats.width = report.frameWidth;
|
|
1835
|
-
stats.height = report.frameHeight;
|
|
1836
|
-
stats.powerEfficientDecoder = report.powerEfficientDecoder;
|
|
1837
|
-
}
|
|
1838
|
-
if(report.type === 'candidate-pair') {
|
|
1839
|
-
stats.roundTripTime = report.currentRoundTripTime;
|
|
1840
|
-
}
|
|
1841
|
-
if(report.type === 'local-candidate') {
|
|
1842
|
-
stats.networkType = report.networkType;
|
|
1843
|
-
}
|
|
1825
|
+
const simulcastConfig = this._findSimulcastConfig(participantStats.source, this.simulcastSettings);
|
|
1826
|
+
const defaultSelectedSubstream = handle.webrtcStuff?.overriddenSimulcastMode[mid]?.defaultSubstream ?? simulcastConfig?.defaultSubstream;
|
|
1827
|
+
const simulcastMode = handle.webrtcStuff?.overriddenSimulcastMode[mid]?.mode ?? simulcastConfig?.mode;
|
|
1828
|
+
|
|
1829
|
+
participantStats.stats.forEach(report => {
|
|
1830
|
+
|
|
1831
|
+
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
1832
|
+
stats.framesPerSecond = report.framesPerSecond || 0;
|
|
1833
|
+
stats.framesDropped = report.framesDropped || 0;
|
|
1834
|
+
stats.totalFreezesDuration = report.totalFreezesDuration || 0;
|
|
1835
|
+
stats.freezeDurationSinceLast = (report.totalFreezesDuration || 0) - (lastStats?.totalFreezesDuration || 0);
|
|
1836
|
+
stats.freezeCount = report.freezeCount || 0;
|
|
1837
|
+
stats.freezeCountSinceLast = (report.freezeCount || 0) - (lastStats?.freezeCount || 0);
|
|
1838
|
+
stats.jitter = report.jitter;
|
|
1839
|
+
stats.packetsLost = report.packetsLost;
|
|
1840
|
+
stats.nackCount = report.nackCount;
|
|
1841
|
+
stats.width = report.frameWidth;
|
|
1842
|
+
stats.height = report.frameHeight;
|
|
1843
|
+
stats.powerEfficientDecoder = report.powerEfficientDecoder;
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
if (report.type === 'candidate-pair') {
|
|
1847
|
+
stats.roundTripTime = report.currentRoundTripTime;
|
|
1848
|
+
}
|
|
1844
1849
|
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1850
|
+
if (report.type === 'local-candidate') {
|
|
1851
|
+
stats.networkType = report.networkType;
|
|
1852
|
+
}
|
|
1853
|
+
});
|
|
1848
1854
|
|
|
1849
|
-
|
|
1855
|
+
stats.selectedSubstream = handle.webrtcStuff.selectedSubstream[mid];
|
|
1856
|
+
stats.desiredSubstream = defaultSelectedSubstream;
|
|
1857
|
+
stats.simulcastMode = simulcastMode;
|
|
1850
1858
|
|
|
1851
|
-
|
|
1852
|
-
handle.webrtcStuff.stats[participantStats.mid].push(stats);
|
|
1853
|
-
if(handle.webrtcStuff.stats[participantStats.mid].length > this._statsMaxLength) {
|
|
1854
|
-
handle.webrtcStuff.stats[participantStats.mid].shift();
|
|
1855
|
-
}
|
|
1859
|
+
handle.webrtcStuff.stats[mid].push(stats);
|
|
1856
1860
|
|
|
1857
|
-
|
|
1858
|
-
|
|
1861
|
+
if (handle.webrtcStuff.stats[mid].length > this._statsMaxLength) {
|
|
1862
|
+
handle.webrtcStuff.stats[mid].shift();
|
|
1859
1863
|
}
|
|
1860
|
-
});
|
|
1861
|
-
})
|
|
1862
1864
|
|
|
1865
|
+
this.emit('rtcStats', {
|
|
1866
|
+
handleId: participantStats.handleId,
|
|
1867
|
+
stats,
|
|
1868
|
+
userId: decodeJanusDisplay(handle.userId)?.userId,
|
|
1869
|
+
source: participantStats.source,
|
|
1870
|
+
mid
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1863
1874
|
}
|
|
1864
1875
|
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1876
|
+
// _parseVideoStats(participantsStats) {
|
|
1877
|
+
// participantsStats.forEach(sourceStats => {
|
|
1878
|
+
// sourceStats.forEach(participantStats => {
|
|
1879
|
+
// if(participantStats !== null && participantStats?.handle?.handleId !== this.handleId) {
|
|
1880
|
+
// let handle = this._getHandle(participantStats.handle.handleId);
|
|
1881
|
+
// if(handle) {
|
|
1882
|
+
//
|
|
1883
|
+
// if(!handle.webrtcStuff.stats[participantStats.mid]) {
|
|
1884
|
+
// handle.webrtcStuff.stats[participantStats.mid] = [];
|
|
1885
|
+
// }
|
|
1886
|
+
//
|
|
1887
|
+
// const stats = {
|
|
1888
|
+
// framesPerSecond: null,
|
|
1889
|
+
// framesDropped: null,
|
|
1890
|
+
// totalFreezesDuration: null,
|
|
1891
|
+
// freezeDurationSinceLast: null,
|
|
1892
|
+
// freezeCount: null,
|
|
1893
|
+
// jitter: null,
|
|
1894
|
+
// packetsLost: null,
|
|
1895
|
+
// nackCount: null,
|
|
1896
|
+
// roundTripTime: null,
|
|
1897
|
+
// width: null,
|
|
1898
|
+
// height: null,
|
|
1899
|
+
// networkType: null,
|
|
1900
|
+
// powerEfficientDecoder: null,
|
|
1901
|
+
// };
|
|
1902
|
+
// participantStats.stats.forEach(report => {
|
|
1903
|
+
//
|
|
1904
|
+
// const simulcastConfigForSource = this._findSimulcastConfig(participantStats.source, this.simulcastSettings);
|
|
1905
|
+
// const defaultSelectedSubstream = handle.webrtcStuff?.overriddenSimulcastMode[participantStats.mid]?.defaultSubstream ?? simulcastConfigForSource?.defaultSubstream;
|
|
1906
|
+
// const simulcastMode = handle.webrtcStuff?.overriddenSimulcastMode[participantStats.mid]?.mode ?? simulcastConfigForSource?.mode ;
|
|
1907
|
+
//
|
|
1908
|
+
// if(report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
1909
|
+
// stats.framesPerSecond = report.framesPerSecond || 0;
|
|
1910
|
+
// stats.framesDropped = report.framesDropped || 0;
|
|
1911
|
+
// stats.totalFreezesDuration = report.totalFreezesDuration || 0;
|
|
1912
|
+
// stats.freezeDurationSinceLast = (report.totalFreezesDuration || 0) - (handle.webrtcStuff.stats?.[participantStats.mid]?.[handle.webrtcStuff.stats?.[participantStats.mid]?.length - 1]?.totalFreezesDuration || 0);
|
|
1913
|
+
// stats.freezeCount = report.freezeCount || 0;
|
|
1914
|
+
// stats.freezeCountSinceLast = (report.freezeCount || 0) - (handle.webrtcStuff.stats?.[participantStats.mid]?.[handle.webrtcStuff.stats?.[participantStats.mid]?.length - 1]?.freezeCount || 0);
|
|
1915
|
+
// stats.jitter = report.jitter;
|
|
1916
|
+
// stats.packetsLost = report.packetsLost;
|
|
1917
|
+
// stats.nackCount = report.nackCount;
|
|
1918
|
+
// stats.width = report.frameWidth;
|
|
1919
|
+
// stats.height = report.frameHeight;
|
|
1920
|
+
// stats.powerEfficientDecoder = report.powerEfficientDecoder;
|
|
1921
|
+
// }
|
|
1922
|
+
// if(report.type === 'candidate-pair') {
|
|
1923
|
+
// stats.roundTripTime = report.currentRoundTripTime;
|
|
1924
|
+
// }
|
|
1925
|
+
// if(report.type === 'local-candidate') {
|
|
1926
|
+
// stats.networkType = report.networkType;
|
|
1927
|
+
// }
|
|
1928
|
+
//
|
|
1929
|
+
// stats.selectedSubstream = handle.webrtcStuff.selectedSubstream[participantStats.mid];
|
|
1930
|
+
// stats.desiredSubstream = defaultSelectedSubstream;
|
|
1931
|
+
// stats.simulcastMode = simulcastMode;
|
|
1932
|
+
//
|
|
1933
|
+
// });
|
|
1934
|
+
//
|
|
1935
|
+
// // pushing stats into handle stats array but keeping only 6 last stats
|
|
1936
|
+
// handle.webrtcStuff.stats[participantStats.mid].push(stats);
|
|
1937
|
+
// if(handle.webrtcStuff.stats[participantStats.mid].length > this._statsMaxLength) {
|
|
1938
|
+
// handle.webrtcStuff.stats[participantStats.mid].shift();
|
|
1939
|
+
// }
|
|
1940
|
+
//
|
|
1941
|
+
// this.emit('rtcStats', {handleId: participantStats.handle.handleId, stats, userId: decodeJanusDisplay(participantStats.handle.userId)?.userId, source: participantStats.source, mid: participantStats.mid});
|
|
1942
|
+
// }
|
|
1943
|
+
// }
|
|
1944
|
+
// });
|
|
1945
|
+
// })
|
|
1946
|
+
//
|
|
1947
|
+
// }
|
|
1889
1948
|
|
|
1890
1949
|
|
|
1891
|
-
|
|
1950
|
+
_getStats(type = null) {
|
|
1951
|
+
return this._participants.reduce((promise, participant) => {
|
|
1952
|
+
return promise.then(results => {
|
|
1953
|
+
let mediaTrack = [];
|
|
1954
|
+
if (type === 'video') {
|
|
1955
|
+
mediaTrack = participant?.webrtcStuff?.stream?.getVideoTracks() || [];
|
|
1956
|
+
} else if (type === 'audio') {
|
|
1957
|
+
mediaTrack = participant?.webrtcStuff?.stream?.getAudioTracks() || [];
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
if (type !== null) {
|
|
1961
|
+
const transceivers = participant?.webrtcStuff?.pc?.getTransceivers();
|
|
1962
|
+
return Promise.all(mediaTrack.map(track => {
|
|
1963
|
+
const source = Object.keys(participant.webrtcStuff.streamMap).find(s =>
|
|
1964
|
+
participant.webrtcStuff.streamMap[s].find(t => t === track.id)
|
|
1965
|
+
);
|
|
1966
|
+
const mid = transceivers.find(t =>
|
|
1967
|
+
t.receiver?.track?.id === track.id || t.sender?.track?.id === track.id
|
|
1968
|
+
)?.mid;
|
|
1969
|
+
|
|
1970
|
+
return participant.webrtcStuff.pc.getStats(track)
|
|
1971
|
+
.then(r => ({
|
|
1972
|
+
stats: r,
|
|
1973
|
+
source,
|
|
1974
|
+
mid,
|
|
1975
|
+
handleId: participant.handleId
|
|
1976
|
+
}))
|
|
1977
|
+
.catch(e => Promise.reject({
|
|
1978
|
+
stats: null,
|
|
1979
|
+
error: e,
|
|
1980
|
+
handleId: participant.handleId,
|
|
1981
|
+
source,
|
|
1982
|
+
mid
|
|
1983
|
+
}));
|
|
1984
|
+
})).then(participantResults => [...results, participantResults]);
|
|
1985
|
+
} else {
|
|
1986
|
+
return participant?.webrtcStuff?.pc?.getStats(null)
|
|
1987
|
+
.then(r => [...results, {
|
|
1988
|
+
handleId: participant.handleId,
|
|
1989
|
+
stats: r
|
|
1990
|
+
}])
|
|
1991
|
+
.catch(e => [...results, {
|
|
1992
|
+
handleId: participant.handleId,
|
|
1993
|
+
error: e
|
|
1994
|
+
}]);
|
|
1995
|
+
}
|
|
1996
|
+
});
|
|
1997
|
+
}, Promise.resolve([]));
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
// _getStats(type = null) {
|
|
2001
|
+
// return Promise.all(this._participants.map(participant => {
|
|
2002
|
+
// let mediaTrack = [];
|
|
2003
|
+
// if (type === 'video') {
|
|
2004
|
+
// mediaTrack = participant?.webrtcStuff?.stream?.getVideoTracks() || [];
|
|
2005
|
+
// } else if (type === 'audio') {
|
|
2006
|
+
// mediaTrack = participant?.webrtcStuff?.stream?.getAudioTracks() || [];
|
|
2007
|
+
// }
|
|
2008
|
+
// if(type !== null ) {
|
|
2009
|
+
// const transceivers = participant?.webrtcStuff?.pc?.getTransceivers();
|
|
2010
|
+
// return Promise.all(mediaTrack.map(track => {
|
|
2011
|
+
// const source = Object.keys(participant.webrtcStuff.streamMap).find(s => participant.webrtcStuff.streamMap[s].find(t => t === track.id));
|
|
2012
|
+
// const mid = transceivers.find(t => t.receiver?.track?.id === track.id || t.sender?.track?.id === track.id)?.mid;
|
|
2013
|
+
// return participant.webrtcStuff.pc.getStats(track)
|
|
2014
|
+
// .then(r =>({stats: r, source, mid, handleId: participant.handleId}))
|
|
2015
|
+
// .catch(e => Promise.reject({stats: null, error: e,handleId: participant.handleId, source, mid}))
|
|
2016
|
+
// }))
|
|
2017
|
+
// }
|
|
2018
|
+
// else {
|
|
2019
|
+
// return participant?.webrtcStuff?.pc?.getStats(null)
|
|
2020
|
+
// .then(r => ({handleId: participant.handleId, stats: r}))
|
|
2021
|
+
// .catch(e => Promise.reject({ handleId: participant.handleId, error: e}))
|
|
2022
|
+
// }
|
|
2023
|
+
// }))
|
|
2024
|
+
// }
|
|
1892
2025
|
|
|
1893
2026
|
_resetStats(handleId, mid) {
|
|
1894
2027
|
let handle = this._getHandle(handleId);
|