Skip to content

Latest commit

 

History

History
366 lines (292 loc) · 7.83 KB

File metadata and controls

366 lines (292 loc) · 7.83 KB

3. 串流

本地串流前置条件:

  1. 已经登录,获取了1.9 本地tokenStore,获得1.11.1的串流凭证gsToken
  2. 已经 获取 2.1 控制台信息

3.1 开始session

使用控制台的id,如F4001DF950A8A获得本次串流sessionId

API: https://uks.core.gssv-play-prodxhome.xboxlive.com/v5/sessions/home/play

Method: POST

header:

{
	'Content-Type': 'application/json',
	'X-MS-Device-Info': deviceInfo,
	'Authorization': 'Bearer '+ xHomeToken.GS_TOKEN,
}

其中deviceInfo是一个固定对象的stringify,如下:

const deviceInfo = JSON.stringify({
	'appInfo': {
		'env': {
			'clientAppId': 'Microsoft.GamingApp',
			'clientAppType': 'native',
			'clientAppVersion': '2203.1001.4.0',
			'clientSdkVersion': '8.5.2',
			'httpEnvironment': 'prod',
			'sdkInstallId': '',
		},
	},
	'dev': {
		'hw': {
			'make': 'Microsoft',
			'model': 'Surface Pro',
			'sdktype': 'native',
		},
		'os': {
			'name': 'Windows 11',
			'ver': '22631.2715',
			'platform': 'desktop',
		},
		'displayInfo': {
			'dimensions': {
				'widthInPixels': 1920,
				'heightInPixels': 1080,
			},
			'pixelDensity': {
				'dpiX': 1,
				'dpiY': 1,
			},
		},
	},
})

body: 只有一个变量serverId,为控制台的id,其他值都是固定值

JSON.stringify({
	clientSessionId: '',
	titleId: '',
	systemUpdateGroup: '',
	settings: {
		nanoVersion: 'V3;WebrtcTransport.dll',
		enableTextToSpeech: false,
		highContrast: 0,
		locale: "en-US",
		useIceConnection: false,
		timezoneOffsetMinutes: 120,
		sdkType: 'web',
		osName: 'windows',
	},
	serverId: serverId, // 控制台id
	fallbackRegionNames: [],
})

response:

{
    "sessionId": "04DBC99C-77BA-4D2E-B8D0-0B39CC16869C",
    "sessionPath": "v5/sessions/home/04DBC99C-77BA-4D2E-B8D0-0B39CC16869C",
    "state": "Provisioning"
}

返回的sessionId即为本次串流的回话id,接下来需要查询主机状态,待主机就绪后才进行webrtc协商。

3.2 轮询状态

前置条件:已经获得sessionId。

API: https://uks.core.gssv-play-prodxhome.xboxlive.com/v5/sessions/home/:sessionId/state

method: GET

header:

headers: {
	'Content-Type': 'application/json',
	'Authorization': 'Bearer '+ xHomeToken.GS_TOKEN,
}

response:

{
    "state": "Provisioning",
    "detailedSessionState": 0,
    "errorDetails": {
        "code": null,
        "message": null
    }
}

返回值state状态如下:

  • Provisioned: 准备就绪,可进入下一步操作3.3

  • Provisioning: 准备中,需再次查询

3.3 获取配置(可选)

待主机进入Provisioned状态后,需要先获得当前配置。

API: https://uks.core.gssv-play-prodxhome.xboxlive.com/v5/sessions/home/:sessionId/configuration

header:

headers: {
	'Content-Type': 'application/json',
	'Authorization': 'Bearer '+ xHomeToken.GS_TOKEN,
}

response:

{
    "keepAlivePulseInSeconds": 300,
    "serverDetails": {
        "ipAddress": "163.125.246.116",
        "port": 9002,
        "ipV4Address": "163.125.246.116",
        "ipV4Port": 9002,
        "ipV6Address": null,
        "ipV6Port": 0,
        "iceExchangePath": "v5/sessions/home/04DBC99C-77BA-4D2E-B8D0-0B39CC16869C/ice",
        "stunServerAddress": null,
        "srtp": {
            "key": "KqZGbZ0cXCvtxzD9z/63GAl2pfu+nB2maykK7Vbq"
        }
    }
}

3.4 创建sdp offer

webrtc示例调用createOfferAP创建sdp offer

webrtcClient.createOffer({
	offerToReceiveAudio: true,
	offerToReceiveVideo: true,
})

生成的sdp内容大致如下:

sdp

3.5 发送sdp offer

发送3.4创建的sdp offer

API: https://uks.core.gssv-play-prodxhome.xboxlive.com/v5/sessions/home/${params.sessionId}/sdp

method: POST

header:

headers: {
	'Accept': 'application/json',
	'Content-Type': 'application/json',
	'Authorization': 'Bearer '+ xHomeToken.GS_TOKEN,
}

body:

JSON.stringify({
		'messageType':'offer',
		'sdp': sdpOffer.sdp, // 创建的sdp,其他为固定内容
		'configuration':{
			'chatConfiguration':{
				'bytesPerSample':2,
				'expectedClipDurationMs':20,
				'format':{
					'codec':'opus',
					'container':'webm',
				},
				'numChannels':1,
				'sampleFrequencyHz':24000,
			},
			'chat':{
				'minVersion':1,
				'maxVersion':1,
			},
			'control':{
				'minVersion':1,
				'maxVersion':3,
			},
			'input':{
				'minVersion':1,
				'maxVersion':8,
			},
			'message':{
				'minVersion':1,
				'maxVersion':1,
			},
		},
	})

发送操作没有返回,需手动查询sdp发送结果

3.6 查询sdp发送结果

API: https://uks.core.gssv-play-prodxhome.xboxlive.com/v5/sessions/home/${params.sessionId}/sdp

method: GET

header:

headers: {
	'Content-Type': 'application/json',
	'Authorization': 'Bearer '+ xHomeToken.GS_TOKEN,
}

response:

{
    "exchangeResponse": "{\"chat\":1,\"chatConfiguration\":{\"format\":{\"codec\":\"opus\",\"container\":\"webm\"}},\"control\":3,\"input\":8,\"message\":1,\"messageType\...ns:trickle renomination\\r\\na=fingerprint:sha-256 E6:E8:C4:DC:10:B5:EB:1E:88:D1:09:62:D7:E8:E4:60:61:2A:ED:C0:90:47:90:51:96:5F:D2:09:99:21:D0:F4\\r\\na=setup:active\\r\\na=mid:2\\r\\na=sctp-port:5000\\r\\na=max-message-size:262144\\r\\n\",\"sdpType\":\"answer\",\"status\":\"success\"}",
    "errorDetails": {
        "code": null,
        "message": null
    }
}

返回exchangeResponse用于3.7设置远程sdp

3.7 设置远程sdp offer

将3.6返回的exchangeResponse进行JSON.parse,取sdp,调用setRemoteDescription API:

var sdpDetails = JSON.parse(sdpResponse.exchangeResponse)
_webrtcClient?.setRemoteDescription({
	type: 'answer',
	sdp: sdpDetails.sdp,
})

3.8 发送ICECandidates

待3.5发送了sdp后,webrtc示例监听icecandidate事件将接受到如图所示的通知事件:

sdp

将其缓存到待发送的ICECandidates中:

_webrtcClient?.addEventListener('icecandidate', event => {
	if (event.candidate) {
		console.log('xCloudPlayer Library.ts - ICE candidate found:', event.candidate)
		// this._iceCandidates = []
		this._iceCandidates.push(event.candidate)
	}
})

之后即可发送ICECandidates。

API: https://uks.core.gssv-play-prodxhome.xboxlive.com/v5/sessions/home/:sessionId/ice

method: POST

header:

headers: {
	'Accept': 'application/json',
	'Content-Type': 'application/json',
	'Authorization': 'Bearer '+ xHomeToken.GS_TOKEN,
}

body:

body: JSON.stringify({
	iceCandidates,
})

该请求通sdp不会返回内容,需3.8手动查询

3.9 查询ICECandidates发送结果

API: https://uks.core.gssv-play-prodxhome.xboxlive.com/v5/sessions/home/:sessionId/ice

method: GET

header:

headers: {
	'Content-Type': 'application/json',
	'Authorization': 'Bearer '+ xHomeToken.GS_TOKEN,
}

response:

{
    "exchangeResponse": "{\"chat\":1,\"chatConfiguration\":{\"format\":{\"codec\":\"opus\",\"container\":\"webm\"}},\"control\":3,\"input\":8,\"message\":1,\"messageType\...ns:trickle renomination\\r\\na=fingerprint:sha-256 E6:E8:C4:DC:10:B5:EB:1E:88:D1:09:62:D7:E8:E4:60:61:2A:ED:C0:90:47:90:51:96:5F:D2:09:99:21:D0:F4\\r\\na=setup:active\\r\\na=mid:2\\r\\na=sctp-port:5000\\r\\na=max-message-size:262144\\r\\n\",\"sdpType\":\"answer\",\"status\":\"success\"}",
    "errorDetails": {
        "code": null,
        "message": null
    }
}

返回exchangeResponse用于3.10设置远程ice

3.10 设置远程ICECandidates

将3.9返回的exchangeResponse进行JSON.parse,调用setIceCandidates API:

var iceDetails = JSON.parse(iceResponse.exchangeResponse)
this._webrtcClient?.addIceCandidate({
	candidate: iceDetails[candidate].candidate,
	sdpMid: iceDetails[candidate].sdpMid,
	sdpMLineIndex: iceDetails[candidate].sdpMLineIndex,
})

3.11 终止session(停止串流)

前置条件:已经获得sessionId。

API: https://uks.core.gssv-play-prodxhome.xboxlive.com/v5/sessions/home/:sessionId

method: DELETE

无返回