mediasoup-client
Advanced tools
Comparing version 0.6.8 to 0.6.9
@@ -5,2 +5,4 @@ import Logger from './Logger'; | ||
const PROFILES = new Set([ 'low', 'medium', 'high' ]); | ||
const logger = new Logger('Consumer'); | ||
@@ -15,2 +17,3 @@ | ||
* @emits {originator: String, [appData]: Any} resume | ||
* @emits {profile: String} effectiveprofilechange | ||
* @emits unhandled | ||
@@ -68,2 +71,10 @@ * @emits {originator: String} close | ||
this._remotelyPaused = false; | ||
// Preferred profile. | ||
// @type {String} | ||
this._preferredProfile = null; | ||
// Effective profile. | ||
// @type {String} | ||
this._effectiveProfile = null; | ||
} | ||
@@ -192,2 +203,22 @@ | ||
/** | ||
* The preferred profile. | ||
* | ||
* @type {String} | ||
*/ | ||
get preferredProfile() | ||
{ | ||
return this._preferredProfile; | ||
} | ||
/** | ||
* The effective profile. | ||
* | ||
* @type {String} | ||
*/ | ||
get effectiveProfile() | ||
{ | ||
return this._effectiveProfile; | ||
} | ||
/** | ||
* Closes the Consumer. | ||
@@ -424,2 +455,66 @@ * This is called when the local Room is closed. | ||
/** | ||
* Set preferred receiving profile. | ||
* | ||
* @param {String} profile | ||
*/ | ||
setPreferredProfile(profile) | ||
{ | ||
logger.debug('setPreferredProfile() [profile:%s]', profile); | ||
if (this._closed) | ||
{ | ||
logger.error('setPreferredProfile() | Consumer closed'); | ||
return; | ||
} | ||
else if (profile === this._preferredProfile) | ||
{ | ||
return; | ||
} | ||
else if (!PROFILES.has(profile)) | ||
{ | ||
logger.error('setPreferredProfile() | invalid profile "%s"', profile); | ||
return; | ||
} | ||
this._preferredProfile = profile; | ||
if (this._transport) | ||
this._transport.setConsumerPreferredProfile(this, this._preferredProfile); | ||
} | ||
/** | ||
* Preferred receiving profile was set on my remote Consumer. | ||
* | ||
* @param {String} profile | ||
*/ | ||
remoteSetPreferredProfile(profile) | ||
{ | ||
logger.debug('remoteSetPreferredProfile() [profile:%s]', profile); | ||
if (this._closed || profile === this._preferredProfile) | ||
return; | ||
this._preferredProfile = profile; | ||
} | ||
/** | ||
* Effective receiving profile changed on my remote Consumer. | ||
* | ||
* @param {String} profile | ||
*/ | ||
remoteEffectiveProfileChanged(profile) | ||
{ | ||
logger.debug('remoteEffectiveProfileChanged() [profile:%s]', profile); | ||
if (this._closed || profile === this._effectiveProfile) | ||
return; | ||
this._effectiveProfile = profile; | ||
this.safeEmit('effectiveprofilechange', this._effectiveProfile); | ||
} | ||
/** | ||
* Mark this Consumer as suitable for reception or not. | ||
@@ -426,0 +521,0 @@ * |
@@ -112,2 +112,16 @@ import sdpTransform from 'sdp-transform'; | ||
{ | ||
// If simulcast is set, mangle the offer. | ||
if (producer.simulcast) | ||
{ | ||
logger.debug('addProducer() | enabling simulcast'); | ||
const sdpObject = sdpTransform.parse(offer.sdp); | ||
sdpPlanBUtils.addSimulcastForTrack(sdpObject, track); | ||
const offerSdp = sdpTransform.write(sdpObject); | ||
offer = { type: 'offer', sdp: offerSdp }; | ||
} | ||
logger.debug( | ||
@@ -242,2 +256,16 @@ 'addProducer() | calling pc.setLocalDescription() [offer:%o]', | ||
{ | ||
// If simulcast is set, mangle the offer. | ||
if (producer.simulcast) | ||
{ | ||
logger.debug('addProducer() | enabling simulcast'); | ||
const sdpObject = sdpTransform.parse(offer.sdp); | ||
sdpPlanBUtils.addSimulcastForTrack(sdpObject, track); | ||
const offerSdp = sdpTransform.write(sdpObject); | ||
offer = { type: 'offer', sdp: offerSdp }; | ||
} | ||
logger.debug( | ||
@@ -244,0 +272,0 @@ 'replaceProducerTrack() | calling pc.setLocalDescription() [offer:%o]', |
@@ -84,2 +84,6 @@ import sdpTransform from 'sdp-transform'; | ||
this._stream = new MediaStream(); | ||
// RID value counter for simulcast (so they never match). | ||
// @type {Number} | ||
this._nextRid = 1; | ||
} | ||
@@ -108,3 +112,53 @@ | ||
rtpSender = this._pc.addTrack(track, this._stream); | ||
}) | ||
.then(() => | ||
{ | ||
// If simulcast is not enabled, do nothing. | ||
if (!producer.simulcast) | ||
return; | ||
logger.debug('addProducer() | enabling simulcast'); | ||
const encodings = []; | ||
if (producer.simulcast.high) | ||
{ | ||
encodings.push( | ||
{ | ||
rid : `high${this._nextRid}`, | ||
active : true, | ||
priority : 'high', | ||
maxBitrate : producer.simulcast.high | ||
}); | ||
} | ||
if (producer.simulcast.medium) | ||
{ | ||
encodings.push( | ||
{ | ||
rid : `medium${this._nextRid}`, | ||
active : true, | ||
priority : 'medium', | ||
maxBitrate : producer.simulcast.medium | ||
}); | ||
} | ||
if (producer.simulcast.low) | ||
{ | ||
encodings.push( | ||
{ | ||
rid : `low${this._nextRid}`, | ||
active : true, | ||
priority : 'low', | ||
maxBitrate : producer.simulcast.low | ||
}); | ||
} | ||
// Update RID counter for future ones. | ||
this._nextRid++; | ||
return rtpSender.setParameters({ encodings }); | ||
}) | ||
.then(() => | ||
{ | ||
return this._pc.createOffer(); | ||
@@ -567,2 +621,21 @@ }) | ||
// NOTE: We need to add a real video track to get the RID extension mapping. | ||
const canvas = document.createElement('canvas'); | ||
// NOTE: Otherwise Firefox fails in next line. | ||
canvas.getContext('2d'); | ||
const fakeStream = canvas.captureStream(); | ||
const fakeVideoTrack = fakeStream.getVideoTracks()[0]; | ||
const rtpSender = pc.addTrack(fakeVideoTrack, fakeStream); | ||
rtpSender.setParameters( | ||
{ | ||
encodings : | ||
[ | ||
{ rid: 'RID1', maxBitrate: 40000 }, | ||
{ rid: 'RID2', maxBitrate: 10000 } | ||
] | ||
}); | ||
return pc.createOffer( | ||
@@ -575,2 +648,5 @@ { | ||
{ | ||
try { canvas.remove(); } | ||
catch (error) {} | ||
try { pc.close(); } | ||
@@ -586,2 +662,5 @@ catch (error) {} | ||
{ | ||
try { canvas.remove(); } | ||
catch (error2) {} | ||
try { pc.close(); } | ||
@@ -588,0 +667,0 @@ catch (error2) {} |
/** | ||
* Fill the given RTP parameters for the given track. | ||
* | ||
* NOTE: Currently it assumes a single encoding (no simulcast). | ||
* | ||
* @param {RTCRtpParameters} rtpParameters - RTP parameters to be filled. | ||
@@ -13,3 +11,2 @@ * @param {Object} sdpObj - Local SDP Object generated by sdp-transform. | ||
const kind = track.kind; | ||
const encoding = {}; | ||
const rtcp = | ||
@@ -28,2 +25,118 @@ { | ||
// First media SSRC (or the only one). | ||
let firstSsrc; | ||
// Get all the SSRCs. | ||
const ssrcs = new Set(); | ||
for (const line of mSection.ssrcs || []) | ||
{ | ||
if (line.attribute !== 'msid') | ||
continue; | ||
const trackId = line.value.split(' ')[1]; | ||
if (trackId === track.id) | ||
{ | ||
const ssrc = line.id; | ||
ssrcs.add(ssrc); | ||
if (!firstSsrc) | ||
firstSsrc = ssrc; | ||
} | ||
} | ||
if (ssrcs.size === 0) | ||
throw new Error(`a=ssrc line not found for local track [track.id:${track.id}]`); | ||
// Get media and RTX SSRCs. | ||
const ssrcToRtxSsrc = new Map(); | ||
// First assume RTX is used. | ||
for (const line of mSection.ssrcGroups || []) | ||
{ | ||
if (line.semantics !== 'FID') | ||
continue; | ||
let [ ssrc, rtxSsrc ] = line.ssrcs.split(/\s+/); | ||
ssrc = Number(ssrc); | ||
rtxSsrc = Number(rtxSsrc); | ||
if (ssrcs.has(ssrc)) | ||
{ | ||
// Remove both the SSRC and RTX SSRC from the Set so later we know that they | ||
// are already handled. | ||
ssrcs.delete(ssrc); | ||
ssrcs.delete(rtxSsrc); | ||
// Add to the map. | ||
ssrcToRtxSsrc.set(ssrc, rtxSsrc); | ||
} | ||
} | ||
// If the Set of SSRCs is not empty it means that RTX is not being used, so take | ||
// media SSRCs from there. | ||
for (const ssrc of ssrcs) | ||
{ | ||
// Add to the map. | ||
ssrcToRtxSsrc.set(ssrc, null); | ||
} | ||
// Get RTCP info. | ||
const ssrcCnameLine = mSection.ssrcs | ||
.find((line) => | ||
{ | ||
return (line.attribute === 'cname' && line.id === firstSsrc); | ||
}); | ||
if (ssrcCnameLine) | ||
rtcp.cname = ssrcCnameLine.value; | ||
// Fill RTP parameters. | ||
rtpParameters.rtcp = rtcp; | ||
rtpParameters.encodings = []; | ||
const simulcast = ssrcToRtxSsrc.size > 1; | ||
const simulcastProfiles = [ 'low', 'medium', 'high' ]; | ||
for (const [ ssrc, rtxSsrc ] of ssrcToRtxSsrc) | ||
{ | ||
const encoding = { ssrc }; | ||
if (rtxSsrc) | ||
encoding.rtx = { ssrc: rtxSsrc }; | ||
if (simulcast) | ||
encoding.profile = simulcastProfiles.shift(); | ||
rtpParameters.encodings.push(encoding); | ||
} | ||
} | ||
/** | ||
* Adds simulcast into the given SDP for the given track. | ||
* | ||
* @param {Object} sdpObj - Local SDP Object generated by sdp-transform. | ||
* @param {MediaStreamTrack} track | ||
*/ | ||
export function addSimulcastForTrack(sdpObj, track) | ||
{ | ||
const kind = track.kind; | ||
const mSection = (sdpObj.media || []) | ||
.find((m) => m.type === kind); | ||
if (!mSection) | ||
throw new Error(`m=${kind} section not found`); | ||
let ssrc; | ||
let rtxSsrc; | ||
let msid; | ||
// Get the SSRC. | ||
@@ -40,3 +153,8 @@ | ||
if (trackId === track.id) | ||
{ | ||
ssrc = line.id; | ||
msid = line.value.split(' ')[0]; | ||
return true; | ||
} | ||
}); | ||
@@ -47,6 +165,2 @@ | ||
const ssrc = ssrcMsidLine.id; | ||
encoding.ssrc = ssrc; | ||
// Get the SSRC for RTX. | ||
@@ -60,10 +174,8 @@ | ||
const ssrcs = line.ssrcs.split(/[ ]+/); | ||
const ssrcs = line.ssrcs.split(/\s+/); | ||
if (Number(ssrcs[0]) === ssrc) | ||
{ | ||
const rtxSsrc = Number(ssrcs[1]); | ||
rtxSsrc = Number(ssrcs[1]); | ||
encoding.rtx = { ssrc: rtxSsrc }; | ||
return true; | ||
@@ -73,4 +185,2 @@ } | ||
// Get RTCP info. | ||
const ssrcCnameLine = mSection.ssrcs | ||
@@ -82,8 +192,90 @@ .find((line) => | ||
if (ssrcCnameLine) | ||
rtcp.cname = ssrcCnameLine.value; | ||
if (!ssrcCnameLine) | ||
throw new Error(`CNAME line not found for local track [track.id:${track.id}]`); | ||
// Fill RTP parameters. | ||
rtpParameters.encodings = [ encoding ]; | ||
rtpParameters.rtcp = rtcp; | ||
const cname = ssrcCnameLine.value; | ||
const ssrc2 = ssrc + 1; | ||
const ssrc3 = ssrc + 2; | ||
mSection.ssrcGroups = mSection.ssrcGroups || []; | ||
mSection.ssrcGroups.push( | ||
{ | ||
semantics : 'SIM', | ||
ssrcs : `${ssrc} ${ssrc2} ${ssrc3}` | ||
}); | ||
mSection.ssrcs.push( | ||
{ | ||
id : ssrc2, | ||
attribute : 'cname', | ||
value : cname | ||
}); | ||
mSection.ssrcs.push( | ||
{ | ||
id : ssrc2, | ||
attribute : 'msid', | ||
value : `${msid} ${track.id}` | ||
}); | ||
mSection.ssrcs.push( | ||
{ | ||
id : ssrc3, | ||
attribute : 'cname', | ||
value : cname | ||
}); | ||
mSection.ssrcs.push( | ||
{ | ||
id : ssrc3, | ||
attribute : 'msid', | ||
value : `${msid} ${track.id}` | ||
}); | ||
if (rtxSsrc) | ||
{ | ||
const rtxSsrc2 = rtxSsrc + 1; | ||
const rtxSsrc3 = rtxSsrc + 2; | ||
mSection.ssrcGroups.push( | ||
{ | ||
semantics : 'FID', | ||
ssrcs : `${ssrc2} ${rtxSsrc2}` | ||
}); | ||
mSection.ssrcs.push( | ||
{ | ||
id : rtxSsrc2, | ||
attribute : 'cname', | ||
value : cname | ||
}); | ||
mSection.ssrcs.push( | ||
{ | ||
id : rtxSsrc2, | ||
attribute : 'msid', | ||
value : `${msid} ${track.id}` | ||
}); | ||
mSection.ssrcGroups.push( | ||
{ | ||
semantics : 'FID', | ||
ssrcs : `${ssrc3} ${rtxSsrc3}` | ||
}); | ||
mSection.ssrcs.push( | ||
{ | ||
id : rtxSsrc3, | ||
attribute : 'cname', | ||
value : cname | ||
}); | ||
mSection.ssrcs.push( | ||
{ | ||
id : rtxSsrc3, | ||
attribute : 'msid', | ||
value : `${msid} ${track.id}` | ||
}); | ||
} | ||
} |
@@ -187,2 +187,6 @@ import sdpTransform from 'sdp-transform'; | ||
// If video, be ready for simulcast. | ||
if (kind === 'video') | ||
remoteMediaObj.xGoogleFlag = 'conference'; | ||
remoteMediaObj.rtp = []; | ||
@@ -248,2 +252,9 @@ remoteMediaObj.rtcpFb = []; | ||
{ | ||
// Don't add a header extension if not present in the offer. | ||
const matchedLocalExt = (localMediaObj.ext || []) | ||
.find((localExt) => localExt.uri === ext.uri); | ||
if (!matchedLocalExt) | ||
continue; | ||
remoteMediaObj.ext.push( | ||
@@ -250,0 +261,0 @@ { |
@@ -257,2 +257,9 @@ import sdpTransform from 'sdp-transform'; | ||
{ | ||
// Don't add a header extension if not present in the offer. | ||
const matchedLocalExt = (localMediaObj.ext || []) | ||
.find((localExt) => localExt.uri === ext.uri); | ||
if (!matchedLocalExt) | ||
continue; | ||
remoteMediaObj.ext.push( | ||
@@ -266,2 +273,26 @@ { | ||
// Simulcast. | ||
if (localMediaObj.simulcast_03) | ||
{ | ||
// eslint-disable-next-line camelcase | ||
remoteMediaObj.simulcast_03 = | ||
{ | ||
value : localMediaObj.simulcast_03.value.replace(/send/g, 'recv') | ||
}; | ||
remoteMediaObj.rids = []; | ||
for (const rid of localMediaObj.rids || []) | ||
{ | ||
if (rid.direction !== 'send') | ||
continue; | ||
remoteMediaObj.rids.push( | ||
{ | ||
id : rid.id, | ||
direction : 'recv' | ||
}); | ||
} | ||
} | ||
remoteMediaObj.rtcpMux = 'rtcp-mux'; | ||
@@ -268,0 +299,0 @@ remoteMediaObj.rtcpRsize = 'rtcp-rsize'; |
/** | ||
* Fill the given RTP parameters for the given track. | ||
* | ||
* NOTE: Currently it assumes a single encoding (no simulcast). | ||
* | ||
* @param {RTCRtpParameters} rtpParameters - RTP parameters to be filled. | ||
@@ -13,3 +11,2 @@ * @param {Object} sdpObj - Local SDP Object generated by sdp-transform. | ||
const kind = track.kind; | ||
const encoding = {}; | ||
const rtcp = | ||
@@ -47,33 +44,52 @@ { | ||
if (!ssrcCnameLine) | ||
throw new Error(`a=ssrc line not found for local track [track.id:${track.id}]`); | ||
let ssrc; | ||
const ssrc = ssrcCnameLine.id; | ||
if (ssrcCnameLine) | ||
{ | ||
ssrc = ssrcCnameLine.id; | ||
rtcp.cname = ssrcCnameLine.value; | ||
} | ||
encoding.ssrc = ssrcCnameLine.id; | ||
rtcp.cname = ssrcCnameLine.value; | ||
// Get a=rid lines. | ||
// Get the SSRC for RTX. | ||
// Array of Objects with rid and profile keys. | ||
const simulcastStreams = []; | ||
(mSection.ssrcGroups || []) | ||
.some((line) => | ||
{ | ||
if (line.semantics !== 'FID') | ||
return; | ||
for (const rid of mSection.rids || []) | ||
{ | ||
if (rid.direction !== 'send') | ||
continue; | ||
const ssrcs = line.ssrcs.split(/[ ]+/); | ||
if (/^low/.test(rid.id)) | ||
simulcastStreams.push({ rid: rid.id, profile: 'low' }); | ||
else if (/^medium/.test(rid.id)) | ||
simulcastStreams.push({ rid: rid.id, profile: 'medium' }); | ||
if (/^high/.test(rid.id)) | ||
simulcastStreams.push({ rid: rid.id, profile: 'high' }); | ||
} | ||
if (Number(ssrcs[0]) === ssrc) | ||
{ | ||
const rtxSsrc = Number(ssrcs[1]); | ||
// Fill RTP parameters. | ||
encoding.rtx = { ssrc: rtxSsrc }; | ||
rtpParameters.rtcp = rtcp; | ||
rtpParameters.encodings = []; | ||
return true; | ||
} | ||
}); | ||
if (simulcastStreams.length === 0) | ||
{ | ||
const encoding = { ssrc }; | ||
// Fill RTP parameters. | ||
rtpParameters.encodings = [ encoding ]; | ||
rtpParameters.rtcp = rtcp; | ||
rtpParameters.encodings.push(encoding); | ||
} | ||
else | ||
{ | ||
for (const simulcastStream of simulcastStreams) | ||
{ | ||
const encoding = | ||
{ | ||
encodingId : simulcastStream.rid, | ||
profile : simulcastStream.profile | ||
}; | ||
rtpParameters.encodings.push(encoding); | ||
} | ||
} | ||
} |
@@ -6,2 +6,9 @@ import Logger from './Logger'; | ||
const SIMULCAST_DEFAULT = | ||
{ | ||
low : 100000, | ||
medium : 300000, | ||
high : 1500000 | ||
}; | ||
const logger = new Logger('Producer'); | ||
@@ -20,5 +27,4 @@ | ||
* @emits {originator: String, [appData]: Any} @close | ||
* | ||
*/ | ||
constructor(track, appData) | ||
constructor(track, options, appData) | ||
{ | ||
@@ -47,2 +53,9 @@ super(logger); | ||
// Simulcast. | ||
// @type {Object|false} | ||
this._simulcast = false; | ||
if (options.simulcast) | ||
this._simulcast = Object.assign({}, SIMULCAST_DEFAULT, options.simulcast); | ||
// Associated Transport. | ||
@@ -63,2 +76,5 @@ // @type {Transport} | ||
this._remotelyPaused = false; | ||
// Handle the effective track. | ||
this._handleTrack(); | ||
} | ||
@@ -117,2 +133,12 @@ | ||
/** | ||
* Simulcast settings. | ||
* | ||
* @return {Object|false} | ||
*/ | ||
get simulcast() | ||
{ | ||
return this._simulcast; | ||
} | ||
/** | ||
* App custom data. | ||
@@ -426,3 +452,3 @@ * | ||
// Stop the previous track. | ||
try { this._track.stop(); } | ||
try { this._track.onended = null; this._track.stop(); } | ||
catch (error) {} | ||
@@ -441,2 +467,5 @@ | ||
// Handle the effective track. | ||
this._handleTrack(); | ||
// Return the new track. | ||
@@ -458,2 +487,20 @@ return this._track; | ||
} | ||
/** | ||
* @private | ||
*/ | ||
_handleTrack() | ||
{ | ||
// If the cloned track is closed (for example if the desktop sharing is closed | ||
// via chrome UI) close the Producer. | ||
this._track.onended = () => | ||
{ | ||
if (this._closed) | ||
return; | ||
logger.warn('track "ended" event, closing Producer'); | ||
this.close(); | ||
}; | ||
} | ||
} |
@@ -475,2 +475,4 @@ import Logger from './Logger'; | ||
* @param {MediaStreamTrack} track | ||
* @param {Object} [options] | ||
* @param {Object} [options.simulcast] | ||
* @param {Any} [appData] - App custom data. | ||
@@ -484,5 +486,5 @@ * | ||
*/ | ||
createProducer(track, appData) | ||
createProducer(track, options, appData) | ||
{ | ||
logger.debug('createProducer() [track:%o]', track); | ||
logger.debug('createProducer() [track:%o, options:%o]', track, options); | ||
@@ -498,4 +500,6 @@ if (!this.joined) | ||
options = options || {}; | ||
// Create a new Producer. | ||
const producer = new Producer(track, appData); | ||
const producer = new Producer(track, options, appData); | ||
@@ -712,2 +716,38 @@ // Store it. | ||
case 'consumerPreferredProfileSet': | ||
{ | ||
const { id, peerName, profile } = notification; | ||
const peer = this._peers.get(peerName); | ||
if (!peer) | ||
throw new Error(`no Peer found [name:"${peerName}"]`); | ||
const consumer = peer.getConsumerById(id); | ||
if (!consumer) | ||
throw new Error(`Consumer not found [id:${id}]`); | ||
consumer.remoteSetPreferredProfile(profile); | ||
break; | ||
} | ||
case 'consumerEffectiveProfileChanged': | ||
{ | ||
const { id, peerName, profile } = notification; | ||
const peer = this._peers.get(peerName); | ||
if (!peer) | ||
throw new Error(`no Peer found [name:"${peerName}"]`); | ||
const consumer = peer.getConsumerById(id); | ||
if (!consumer) | ||
throw new Error(`Consumer not found [id:${id}]`); | ||
consumer.remoteEffectiveProfileChanged(profile); | ||
break; | ||
} | ||
default: | ||
@@ -714,0 +754,0 @@ throw new Error(`unknown notification method "${method}"`); |
@@ -416,2 +416,18 @@ import Logger from './Logger'; | ||
/** | ||
* @private | ||
*/ | ||
setConsumerPreferredProfile(consumer, profile) | ||
{ | ||
logger.debug('setConsumerPreferredProfile() [consumer:%o]', consumer); | ||
const data = | ||
{ | ||
id : consumer.id, | ||
profile : profile | ||
}; | ||
this.safeEmit('@notify', 'setConsumerPreferredProfile', data); | ||
} | ||
_execCommand(command, promiseHolder) | ||
@@ -557,5 +573,6 @@ { | ||
{ | ||
id : consumer.id, | ||
transportId : this.id, | ||
paused : consumer.locallyPaused | ||
id : consumer.id, | ||
transportId : this.id, | ||
paused : consumer.locallyPaused, | ||
preferredProfile : consumer.preferredProfile | ||
}; | ||
@@ -567,3 +584,3 @@ | ||
{ | ||
const { paused } = response; | ||
const { paused, preferredProfile, effectiveProfile } = response; | ||
@@ -573,2 +590,8 @@ if (paused) | ||
if (preferredProfile) | ||
consumer.remoteSetPreferredProfile(preferredProfile); | ||
if (effectiveProfile) | ||
consumer.remoteEffectiveProfileChanged(effectiveProfile); | ||
return consumerTrack; | ||
@@ -575,0 +598,0 @@ }); |
@@ -273,3 +273,4 @@ # mediasoup protocol | ||
transportId: 9999, | ||
paused: false | ||
paused: false, | ||
preferredProfile: 'low' | ||
} | ||
@@ -282,3 +283,5 @@ ``` | ||
{ | ||
paused : false | ||
paused: false, | ||
preferredProfile: null, | ||
effectiveProfile: 'default' | ||
} | ||
@@ -322,2 +325,18 @@ ``` | ||
### setConsumerPreferredProfile | ||
Set the desired receiving profile. | ||
Notification: | ||
```js | ||
{ | ||
method: 'setConsumerPreferredProfile', | ||
notification: true, | ||
id: 3333, | ||
profile: 'high' | ||
} | ||
``` | ||
## From server to client | ||
@@ -463,3 +482,5 @@ | ||
rtpParameters: {}, | ||
paused: false | ||
paused: false, | ||
preferredProfile: 'high', | ||
effectiveProfile: 'medium', | ||
appData: Any | ||
@@ -504,5 +525,5 @@ } | ||
### consumerClosed | ||
### consumerPreferredProfileSet | ||
A server-side `Consumer` has been closed (its originating `Peer` may have left the room, he may have closed it, or his server-side `Peer` or `Producer` may have been closed in the server). | ||
A server-side `Consumer` has set its preferred receiving profile. | ||
@@ -513,7 +534,25 @@ Notification: | ||
{ | ||
method: 'consumerClosed', | ||
method: 'consumerPreferredProfileSet', | ||
notification: true, | ||
id: 3333, | ||
peerName: 'alice' | ||
peerName: 'alice', | ||
profile: 'medium' | ||
} | ||
``` | ||
### consumerEffectiveProfileChanged | ||
The effective receiving profile in a server-side `Consumer` changed. | ||
Notification: | ||
```js | ||
{ | ||
method: 'consumerEffectiveProfileChanged', | ||
notification: true, | ||
id: 3333, | ||
peerName: 'alice', | ||
profile: 'high' | ||
} | ||
``` |
{ | ||
"name": "mediasoup-client", | ||
"version": "0.6.8", | ||
"version": "0.6.9", | ||
"description": "mediasoup client SDK for mediasoup >= 2.0.0", | ||
@@ -5,0 +5,0 @@ "author": "Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)", |
197628
6948