Janus流媒体服务器信令分析

Janus流媒体服务器信令分析


目录

  1. 房间配置文件
  2. API分类
  3. Video Room房间管理
  4. VideoRoom Publishers
  5. VideoRoom Subscribers

video room文档:https://janus.conf.meetecho.com/docs/videoroom.html


1. 房间配置文件

room-<unique room ID>: {
		# 房间描述
        description = This is my awesome room
        # 是否是私有房间,当提出“list”请求时,私人房间不会出现
        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>
        # 订阅者是否需要提供⼀个有效的与发布者关联的有效private_id
        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指令
        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")
        # 是否使⽤内置FEC
        opus_fec = true|false (whether inband FEC must be negotiated; only works for Opus, default=false)
        # 是否⽀持编码SVC模式,⽬前只⽀持VP9
        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)
}

2. API分类

  1. Video Room ⽀持不同的请求,⼀部分是同步请求,⼀部分是异步请求。

1. 同步请求

  1. 同步请求:直接在事务( transacation )的上下⽂⾥获取响应,即直接响应( transaction 绑定即可)
    1. create:动态创建⼀个新的房间,作为使⽤配置⽂件的替代⽅法
    2. destroy:移除并销毁房间,同时剔除房间⾥的所有⽤户
    3. edit:动态修改⼀些房间属性
    4. exists:查询是否存在指定的房间
    5. list:列出所有可⽤的房间
    6. allowed:配置观众进⼊房间权限
    7. kick:管理员踢除⽤户操作
    8. listparticipants:列出所有指定房间中活跃(⽐如当前正在发布)的参与者和他们的详细信息

2. 异步请求

  1. 异步请求:在事件( event )通知中获取成功( success )与失败( failure )事件,先发⼀个ask后再发⼀个 event 进⾏响应(必须使⽤ handle_id 绑定)
    1. join:加⼊指定的房间,并指定连接⽤于发布或观看⾳视频
    2. configure:修改⼀些参与者的设置,例如 bitrate cap
    3. joinandconfigure:对于发布者,将前两个请求合成⼀个
    4. publish:开始发送媒体并⼴播给其他参与者
    5. unpublish:停⽌发送媒体并⼴播给其他参与者
    6. start:开始接收来⾃发布者的媒体数据
    7. pause:停⽌传递媒体数据
    8. switch:修改媒体连接的来源
    9. leave:离开房间

3. Video Room房间管理

1. create-创建房间

1. 请求body
{
        "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" : "",
        "secret" : "",
        "pin" : "",
        "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],
        ...
}
  1. 更多房间创建参数可参考房间配置⽂件—— conf/janus.plugin.videoroom.jcfg
  2. 请求都是以"request"为key,接着是命令,⽐如这⾥的"create"。
    1. room:可选,唯⼀的房间ID,不提供时由video room插件⾃动⽣成;
    2. permanent:可选,是否永久保存该房间;
    3. secret: 可选,编辑/销毁房间时⽤的密码;
    4. pin:可选,加⼊房间的密码;
    5. is_private:可选,是否是私有房间?如果是私有房间则不会出现在房间列表中;
    6. allowed:可选,⽤户加⼊房间的token数组;
2. 成功响应-created
{
        "videoroom" : "created",
        "room" : <unique numeric ID>,
        "permanent" : <true if saved to config file, false if not>
}
  1. 创建成功后返回房间ID
  2. 如果你请求了⼀个永久房间但返回的是false,则很有可能是权限的问题。
3. 失败回调 event
{
        "videoroom" : "event",
        "error_code" : <numeric ID, check Macros below>,
        "error" : ""
}
  1. 默认情况下,Janus 中所有⽤户都可以创建房间,但我们可以在插件中配置 admin_key 来限制此功能,只有在 create 携带了正确的 admin_key 才可以创建成功。
  2. 也可以选择将此功能扩展到RTP转发,以便只允许受信任的客户端使⽤此功能。

2. edit-编辑房间

  1. 在房间被创建后,我们可以使⽤ edit 编辑房间的属性(例如 room description 、 secret 、 pin 、private or not ),但不能修改⼀些静态的属性(例如 room ID 、 sampling rate )。
1. 请求body
{
        "request" : "edit",
        "room" : <unique numeric ID of the room to edit>,
        "secret" : "",
        "new_description" : "",
        "new_secret" : "",
        "new_pin" : "",
        "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>
}
  1. 创建房间完成后,ID是不可以修改的。
2. 成功响应-edited
{
        "videoroom" : "edited",
        "room" : <unique numeric ID>
}

3. destroy-销毁房间

  1. ⽆论是静态还是动态的房间,都可以⽤ destroy 进⾏销毁。
1. 请求body
{
        "request" : "destroy",
        "room" : <unique numeric ID of the room to destroy>,
        "secret" : "",
        "permanent" : <true|false, whether the room should be also removed from the config file, default=false>
}
2. 成功响应-destroyed
{
        "videoroom" : "destroyed",
        "room" : <unique numeric ID>
}
3. 房间用户接收的事件-event
  1. 当房间被destroy时,其他所有参与者都会收到这个事件,获知房间被销毁
{
        "videoroom" : "destroyed",
        "room" : <unique numeric ID of the destroyed room>
}

4. exist-房间是否存在

1. 请求body
{
        "request" : "exists",
        "room" : <unique numeric ID of the room to check>
}
2. 成功响应-success
{
        "videoroom" : "success",
        "room" : <unique numeric ID>,
        "exists" : <true|false>
}

5. allowd-出入管理

  1. 可以配置是否检查tokens,或者添加/删除增加/删除允许加⼊房间的⽤户。
1. 请求body
{
        "request" : "allowed",
        "secret" : "",
        "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)
        ]
}
2. 成功响应-success
{
        "videoroom" : "success",
        "room" : <unique numeric ID>,
        "allowed" : [
                // Updated, complete, list of allowed tokens (only for enable|add|remove)
        ]
}

6. kick-踢出房间

  1. 房间的管理员可以通过 kick ⽅法将指定参与者踢出房间。注意,只是能将他踢出房间,并不能阻⽌他再次进⼊。若想阻⽌他再次进⼊,则需要使⽤ allowed 对他进⾏限制
1. 请求body
{
        "request" : "kick",
        "secret" : "",
        "room" : <unique numeric ID of the room>,
        "id" : <unique numeric ID of the participant to kick>
}
2. 成功响应-success
{
        "videoroom" : "success",
}

7. list-房间列表

  1. ⽤于展示公开的所有房间
1. 请求body
{
        "request" : "list"
}
2. 成功响应-success
{
        "videoroom" : "success",
        "list" : [              // Array of room objects
                {       // Room #1
                        "room" : <unique numeric ID>,
                        "description" : "",
                        "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" : "",
                        "videocodec" : "",
                        "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" : "",
                        "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
        ]
}

8. listparticipants列出房间的参与者

  1. 可以使⽤listparticipants列出房间的参与者。
1. 请求body
{
        "request" : "listparticipants",
        "room" : <unique numeric ID of the room>
}
2. 成功响应-participants
{
        "videoroom" : "participants",
        "room" : <unique numeric ID of the room>,
        "participants" : [              // Array of participant objects
                {       // Participant #1
                        "id" : <unique numeric ID of the participant>,
                        "display" : "",
                        "publisher" : "",
                        "talking" : <true|false, whether user is talking or not (only if audio levels are used)>
                },
                // Other participants
        ]
}

4. VideoRoom Publishers

  1. 发布者和订阅者在房间⾥有不同的属性。
  2. 发布者 Publisher
    1. 活跃的发布者 active publisher
    2. 不活跃的发布者 passive publisher
  3. 订阅者 Subscriber
  4. 在Video Room中,发布者(Publisher)是将多媒体数据发布在房间中的参与者,他们可以成为 feeds让其他⽤户进⾏订阅(subscribe)。

1. join-加入房间

  1. 可以通过 join 请求将指定的 handle 指定为 publisher 或 subscriber 。
    1. 指定为 publisher :Janus 会将指定⽤户添加到房间中的参与者列表( the list ofparticipants )中,此后,参与者可以接受到房间中关于 handle 的⼀系列通知(包括流的可⽤与移除)。
    2. 指定为 subscriber :
1. 请求body
{
        "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" : "",
        "token" : ""
}
2. 成功响应-joined
  1. 成功 join ⼊房间后,将会接收到当前房间中活跃的 publishers 的列表。
{
        "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" : "",
                        "streams" : [
                                {
                                        "type" : ">,
                                        "mindex" : "",
                                        "mid" : "",
                                        "disabled" : <if true, it means this stream is currently inactive/disabled (and so codec, description, etc. will be missing)>,
                                        "codec" : "",
                                        "description" : "",
                                        "moderated" : <true if this stream audio has been moderated for this participant>,
                                        "simulcast" : "",
                                        "svc" : "",
                                        "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" : ""
                },
                // Other attendees
        ]
}
  1. 当房间配置了 notify_joining 为 TRUE 时,也会返回不推流的参与者。
  2. private_id :该属性⽤于订阅,便于插件对其进⾏关联。
  3. attendees:当notify_joining=true时返回。
3. 关于不活跃的发布者进出通知
  1. 不活跃的发布者加⼊房间不会通知其他参与者,因为⼀个⼤房间中可能会有很多参与者,如果每⼀个进⼊离开都需要通知所有⼈的话会显得太过于繁琐。如果开发者它进出房间也通知所有⼈,那么需要将房间的notify_joining 配置为 true 。通知的事件如下:
{
        "videoroom" : "event",
        "room" : <room ID>,
        "joining" : {
                "id" : <unique ID of the new participant>,
                "display" : ""
        }
}

2. publish-发布

  1. 发布者带着 Offer 向 Janus 进⾏协商
  2. publish 请求必须携带着 JSEP SDP offer去协商⼀个新的 PeerConnection,即插件会检查编码器和码率是否是房间所⽀持的,之后将会回应⼀个 JSEP SDP answer 来关闭循环并完成配置⼀个PeerConnection。当指定的 PeerConnection 搭建好后,该指定的 publisher 才会变成⼀个活跃的publisher,之后其他参与者才可以订阅它。
1. 请求body
{
        "request" : "publish",
        "audiocodec" : ",
        "videocodec" : ",
        "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" : "",
        "display" : "",
        "audio_level_average" : "",
        "audio_active_packets" : "",
        "display" : "",
        "descriptions" : [      // Optional
                {
                        "mid" : "",
                        "description" : ""
                },
                // Other descriptions, if any
        ]}
  1. audio:是否转发⾳频;
  2. video:是否转发视频;
  3. data:是否转发数据;
  4. 该请求和JSEP SDP offer⼀起提供,插件收到此消息后,将协商与之匹配的 JSEP SDP Answer 。
2. 成功响应-event
{
        "videoroom" : "event",
        "configured" : "ok"
}

3. configure-配置(开始发布)

  1. publish 和 configure 在功能上时相同的,他们都有开始发布的功能。从语义上, publish 更加合适。但是 configure 可以更新发布者会话的某些属性。总的来说 configure 的功能更加强⼤。
1. 请求body
{
        "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" : "",
        "display" : "",
        "audio_active_packets" : "",
        "audio_level_average" : "",
        "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
        ]
}
2. 成功响应-event
{
        "videoroom" : "event",
        "configured" : "ok"
}

4. joinandconfigure-加入并配置(加入并且发布)

1. 请求body
  1. 参考join请求用的body,并携带 JSEP SDP offer
2. 成功响应-joined
  1. 成功响应将是⼀个 joined 事件,并且携带 JSEP SDP answer。

5. 发布成功后推送

  1. 当⼀个⽤户在房间中发布成功后,Janus 将会发送⼀个关于新对端的事件给所有参与者,事件如下:
{
        "videoroom" : "event",
        "room" : <room ID>,
        "publishers" : [
                {
                        "id" : <unique ID of the new publisher>,
                        "display" : "",
                        "streams" : [
                                {
                                        "type" : ">,
                                        "mindex" : "",
                                        "mid" : "",
                                        "disabled" : <if true, it means this stream is currently inactive/disabled (and so codec, description, etc. will be missing)>,
                                        "codec" : "",
                                        "description" : "",
                                        "moderated" : <true if this stream audio has been moderated for this participant>,
                                        "simulcast" : "",
                                        "svc" : "",
                                        "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>,
                }
        ]
}

6. unpublish-停止发布

  1. unpublish 请求⽤于停⽌发布并且销毁相关的 PeerConnection,并且将发布者从活跃流列表中移除。
1. 请求body
{
        "request" : "unpublish"
}
2. 成功响应-event
{
        "videoroom" : "event",
        "unpublished" : "ok"
}
3. 其他成员通知
  1. ⼀旦PeerConnections断开,房间内的其他参与者会通过下⾯这个通知得知此事
{
        "videoroom" : "event",
        "room" : <room ID>,
        "unpublished" : <unique ID of the publisher who unpublished>
}
  1. 可以在同⼀个 handle 中多次发布和取消发布流
  2. configure 基本上与 publish 的属性相同。这就是为什么两个请求都可以⽤来开始发布的原因。如果configure 成功,则返回 configured 事件,格式如下:
{
        "videoroom" : "event",
        "configured" : "ok"
}
  1. 当发送 configure 请求RTP扩展 ssrc-audio-level 时,如果 audiolevel_event 设置为true ,则可能会向所有发布者发送⼀些临时事件。这些事件将具有以下格式:
{
        "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'>
}

7. RTP转发器

  1. VideoRoom 插件的主要⽬的是从WebRTC源(发布者)获取媒体,并将其转发到WebRTC⽬的地(订阅者),但实际上存在⼏种⽅案,可以将媒体转发给外部(不⼀定与WebRTC兼容)组件。例如,⽤于媒体处理,外部录制,转码,级联等等。 rtp_forward 顾名思义,就是将发布者发送的RTP包(普通或加密)实时转发到远程后端。
  2. 可以使⽤ rtp_forward 请求为现有发布者添加新的RTP转发器,其格式如下:
{
        "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_family" : "",
        "streams" : [
                {
                        "mid" : "",
                        "host" : "",
                        "host_family" : "",
                        "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" : ""
}
  1. 如果配置了admin_key属性,则在请求中也需要提供它,否则未授权的请求将被拒绝。默认情况下,没有对rtp_forward进⾏限制。
  2. 如果请求成功则返回 rtp_forward 响应,其中格式如下:
{
        "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" : "",
                        "host" : "",
                        "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
        ]
}
  1. 要停⽌以前创建的RTP转发器,可以使⽤ stop_rtp_forward 请求,其格式如下:
{
        "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>
}
  1. 请求成功,则返回 stop_rtp_forward 响应:
{
        "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>
}
  1. 如果要获取特定房间中所有转发器的列表,可以使⽤ listforwarders 请求,其格式如下:
{
        "request" : "listforwarders",
        "room" : <unique numeric ID of the room>,
        "secret" : ""
}
  1. 请求成功,则返回forwarders响应,其中包括RTP转发器列表:
{
        "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" : "",
                                        "host" : "",
                                        "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
        ]
}
  1. 在会议进⾏期间启⽤或禁⽤录制,您可以使⽤ enable_recording 请求,该请求的格式如下:
{
        "request" : "enable_recording",
        "room" : <unique numeric ID of the room>,
        "secret" : ""
        "record" : <true|false, whether participants in this room should be automatically recorded or not>,
}
  1. 参与者通常也可以通过configure请求来更改⾃⼰的录制状态:这样做是为了获得最⼤的灵活性,可能希望单独记录⼀些流,⽽不是全局或⾃动记录⼀些内容,到特定⽂件。

  2. 就是说,如果希望确保在启⽤全局录制后参与者不能停⽌其录制,或者在不应该录制该会议室的情况下启动它,那么您应该确保在创建会议室时使⽤lock_record属性,将其设置为true。这样,只有在提供了房间密码的情况下,才能更改录制状态,从⽽确保只有管理员才能执⾏此操作。

  3. 最后,您可以使⽤ leave 请求离开会议室。如果您是会议室中的活动发布者,这也将隐式取消你的发布。该leave请求如下所示

{
        "request" : "leave"
}
  1. 如果成功,响应将如下所示:
{
        "videoroom" : "event",
        "leaving" : "ok"
}
  1. 其他参与者将收到”leave”事件,格式如下:
{
        "videoroom" : "event",
        "room" : <room ID>,
        "leaving : <unique ID of the participant who left>
}
  1. 如果是活跃的发布者,则其他⽤户也将收到相应的 unpublish 事件,以通知他们该流不再可⽤。如果只是潜伏⽽不是发布者,则其他参与者将仅收到”leave”事件。

5. VideoRoom Subscribers

  1. 在 VideoRoom 中,订阅者(Subscriber)不是参与者,但是他可以准确接收指定发布者的媒体数据。
  2. 通常发布者发布了媒体后,订阅者可以获取该流进⾏播放。当发布者取消发布后,订阅者 handle 也会随之被移除。除⾮给订阅者正确的信息,不然订阅者是不能单独存在的。

1. join-加入房间

1. 请求body
{
        "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" : ""
                        // Optionally, simulcast or SVC targets (defaults if missing)
                },
                // Other streams to subscribe to
        ]
}
  1. 如果发布者对房间中的媒体进⾏订阅,则需要传⼊ private_id 。
2. 成功响应-attached(Offer)
  1. 订阅者成功加⼊房间并订阅指定 feed 成功后,Janus 会给予⼀个 attached 响应,并且在这个 event中携带 JSEP SDP offer,⽤于进⾏媒体协商。
{
        "videoroom" : "attached",
        "room" : <room ID>,
        "streams" : [
                {
                        "mindex" : <unique m-index of this stream>,
                        "mid" : "",
                        "type" : "",
                        "feed_id" : <unique ID of the publisher originating this stream>,
                        "feed_mid" : "",
                        "feed_display" : "",
                        "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. start-开始订阅(Answer 对 attached 的订阅者响应)

  1. 订阅者接收到含有 attach 的 event 后,获取⾥⾯的 JSEP SDP offer 后,将其设置为远程 SDP 后,然后发送 start 请求并携带 JSEP SDP answer。
1. 请求body
{
        "request" : "start"
}
2. 成功响应-event
{
        "videoroom" : "event",
        "started" : "ok"
}
  1. 当订阅者与Janus媒体协商完毕后,双⽅就会建⽴⼀条新的 WebRTC PeerConnection。在这之后,Streaming插件将会开始将媒体转发到订阅者端。

3. pause-暂停订阅

1. 请求body
  1. 以通过 pause 和 start 请求对订阅媒体进⾏临时的暂停和恢复,此处的 start 不需要携带 JSEP SDP answer
{
        "request" : "pause"
}
2. 成功响应-event
{
        "videoroom" : "event",
        "paused" : "ok"
}
  1. ⽤于恢复的 start 其⽤法和上⾯是⼀致的,注意他不⽤携带 JSEP 即可。

4. configure-配置

  1. configure 请求允许动态修改订阅者对于媒体订阅的⼀些属性,⽐如配置⾳频和视频的启⽤与禁⽤,灵活设置订阅内容。
1. 请求body
{
        "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" : "",
        "audio_active_packets" : "",
        "restart" : <trigger an ICE restart; optional>
}
  1. audio 、 video 和 data :可以在媒体层( media-level )上进⾏暂停与恢复,对⽐ pause 和start 直接作⽤所有⾳视频流⽽⾔,它更加灵活。
  2. substream 和 temporal : The substream and temporal properties, instead, only make sense when the mountpoint is configured with video simulcasting support, and as such the viewer is interested in receiving a specific substream or temporal layer, rather than any other of the available ones.
  3. spatial_layer 和 temporal_layer :The spatial_layer and temporal_layer have exactly the same meaning, but within the context of VP9-SVC publishers, and will have no effect on subscriptions associated to regular publishers.

5. switch-切换

  1. switch 适⽤于已经与 Janus 成功建⽴ PeerConnection 的订阅者,通过这个请求完成订阅的切换,就像看电视切换频道⼀样。这样做的好处就是能复⽤⼀条连接,在切换订阅⽬标的时候不需要重新建⽴连接,消耗不必要的资源。
  2. 但是他也有以下的限制:
    1. 不能只换⾳视频流的其中⼀个,要都换
    2. 两个⽬标发布者必须使⽤⼀样的配置,⽐如⼀样的编码器、⼀样的数据格式(不⼀样的话会导致延迟甚⾄直接⿊屏没声⾳)
1. 请求body
{
        "request" : "switch",
        "streams" : [
                {
                        "feed" : <unique ID of the publisher the new source is from>,
                        "mid" : "",
                        "sub_mid" : ""
                },
                {
                        // Other updates, if any
                }
        ]
}
2. 成功响应-event
{
        "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
        ]
}

6. leave-离开房间

  1. leave 请求⽤于停⽌订阅并销毁相关的 PeerConnection,由于上下⽂是隐式的,所以不需要其他参数
1. 请求body
{
        "request" : "leave"
}
2. 成功响应-event
{
        "videoroom" : "event",
        "left" : "ok",
}

你可能感兴趣的:(WebRTC,服务器,运维)