概述

天气燥热,不易出门。遂研究一下owt-server,从owt-client-javascript的流程开始吧。

获取一个会议室

owt-client-javascript的时候有一个初始化房间的过程

///owt-client-javascript/src/samples/conference/samplertcservice.js
(function initSampleRoom () {
    
    icsREST.API.getRooms(pageOption, function(rooms){
        ...
        // 获取房间信息,如果有房间,直接跳出,如果没有房间则创建一个房间
        if (sampleRoom !== undefined) {
                break;
        }
    }
    // 创建房间的方法
    var tryCreate = function(room, callback) {...}

    if (!sampleRoom) {
        room = {
        name: 'sampleRoom'
      };
        //创建房间
      tryCreate(room, function(Id) {
        sampleRoom = Id;
        console.log('sampleRoom Id:', sampleRoom);
      });
    }
})

获取token

从owt-client-javascript的rest-sample.js开始发送获取token请求。

///owt-client-javascript/src/samples/conference/public/scripts/rest-sample.js
var createToken = function (room, user, role, callback, host) {
  ...
  send('POST', '/tokens/', body, callback, host);
};

请求到本地服务

///owt-client-javascript/src/samples/conference/samplertcservice.js
app.post('/tokens', function(req, res) {
    ...
    icsREST.API.createToken(room, user, role, preference, ...});
}

本地服务开始请求到owt-server的接口创建token,并且返回token

///owt-server/source/management_api/resource/v1/index.js
router.post('/rooms/:room/tokens', tokensResource.create);

加入会议并且获取房间中的流

加入会议:

///owt-client-javascript/src/samples/conference/public/scripts/index.js
conference.join(token).then(resp => {}

通过返回的token解析出host, 连接上房间,并且把房间中的流信息加入到map里

///owt-client-javascript/src/samples/conference/public/scripts/index.js
signaling.connect(host, isSecured, loginInfo).then((resp) => {
        //修改连接状态
        signalingState = SignalingState.CONNECTED;   
        room = resp.room;
        if (room.streams !== undefined) {
          for (const st of room.streams) {
            //判断流的状态
            if (st.type === 'mixed') {      
              st.viewport = st.info.label;
            }
            //把房间的流信息加入到列表里
            remoteStreams.set(st.id, createRemoteStream(st));
          }
        }
       ...
}

设置好房间的流后,开始获取本地流并且开始推流。

///owt-client-javascript/src/samples/conference/public/scripts/index.js
                    ...
let mediaStream;
Owt.Base.MediaStreamFactory.createMediaStream(new Owt.Base.StreamConstraints(
    audioConstraints, videoConstraints)).then(stream => {
    let publishOption;
    if (simulcast) {
        publishOption = {video:[
            {rid: 'q', active: true/*, scaleResolutionDownBy: 4.0*/},
            {rid: 'h', active: true/*, scaleResolutionDownBy: 2.0*/},
            {rid: 'f', active: true}
        ]};
    }
// 获取本地流
    mediaStream = stream;
    localStream = new Owt.Base.LocalStream(
        mediaStream, new Owt.Base.StreamSourceInfo(
            'mic', 'camera'));
    $('.local video').get(0).srcObject = stream;
// 推流
    conference.publish(localStream, publishOption).then(publication => {
        publicationGlobal = publication;
        mixStream(myRoom, publication.id, 'common')
        publication.addEventListener('error', (err) => {
            console.log('Publication error: ' + err.error.message);
        });
    });
}, err => {
    console.error('Failed to create MediaStream, ' +
        err);
});

拉流

开始拉流

///owt-client-javascript/src/samples/conference/public/scripts/index.js
 for (const stream of streams) {
        if(!subscribeForward){
          if (stream.source.audio === 'mixed' || stream.source.video ===
            'mixed') {
            //开始拉流
            subscribeAndRenderVideo(stream);
          }
        } else if (stream.source.audio !== 'mixed') {
            //开始拉流
            subscribeAndRenderVideo(stream);
        }
    }

拉流所在的函数

function subscribeAndRenderVideo(stream){
    let subscirptionLocal=null;
    function subscribeDifferentResolution(stream, resolution){
        subscirptionLocal && subscirptionLocal.stop();
        subscirptionLocal = null;
        const videoOptions = {};
        videoOptions.resolution = resolution;
        conference.subscribe(stream, {
            audio: true,
            video: videoOptions
        }).then((
            subscription) => {
                subscirptionLocal = subscription;
            $(`#${stream.id}`).get(0).srcObject = stream.mediaStream;
        });
    }
    // 创建不同分辨率的按钮和拉对应分辨率的流
    let $p = createResolutionButtons(stream, subscribeDifferentResolution);

    //拉默认流
    conference.subscribe(stream)
    .then((subscription)=>{
        subscirptionLocal = subscription;
        let $video = $(`<video controls autoplay id=${stream.id} style="display:block" >this browser does not supported video tag</video>`);
       $video.get(0).srcObject = stream.mediaStream;
       $p.append($video);
    }, (err)=>{ console.log('subscribe failed', err);
    });

    //流结束的事件
    stream.addEventListener('ended', () => {
        removeUi(stream.id);
        $(`#${stream.id}resolutions`).remove();
    });
    // 更新流的事件
    stream.addEventListener('updated', () => {
        // Update resolution buttons
        $p.children('button').remove();
        createResolutionButtons(stream, subscribeDifferentResolution);
    });
}

至此,owt-server的获取房间,创建token,推本地流和拉会议室的所有流的流程就完成了。

--完--