Protocolo da conferência

Este documento visa descrever as evoluções que iremos efetuar na gestão de conferências (áudio/vídeo). O objetivo é melhorar a implementação atual, que se limita a fundir chamadas SIP e a fornecer uma vista em grelha, para uma vista em que os participantes são listados, podem ser silenciados independentemente ou a disposição do vídeo pode ser alterada (para mostrar apenas um participante)

Definições

  • Hospedeiro: é o utilizador que mistura os fluxos de áudio/vídeo para os outros

  • Participante: Todos os utilizadores da conferência, mesmo o hospedeiro

Isenção de responsabilidade

Para já, este documento descreve apenas os primeiros passos. Isto significa que a identificação dos participantes e a posição no misturador de vídeo é enviada a todos os participantes.

Layouts possíveis

  • Grelha: todos os membros são apresentados com a mesma altura/largura

  • UM_GRANDE_COM_UM_PEQUENO: Um membro é ampliado e a outra pré-visualização é mostrada

  • UM_GRANDE: um membro cobre todo ecrã

Estão disponíveis dois novos métodos para gerir o layout da conferência no CallManager:

/**
 * Change the conference layout
 * @param confId
 * @param layout    0 = matrix, 1 = one big, others in small, 2 = one in big
 */
void setConferenceLayout(const std::string& confId, int layout);

/**
 * Change the active participant (used in layout != matrix)
 * @param confId
 * @param participantId    If participantId not found, the local video will be shown
 */
void setActiveParticipant(const std::string& confId, const std::string& participantId);

Implementação

A implementação é bastante simples. Tudo é gerido por conference.cpp (para ligar os participantes às fontes) e video_mixer.cpp (para renderizar o layout desejado).

Sincronização das informações das conferências

Nota: atualmente, a palavra participante é utilizada para o callID misturado numa conferência. Este facto pode, inicialmente, causar alguns problemas na API e deve ser corrigido no futuro

O objetivo é notificar todos os participantes sobre os metadados do vídeo processado. Isto significa qual o participante que está na conferência e onde se encontra o vídeo.

Se um participante for ele próprio uma conferência, as suas informações de apresentação recebidas devem ser fundidas quando enviadas a outros participantes. As informações de apresentação não devem ser fundidas quando enviadas de volta para uma conferência.

Informações sobre o layout

O layout é armazenado como um VectorMapStringString para clientes e internamente com um vetor com o seguinte formato:

Layout = {
    {
        "uri": "participant", "x":"0", "y":"0", "w": "0", "h": "0", "isModerator": "true"
    },
    {
        "uri": "participant1", "x":"0", "y":"0", "w": "0", "h": "0", "isModerator": "false"
    }
    (...)
}

As chaves possíveis são:

  • uri = uri da conta

  • device = ID (identificação) do dispositivo

  • media = identificação da media

  • active = se o participante estiver ativo

  • x = posição (x) no vídeo

  • y = posição (y) no vídeo

  • w = tamanho (largura) no vídeo

  • h = tamanho (altura) no vídeo

  • videoMuted = se o vídeo está silenciado

  • audioLocalMuted = se o áudio está localmente silenciado

  • audioModeratorMuted = se o áudio é silenciado pelos moderadores

  • isModerator = se é um moderador

  • handRaised = se a mão estiver levantada

  • voiceActivity = se o fluxo tem atividade de voz

  • recording = se o par estiver a gravar a conferência

Nova API

Estão disponíveis um novo método (no CallManager) e um novo sinal para, respetivamente, obter informações e atualizações da conferência atual:

VectorMapStringString getConferenceInfos(const std::string& confId);

void onConferenceInfosUpdated(const std::string& confId, const VectorMapStringString& infos);

Implementação

O objeto Conference (que só existe se misturarmos chamadas, o que significa que somos o mestre) gere a informação de toda a conferência, com base nos LayoutInfos de cada objeto Call. O getConferenceInfos irá obter informações diretamente deste objeto.

Assim, cada objeto Call tem agora um LayoutInfo e, se atualizado, pede ao objeto Conference para atualizar a sua informação.

O mestre de uma conferência envia as suas informações através do canal SIP como uma mensagem com o seguinte tipo MIME: application/confInfo+json

Assim, se uma chamada receber algum confInfo, sabemos que essa chamada é membro de uma conferência.

Resumindo, Call gere os layouts recebidos, Conference gere os layouts enviados.

Alterar o estado da conferência

Para mudar o estado da conferência, os participantes precisam de enviar ordens com as quais o hospedeiro irá lidar.

O protocolo tem as seguintes necessidades:

Deve tratar as ordens a vários níveis. De facto, para uma conferência, existem 3 níveis para definir um participante:

  • A conta que representa a identidade do participante

  • Dispositivos, porque cada conta pode aderir através de vários dispositivos

  • Medias, porque pode haver vários vídeos por dispositivos (por exemplo, 1 câmara e 1 partilha de ecrã)

Para poupar largura de banda, os clientes devem poder enviar várias ordens de uma só vez.

Ações gerais

Para alterar um esquema, o moderador pode enviar uma carga com «application/confOrder+json» como tipo: onde 0 é uma grelha, 1 é um utilizador em grande, outros em pequeno, 2 é um em grande

Ações da conta

Por enquanto, não existe nenhuma ação suportada, no entanto, no futuro moderador: verdadeiro/falso deve ser tratado para alterar um moderador.

Ações do dispositivo

  • hangup: true para desligar um dispositivo da conferência (apenas moderadores)

  • raisehand: true/false para alterar o estado da mão levantada. Só pode ser efetuado pelo próprio dispositivo, caso contrário é eliminado.

Ações da media

  • muteAudio só é possível aos moderadores silenciarem o áudio de um participante

  • muteVideo ainda não suportado.

  • active para marcar o media como ativo.

  • voiceActivity para indicar o estado da atividade vocal de um fluxo de media (apenas relevante para o áudio)

Exemplo

Assim, o application/confOrder+json conterá:

{
    "989587609427420" : {
        "moderator": true/false,
        "devices": {
            "40940943604396R64363": {
                "hangup": true,
                "raisehand": true/false,
                "media":{
                    "3532532662432" : {
                        "muteAudio": true/false,
                        "muteVideo": true/false,
                        "active": true/false,
                        "voiceActivity": true/false
                    }
                }
            }
        }
    },
    "layout": 0/1/2,
}

Nota: o tipo de media deve ser incluído nas informações das conferências e pode ser utilizado pelo cliente para melhorar a visualização (por exemplo, não cortar a partilha de ecrã)

Controlo dos moderadores

Na verdade, existem 3 possibilidades:

  • Alterar a configuração da conta para adicionar uma lista de moderadores (no config.yml (defaultModerators pode conter uma lista de moderadores predefinidos)

  • Se localModeratorsEnabled for true, todas as contas do dispositivo serão moderadoras

  • Se allModeratorsEnabled for true, qualquer pessoa na conferência será um moderador

Futuro

  • Fluxos separados para permitir mais controlos?

Notas / comentários

É provável que o protocolo evolua para necessidades futuras. Penso que é preferível dispormos de um campo «versão». A versão mais antiga será reconhecida se este campo não existir.