janus视频房间插件协议整理

一、房间配置参数

room-<unique room ID>: {
	description = This is my awesome room
	is_private = true|false (private rooms don't appear when you do a 'list' request, default=false)
	secret = <optional password needed for manipulating (e.g. destroying) the room>
	pin = <optional password needed for joining the room>
	require_pvtid = true|false (whether subscriptions are required to provide a valid private_id
				 to associate with a publisher, default=false)
	publishers = <max number of concurrent senders> (e.g., 6 for a video
				 conference or 1 for a webinar, default=3)
	bitrate = <max video bitrate for senders> (e.g., 128000)
	bitrate_cap = <true|false, whether the above cap should act as a limit to dynamic bitrate changes by publishers, default=false>,
	fir_freq = <send a FIR to publishers every fir_freq seconds> (0=disable)
	audiocodec = opus|g722|pcmu|pcma|isac32|isac16 (audio codec to force on publishers, default=opus
				can be a comma separated list in order of preference, e.g., opus,pcmu)
	videocodec = vp8|vp9|h264|av1|h265 (video codec to force on publishers, default=vp8
				can be a comma separated list in order of preference, e.g., vp9,vp8,h264)
	vp9_profile = VP9-specific profile to prefer (e.g., "2" for "profile-id=2")
	h264_profile = H.264-specific profile to prefer (e.g., "42e01f" for "profile-level-id=42e01f")
	opus_fec = true|false (whether inband FEC must be negotiated; only works for Opus, default=false)
	video_svc = true|false (whether SVC support must be enabled; only works for VP9, default=false)
	audiolevel_ext = true|false (whether the ssrc-audio-level RTP extension must be
		negotiated/used or not for new publishers, default=true)
	audiolevel_event = true|false (whether to emit event to other users or not, default=false)
	audio_active_packets = 100 (number of packets with audio level, default=100, 2 seconds)
	audio_level_average = 25 (average value of audio level, 127=muted, 0='too loud', default=25)
	videoorient_ext = true|false (whether the video-orientation RTP extension must be
		negotiated/used or not for new publishers, default=true)
	playoutdelay_ext = true|false (whether the playout-delay RTP extension must be
		negotiated/used or not for new publishers, default=true)
	transport_wide_cc_ext = true|false (whether the transport wide CC RTP extension must be
		negotiated/used or not for new publishers, default=true)
	record = true|false (whether this room should be recorded, default=false)
	rec_dir = <folder where recordings should be stored, when enabled>
	lock_record = true|false (whether recording can only be started/stopped if the secret
				is provided, or using the global enable_recording request, default=false)
	notify_joining = true|false (optional, whether to notify all participants when a new
				participant joins the room. The Videoroom plugin by design only notifies
				new feeds (publishers), and enabling this may result extra notification
				traffic. This flag is particularly useful when enabled with require_pvtid
				for admin to manage listening only participants. default=false)
	require_e2ee = true|false (whether all participants are required to publish and subscribe
				using end-to-end media encryption, e.g., via Insertable Streams; default=false)
}

二、协议格式

视频房间接口部分支持同步请求,部分支持异步请求。无效的json格式和无效的请求会同步返回错误。
同步请求的方法有:create 、 destroy 、 edit 、exists、 list、 allowed、 kick 、moderate、 enable_recording 、listparticipants、 listforwarders。这些方法会同步返回结果。
异步请求的方法有:join、 joinandconfigure、configure、publish、unpublish、start 、pause 、switch 、leave。这些方法会通过一个事件返回成功或者失败。

1、同步请求

1.1、创建新房间
通常情况,所有用户都可以创建房间,如果想对此做限制,可以在插件设置中配置"admin_key"属性,配置后,只有请求中携带正确的"admin_key"值,才能创建成功。

请求:

{
	"request" : "create",
	"room" : <unique numeric ID, optional, chosen by plugin if missing>,
	"permanent" : <true|false, whether the room should be saved in the config file, default=false>,
	"description" : "<pretty name of the room, optional>",
	"secret" : "<password required to edit/destroy the room, optional>",
	"pin" : "<password required to join the room, optional>",
	"is_private" : <true|false, whether the room should appear in a list request>,
	"allowed" : [ array of string tokens users can use to join this room, optional],
	...
}

响应:
成功

{
	"videoroom" : "created",
	"room" : <unique numeric ID>,
	"permanent" : <true if saved to config file, false if not>
}

失败

{
	"videoroom" : "event",
	"error_code" : <numeric ID, check Macros below>,
	"error" : "<error description as a string>"
}

1.2、编辑房间
房间创建后,属性"description", “secret”, “pin” 和"private"可支持编辑。

请求:

{
	"request" : "edit",
	"room" : <unique numeric ID of the room to edit>,
	"secret" : "<room secret, mandatory if configured>",
	"new_description" : "<new pretty name of the room, optional>",
	"new_secret" : "<new password required to edit/destroy the room, optional>",
	"new_pin" : "<new password required to join the room, optional>",
	"new_is_private" : <true|false, whether the room should appear in a list request>,
	"new_require_pvtid" : <true|false, whether the room should require private_id from subscribers>,
	"new_bitrate" : <new bitrate cap to force on all publishers (except those with custom overrides)>,
	"new_fir_freq" : <new period for regular PLI keyframe requests to publishers>,
	"new_publishers" : <new cap on the number of concurrent active WebRTC publishers>,
	"new_lock_record" : <true|false, whether recording state can only be changed when providing the room secret>,
	"permanent" : <true|false, whether the room should be also removed from the config file, default=false>
}

响应:

{
	"videoroom" : "edited",
	"room" : <unique numeric ID>
}

1.3、房间销毁

请求:

{
	"request" : "destroy",
	"room" : <unique numeric ID of the room to destroy>,
	"secret" : "<room secret, mandatory if configured>",
	"permanent" : <true|false, whether the room should be also removed from the config file, default=false>
}

响应:

{
	"videoroom" : "destroyed",
	"room" : <unique numeric ID>
}

通知其他参与者:

{
	"videoroom" : "destroyed",
	"room" : <unique numeric ID of the destroyed room>
}

1.4、检测房间是否存在

请求:

{
	"request" : "exists",
	"room" : <unique numeric ID of the room to check>
}

响应:

{
	"videoroom" : "success",
	"room" : <unique numeric ID>,
	"exists" : <true|false>
}

1.5、允许进入房间
配置是否检测令牌,或者添加删除令牌

请求:

{
	"request" : "allowed",
	"secret" : "<room secret, mandatory if configured>",
	"action" : "enable|disable|add|remove",
	"room" : <unique numeric ID of the room to update>,
	"allowed" : [
		// Array of strings (tokens users might pass in "join", only for add|remove)
	]
}

响应:

{
	"videoroom" : "success",
	"room" : <unique numeric ID>,
	"allowed" : [
		// Updated, complete, list of allowed tokens (only for enable|add|remove)
	]
}

1.6、请离房间
房间管理员可以使用踢人功能,但是只能使用户离开房间,不能阻止用户再次进去房间,若想禁止再次进入,需先使用allowed请求移除该用户,再请离该用户。

请求:

{
	"request" : "kick",
	"secret" : "<room secret, mandatory if configured>",
	"room" : <unique numeric ID of the room>,
	"id" : <unique numeric ID of the participant to kick>
}

响应:

{
	"videoroom" : "success",
}

1.7、主持
管理员可以强制静默其他用户(视频流,音频流或者数据流)。

请求:

{
	"request" : "moderate",
	"secret" : "<room secret, mandatory if configured>",
	"room" : <unique numeric ID of the room>,
	"id" : <unique numeric ID of the participant to moderate>,
	"mid" : <mid of the m-line to refer to for this moderate request>,
	"mute" : <true|false, depending on whether the media addressed by the above mid should be muted by the moderator>
}

响应:

{
	"videoroom" : "success",
}

1.8、列举所有房间
若设置可选属性admin_key,私有属性房间也会在列表中返回。

请求:

{
	"request" : "list"
}

响应:

{
	"videoroom" : "success",
	"list" : [		// Array of room objects
		{	// Room #1
			"room" : <unique numeric ID>,
			"description" : "<Name of the room>",
			"pin_required" : <true|false, whether a PIN is required to join this room>,
			"is_private" : <true|false, whether this room is 'private' (as in hidden) or not>,
			"max_publishers" : <how many publishers can actually publish via WebRTC at the same time>,
			"bitrate" : <bitrate cap that should be forced (via REMB) on all publishers by default>,
			"bitrate_cap" : <true|false, whether the above cap should act as a limit to dynamic bitrate changes by publishers (optional)>,
			"fir_freq" : <how often a keyframe request is sent via PLI/FIR to active publishers>,
			"require_pvtid": <true|false, whether subscriptions in this room require a private_id>,
			"require_e2ee": <true|false, whether end-to-end encrypted publishers are required>,
			"notify_joining": <true|false, whether an event is sent to notify all participants if a new participant joins the room>,
			"audiocodec" : "<comma separated list of allowed audio codecs>",
			"videocodec" : "<comma separated list of allowed video codecs>",
			"opus_fec": <true|false, whether inband FEC must be negotiated (note: only available for Opus) (optional)>,
			"video_svc": <true|false, whether SVC must be done for video (note: only available for VP9 right now) (optional)>,
			"record" : <true|false, whether the room is being recorded>,
			"rec_dir" : "<if recording, the path where the .mjr files are being saved>",
			"lock_record" : <true|false, whether the room recording state can only be changed providing the secret>,
			"num_participants" : <count of the participants (publishers, active or not; not subscribers)>
			"audiolevel_ext": <true|false, whether the ssrc-audio-level extension must be negotiated or not for new publishers>,
			"audiolevel_event": <true|false, whether to emit event to other users about audiolevel>,
			"audio_active_packets": <amount of packets with audio level for checkup (optional, only if audiolevel_event is true)>,
			"audio_level_average": <average audio level (optional, only if audiolevel_event is true)>,
			"videoorient_ext": <true|false, whether the video-orientation extension must be negotiated or not for new publishers>,
			"playoutdelay_ext": <true|false, whether the playout-delay extension must be negotiated or not for new publishers>,
			"transport_wide_cc_ext": <true|false, whether the transport wide cc extension must be negotiated or not for new publishers>
		},
		// Other rooms
	]
}

1.9、列举某个房间所有用户

请求:

{
	"request" : "listparticipants",
	"room" : <unique numeric ID of the room>
}

响应:

{
	"videoroom" : "participants",
	"room" : <unique numeric ID of the room>,
	"participants" : [		// Array of participant objects
		{	// Participant #1
			"id" : <unique numeric ID of the participant>,
			"display" : "<display name of the participant, if any; optional>",
			"publisher" : "<true|false, whether user is an active publisher in the room>",
			"talking" : <true|false, whether user is talking or not (only if audio levels are used)>
		},
		// Other participants
	]
}

2、异步请求

会议发布者在视频房间中提供流媒体,订阅者可以订阅发布者提供的流媒体。
由于会议发布者和会议订阅者建立PeerConnection的方式不通,故两者接口分开描述。

2.1 发布者

2.1.1 进入房间
发布者进入房间,应设置"ptype"属性为"publisher"。

请求:

{
	"request" : "join",
	"ptype" : "publisher",
	"room" : <unique ID of the room to join>,
	"id" : <unique ID to register for the publisher; optional, will be chosen by the plugin if missing>,
	"display" : "<display name for the publisher; optional>",
	"token" : "<invitation token, in case the room has an ACL; optional>"
}

响应:
加入成功会返回joined事件,事件中包含当前的publisher角色用户,如果房间的"notify_joining"属性为true,也会返回被动参与者。

{
	"videoroom" : "joined",
	"room" : <room ID>,
	"description" : <description of the room, if available>,
	"id" : <unique ID of the participant>,
	"private_id" : <a different unique ID associated to the participant; meant to be private>,
	"publishers" : [
		{
			"id" : <unique ID of active publisher #1>,
			"display" : "<display name of active publisher #1, if any>",
			"streams" : [
				{
					"type" : "<type of published stream #1 (audio|video|data)">,
					"mindex" : "<unique mindex of published stream #1>",
					"mid" : "<unique mid of of published stream #1>",
					"disabled" : <if true, it means this stream is currently inactive/disabled (and so codec, description, etc. will be missing)>,
					"codec" : "<codec used for published stream #1>",
					"description" : "<text description of published stream #1, if any>",
					"moderated" : <true if this stream audio has been moderated for this participant>,
					"simulcast" : "<true if published stream #1 uses simulcast (VP8 and H.264 only)>",
					"svc" : "<true if published stream #1 uses SVC (VP9 only)>",
					"talking" : <true|false, whether the publisher stream has audio activity or not (only if audio levels are used)>,
				},
				// Other streams, if any
			],
			"talking" : <true|false, whether the publisher is talking or not (only if audio levels are used); deprecated, use the stream specific ones>,
		},
		// Other active publishers
	],
	"attendees" : [		// Only present when notify_joining is set to TRUE for rooms
		{
			"id" : <unique ID of attendee #1>,
			"display" : "<display name of attendee #1, if any>"
		},
		// Other attendees
	]
}

如果仅仅调用了join接口,用户还不是活跃的发布者(尚未建立PeerConnection链接),也不会通知其他的参与者。当房间的notify_joining值为false时,仅仅活跃的发布者用户会通知其他参与者,其他参与者便可以订阅。当notify_joining值为true时,所有的join和leave都会通知,当房间人数很多时,通知就会非常频繁,正在join的状态也会通知。

{
	"videoroom" : "event",
	"room" : <room ID>,
	"joining" : {
		"id" : <unique ID of the new participant>,
		"display" : "<display name of the new participant, if any>"
	}
}

2.1.2 发布
调用publish请求,可以在房间里发布自己的媒体流。请求必须携带一个sdp offer来协商一个新的PeerConnection,插件会返回一个sdp answer来完成PeerConnection的建立,一旦建立成功,就会成为活跃的发布者,此时,其他用户可以订阅。

请求:

{
	"request" : "publish",
	"audiocodec" : "<audio codec to prefer among the negotiated ones; optional>",
	"videocodec" : "<video codec to prefer among the negotiated ones; optional>",
	"bitrate" : <bitrate cap to return via REMB; optional, overrides the global room value if present>,
	"record" : <true|false, whether this publisher should be recorded or not; optional>,
	"filename" : "<if recording, the base path/file to use for the recording files; optional>",
	"display" : "<new display name to use in the room; optional>",
	"audio_level_average" : "<if provided, overrided the room audio_level_average for this user; optional>",
	"audio_active_packets" : "<if provided, overrided the room audio_active_packets for this user; optional>",
	"display" : "<new display name to use in the room; optional>",
	"descriptions" : [	// Optional
		{
			"mid" : "<unique mid of a stream being published>",
			"description" : "<text description of the stream (e.g., My front webcam)>"
		},
		// Other descriptions, if any
	]}

响应:

{
	"videoroom" : "event",
	"configured" : "ok"
}

configure请求可以替代publish来实现发布功能,并且可以更新发布会话的一些属性,而publish仅能作为发布功能使用,并且发布后,再次调用会返回失败。
当PeerConnection建立成功,用户会变为活跃发布者,通知房间内的其他用户。

{
	"videoroom" : "event",
	"room" : <room ID>,
	"publishers" : [
		{
			"id" : <unique ID of the new publisher>,
			"display" : "<display name of the new publisher, if any>",
			"streams" : [
				{
					"type" : "<type of published stream #1 (audio|video|data)">,
					"mindex" : "<unique mindex of published stream #1>",
					"mid" : "<unique mid of of published stream #1>",
					"disabled" : <if true, it means this stream is currently inactive/disabled (and so codec, description, etc. will be missing)>,
					"codec" : "<codec used for published stream #1>",
					"description" : "<text description of published stream #1, if any>",
					"moderated" : <true if this stream audio has been moderated for this participant>,
					"simulcast" : "<true if published stream #1 uses simulcast (VP8 and H.264 only)>",
					"svc" : "<true if published stream #1 uses SVC (VP9 only)>",
					"talking" : <true|false, whether the publisher stream has audio activity or not (only if audio levels are used)>,
				},
				// Other streams, if any
			],
			"talking" : <true|false, whether the publisher is talking or not (only if audio levels are used); deprecated, use the stream specific ones>,
		}
	]
}

2.1.3 停止发布
unpublish请求可以停止发布并且断开PeerConnection链接。
请求:

{
	"request" : "unpublish"
}

响应
插件断开PeerConnection链接,并且将用户从活跃发布者中移除。

{
	"videoroom" : "event",
	"unpublished" : "ok"
}

通知其他用户,该媒体流失效。该事件在发布者的流失效时也会通知,而不仅仅是显示调用unpublish时。

{
	"videoroom" : "event",
	"room" : <room ID>,
	"unpublished" : <unique ID of the publisher who unpublished>
}

2.1.4 配置
如前所诉,configure可以更新一个活跃发布会话的某些属性。
请求:

{
	"request" : "configure",
	"bitrate" : <bitrate cap to return via REMB; optional, overrides the global room value if present (unless bitrate_cap is set)>,
	"keyframe" : <true|false, whether we should send this publisher a keyframe request>,
	"record" : <true|false, whether this publisher should be recorded or not; optional>,
	"filename" : "<if recording, the base path/file to use for the recording files; optional>",
	"display" : "<new display name to use in the room; optional>",
	"audio_active_packets" : "<new audio_active_packets to overwrite in the room one; optional>",
	"audio_level_average" : "<new audio_level_average to overwrite the room one; optional>",
	"mid" : <mid of the m-line to refer to for this configure request; optional>,
	"send" : <true|false, depending on whether the media addressed by the above mid should be relayed or not; optional>,
	"descriptions" : [
		// Updated descriptions for the published streams; see "publish" for syntax; optional
	]
}

响应:

{
	"videoroom" : "event",
	"configured" : "ok"
}

当房间audiolevel_event属性为true时,会通知其他用户ad-hoc事件。

{
	"videoroom" : <"talking"|"stopped-talking", whether the publisher started or stopped talking>,
	"room" : <unique numeric ID of the room the publisher is in>,
	"id" : <unique numeric ID of the publisher>,
	"audio-level-dBov-avg" : <average value of audio level, 127=muted, 0='too loud'>
}

2.1.5 rtp转发
该请求可以转发发布者的媒体流可以被外部使用,而不必是兼容webrtc的组件。对于音频和视频,在streams列表中分别定义负载类型和ssrc。simulcast流也可以每一层分别转发。
请求:

{
	"request" : "rtp_forward",
	"room" : <unique numeric ID of the room the publisher is in>,
	"publisher_id" : <unique numeric ID of the publisher to relay externally>,
	"host" : "<host address to forward the RTP and data packets to>",
	"host_family" : "<ipv4|ipv6, if we need to resolve the host address to an IP; by default, whatever we get>",
	"streams" : [
		{
			"mid" : "<mid of publisher stream to forward>",
			"host" : "<host address to forward the packets to; optional, will use global one if missing>",
			"host_family" : "<optional, will use global one if missing>",
			"port" : <port to forward the packets to>,
			"ssrc" : <SSRC to use to use when forwarding; optional, and only for RTP streams, not data>,
			"pt" : <payload type to use when forwarding; optional, and only for RTP streams, not data>,
			"rtcp_port" : <port to contact to receive RTCP feedback from the recipient; optional, and only for RTP streams, not data>,
			"simulcast" : <true|false, set to true if the source is simulcast and you want the forwarder to act as a regular viewer (single stream being forwarded) or false otherwise (substreams forwarded separately); optional, default=false>,
			"port_2" : <if video and simulcasting, port to forward the packets from the second substream/layer to>,
			"ssrc_2" : <if video and simulcasting, SSRC to use to use the second substream/layer; optional>,
			"pt_2" : <if video and simulcasting, payload type to use the second substream/layer; optional>,
			"port_3" : <if video and simulcasting, port to forward the packets from the third substream/layer to>,
			"ssrc_3" : <if video and simulcasting, SSRC to use to use the third substream/layer; optional>,
			"pt_3" : <if video and simulcasting, payload type to use the third substream/layer; optional>,
		},
		{
			.. other streams, if needed..
		}
	],
	"srtp_suite" : <length of authentication tag (32 or 80); optional>,
	"srtp_crypto" : "<key to use as crypto (base64 encoded key as in SDES); optional>"
}

响应:

{
	"videoroom" : "rtp_forward",
	"room" : <unique numeric ID, same as request>,
	"publisher_id" : <unique numeric ID, same as request>,
	"forwarders" : [
		{
			"stream_id" : <unique numeric ID assigned to this forwarder, if any>,
			"type" : "<audio|video|data>",
			"host" : "<host this forwarder is streaming to, same as request if not resolved>",
			"port" : <port this forwarder is streaming to, same as request if configured>,
			"local_rtcp_port" : <local port this forwarder is using to get RTCP feedback, if any>,
			"remote_rtcp_port" : <remote port this forwarder is getting RTCP feedback from, if any>,
			"ssrc" : <SSRC this forwarder is using, same as request if configured>,
			"pt" : <payload type this forwarder is using, same as request if configured>,
			"substream" : <video substream this video forwarder is relaying, if any>,
			"srtp" : <true|false, whether the RTP stream is encrypted (not used for data)>
		},
		// Other forwarders, if configured
	]
}

2.1.6 停止rtp转发

请求:

{
	"request" : "stop_rtp_forward",
	"room" : <unique numeric ID of the room the publisher is in>,
	"publisher_id" : <unique numeric ID of the publisher to update>,
	"stream_id" : <unique numeric ID of the RTP forwarder>
}

响应:

{
	"videoroom" : "stop_rtp_forward",
	"room" : <unique numeric ID, same as request>,
	"publisher_id" : <unique numeric ID, same as request>,
	"stream_id" : <unique numeric ID, same as request>
}

2.1.7 列举所有rtp转发者

请求:

{
	"request" : "listforwarders",
	"room" : <unique numeric ID of the room>,
	"secret" : "<room secret; mandatory if configured>"
}

响应:

{
	"videoroom" : "forwarders",
	"room" : <unique numeric ID of the room>,
	"publishers" : [		// Array of publishers with RTP forwarders
		{	// Publisher #1
			"publisher_id" : <unique numeric ID of publisher #1>,
			"forwarders" : [		// Array of RTP forwarders
				{	// RTP forwarder #1
					"stream_id" : <unique numeric ID assigned to this RTP forwarder, if any>,
					"type" : "<audio|video|data>",
					"host" : "<host this forwarder is streaming to>",
					"port" : <port this forwarder is streaming to>,
					"local_rtcp_port" : <local port this forwarder is using to get RTCP feedback, if any>,
					"remote_rtcp_port" : <remote port this forwarder getting RTCP feedback from, if any>,
					"ssrc" : <SSRC this forwarder is using, if any>,
					"pt" : <payload type this forwarder is using, if any>,
					"substream" : <video substream this video forwarder is relaying, if any>,
					"srtp" : <true|false, whether the RTP stream is encrypted>
				},
				// Other forwarders for this publisher
			],
		},
		// Other publishers
	]
}

2.1.8 录像
会议中所有用户是否自动录像。
configure请求也可以改变用户自己的录像状态,enable_recording无法改变用户的个性配置。当房间lock_record属性为true时,必须提供正确的secret值才能改变录像状态。
请求:

{
	"request" : "enable_recording",
	"room" : <unique numeric ID of the room>,
	"secret" : "<room secret; mandatory if configured>"
	"record" : <true|false, whether participants in this room should be automatically recorded or not>,
}

2.1.9 离开房间
离开房间会默认停止发布

请求:

{
	"request" : "leave"
}

响应:

{
	"videoroom" : "event",
	"leaving" : "ok"
}

其他用户会收到"leaving"事件,如果是活跃发布者,其他用户还会收到"unpublished"事件。

{
	"videoroom" : "event",
	"room" : <room ID>,
	"leaving : <unique ID of the participant who left>
}
2.2 订阅者

在会议中,订阅者从众多发布者接收媒体,不是参与者。典型的应用是,当收到活跃发布者上线通知,订阅者可以创建会话来接收媒体流,当收到活跃发布者离线通知,订阅者应当移除会话,因此,订阅会话不能单独存在。
streams列表每个对象表示一个发布者的流,feed id表示流的拥有者,当只提供feed id时,表示订阅该发布者的所有流,当提供mid时,表示订阅流中的更具体的对象,如音频或者视频。
根据订阅是单流模式还是多流模式,streams列表会有所不同。当你不能或者不想订阅发布者流的所有内容时,单独订阅某个部分的能力就显得很有作用了。

2.2.1 进入房间
作为订阅者,应设置"ptype"属性为"subscriber",并且明确订阅哪个发布者的流。

请求:

{
	"request" : "join",
	"ptype" : "subscriber",
	"room" : <unique ID of the room to subscribe in>,
	"feed" : <unique ID of the publisher to subscribe to; mandatory>,
	"private_id" : <unique ID of the publisher that originated this request; optional, unless mandated by the room configuration>,
	"streams" : [
		{
			"feed" : <unique ID of publisher owning the stream to subscribe to>,
			"mid" : "<unique mid of the publisher stream to subscribe to; optional>"
			// Optionally, simulcast or SVC targets (defaults if missing)
		},
		// Other streams to subscribe to
	]
}

响应:
成功会返回attached事件,并且携带sdp offer。

{
	"videoroom" : "attached",
	"room" : <room ID>,
	"streams" : [
		{
			"mindex" : <unique m-index of this stream>,
			"mid" : "<unique mid of this stream>",
			"type" : "<type of this stream's media (audio|video|data)>",
			"feed_id" : <unique ID of the publisher originating this stream>,
			"feed_mid" : "<unique mid of this publisher's stream>",
			"feed_display" : "<display name of this publisher, if any>",
			"send" : <true|false; whether we configured the stream to relay media>,
			"ready" : <true|false; whether this stream is ready to start sending media (will be false at the beginning)>
		},
		// Other streams in the subscription, if any
	]
}

2.2.2 开始
start请求携带sdp answer来完成PeerConnection的建立。

请求:

{
	"request" : "start"
}

响应:

{
	"videoroom" : "event",
	"started" : "ok"
}

之后,便是等待WebRTC PeerConnection的建立完成,建立成功后,插件就会转发流到订阅者。

2.2.3 订阅
WebRTC PeerConnection建立成功后,如果想更新订阅,可以使用subscribe和unsubscribe方法。
subscribe可以订阅更多的流,unsubscribe可以删除已经订阅的流,两个请求都会触发重新协商操作,插件会返回sdp offer,订阅者需调用"start"方法返回sdp answer。当插件正在处理同个订阅者的上一次更新时,重新协商操作会延迟触发。
如果streams中所示的流已经订阅,那么将以一个不同的m-line再次订阅,因此需要避免重复订阅。
请求:

{
	"request" : "subscribe",
	"streams" : [
		{
			"feed" : <unique ID of publisher owning the new stream to subscribe to>,
			"mid" : "<unique mid of the publisher stream to subscribe to; optional>"
			// Optionally, simulcast or SVC targets (defaults if missing)
		},
		// Other new streams to subscribe to
	]
}

响应:
如果更新成功,将会收到"updated"事件,携带一个sdp offer,用户需调用"start"返回一个sdp answer来完成重新协商。如果"subscribe"请求没有更改任务东西,将会收到一个不带"streams"对象的"updated"事件。

{
	"videoroom" : "updated",
	"room" : <room ID>,
	"streams": [
		{
			"mindex" : <unique m-index of this stream>,
			"mid" : "<unique mid of this stream>",
			"type" : "<type of this stream's media (audio|video|data)>",
			"feed_id" : <unique ID of the publisher originating this stream>,
			"feed_mid" : "<unique mid of this publisher's stream>",
			"feed_display" : "<display name of this publisher, if any>",
			"send" : <true|false; whether we configured the stream to relay media>,
			"ready" : <true|false; whether this stream is ready to start sending media (will be false at the beginning)>
		},
		// Other streams in the subscription, if any; old and new
	]
}

2.2.4 取消订阅

请求:
取消订阅有多重方式,如果仅指定feed id,将会移除所有从该发布者接收的流,如果指定feed id和mid,将会移除其中的某个具体流(音频或者视频)。

{
	"request" : "unsubscribe",
	"streams" : [
		{
			"feed" : <unique ID of publisher owning the new stream to unsubscribe from; optional>,
			"mid" : "<unique mid of the publisher stream to unsubscribe from; optional>"
			"sub_mid" : "<unique mid of the subscriber stream to unsubscribe; optional>"
		},
		// Other streams to unsubscribe from
	]
}

响应:
取消订阅成功也会返回"updated"事件,订阅者需要调用"start"方法,返回sdp answer。如果取消订阅没有引起更改,将会收到一个不带"streams"对象的"updated"事件。

注意:如果是想触发ice重新协商,而不是更新订阅,应该使用"configure"方法。

作为订阅者,可以暂时的暂时和恢复媒体流的传输。

2.2.5 暂停

请求:

{
	"request" : "pause"
}

响应:

{
	"videoroom" : "event",
	"paused" : "ok"
}

2.2.6 恢复
此时,"start"可以不携带sdp answer。

请求:

{
	"request" : "start"
}

响应:

{
	"videoroom" : "event",
	"started" : "ok"
}

2.2.7 配置
"configure"方法允许订阅者动态地改变某些订阅属性。"mid"和"send"属性可以暂停和恢复某个mid的流内容,而"pause"和"start"方法会暂停和恢复某路流的所有内容,当支持"simulcast"时, "substream"和"temporal"属性可以控制某一时层的流,当支持"VP9-SVC"时,"spatial_layer"和"temporal_layer"可以控制时域和空域层级的流。

{
	"request" : "configure",
	"mid" : <mid of the m-line to refer to for this configure request; optional>,
	"send" : <true|false, depending on whether the mindex media should be relayed or not; optional>,
	"substream" : <substream to receive (0-2), in case simulcasting is enabled; optional>,
	"temporal" : <temporal layers to receive (0-2), in case simulcasting is enabled; optional>,
	"fallback" : <How much time (in us, default 250000) without receiving packets will make us drop to the substream below>,
	"spatial_layer" : <spatial layer to receive (0-2), in case VP9-SVC is enabled; optional>,
	"temporal_layer" : <temporal layers to receive (0-2), in case VP9-SVC is enabled; optional>,
	"audio_level_average" : "<if provided, overrides the room audio_level_average for this user; optional>",
	"audio_active_packets" : "<if provided, overrides the room audio_active_packets for this user; optional>",
	"restart" : <trigger an ICE restart; optional>
}

2.2.8 切换
当订阅一个或者多个发布者时,可以随时切换订阅流关联的发布者,而不用取消订阅,然后重新订阅,也不用做任何的重新协商,仅仅是逻辑上的一些改变。就像电视切换频道一样,订阅者使用同一个PeerConnection,插件切换媒体源。但是,这种方式也有一些限制,两个源之间必须要有相同的媒体配置,比如编码格式。因为PeerConnection是同一个,不会发生重新协商,如果媒体不兼容的话,将不会播放音视频,这种情况,应当使用重新订阅。

请求:

{
	"request" : "switch",
	"streams" : [
		{
			"feed" : <unique ID of the publisher the new source is from>,
			"mid" : "<unique mid of the source we want to switch to>",
			"sub_mid" : "<unique mid of the stream we want to pipe the new source to>"
		},
		{
			// Other updates, if any
		}
	]
}

响应:
成功将会返回事件,订阅新的发布者,并且没有任何的重新协商(没有sdp交换)。

{
	"videoroom" : "event",
	"switched" : "ok",
	"room" : <room ID>,
	"changes" : <number of successful changes (may be smaller than the size of the streams array provided in the request)>,
	"streams" : [
		// Current configuration of the subscription, same format as when subscribing
		// Will contain info on all streams, not only those that have been updated
	]
}

2.2.9 离开
关闭订阅,解除与发布者的关联。

请求:

{
	"request" : "leave"
}

响应:
返回事件并断开PeerConnection。

{
	"videoroom" : "event",
	"left" : "ok",
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值