Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

Пример клиента на Android для участника многоточечной конференции

Данный пример может использоваться для организации многоточечной видео конференции (MCU) на Web Call Server. Каждый участник такой конференции может публиковать WebRTC-поток и воспроизводить микшированный поток с аудио и видео других участников и собственным видео (без собственного аудио).

Для работы примера требуются следующие настройки в конфиге flashphoner.properties WCS-сервера

mixer_auto_start=true
mixer_mcu_audio=true
mixer_mcu_video=true

При подключении нового участника, использующего данный клиент, к конференции

  • публикуется поток с видео участника и именем <participantName> + "#" + <roomName>
  • этот поток добавляется к микшеру с именем <roomName> (если такой микшер еще не существует, то он создается)
  • публикуется другой микшер с именем <roomName> + "-" + <participantName> + <roomName>, который содержит видео всех участников (включая данного) и аудио только от других участников, и начинается воспроизведение этого микшера

На скриншоте ниже участник конференции публикует поток и воспроизводит микшированный поток конференции:

Поля ввода

  • 'WCS URL', где test.flashphoner.com - адрес WCS-сервера
  • 'Login' - имя пользователя
  • 'Room' - имя комнаты
  • 'Transport' - выбор WebRTC транспорта
  • 'Send Audio' - переключатель, разрешающий/запрещающий публикацию аудио
  • 'Send Video' - переключатель, разрешающий/запрещающий публикацию видео


Работа с кодом примера

Для разбора кода возьмем класс McuClientActivity.java примера mcu-client, который доступен для скачивания в соответствующей сборке 1.1.0.24.

1. Инициализация API.

Flashphoner.init() code

Flashphoner.init(this);

При инициализации методу init() передается объект Сontext.

2. Создание сессии

Flashphoner.createSession() code

Методу передается объект SessionOptions со следующими параметрами

  • URL WCS-сервера
  • SurfaceViewRenderer remoteRenderer, который будет использоваться для отображения воспроизводимого потока
sessionOptions = new SessionOptions(mWcsUrlView.getText().toString());
sessionOptions.setRemoteRenderer(remoteRender);

/**
  * Session for connection to WCS server is created with method createSession().
  */
session = Flashphoner.createSession(sessionOptions);

3. Подключение к серверу.

Session.connect(). code

session.connect(new Connection());

4. Получение от сервера события, подтверждающего успешное соединение.

session.onConnected() code

@Override
public void onConnected(final Connection connection) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mStatusView.setText(connection.getStatus());
            ...
        }
    });
});

5. Создание потока

Session.createStream() code

                                    StreamOptions streamOptions = new StreamOptions(publishStreamName);
                                    Constraints constraints = getConstraints();
                                    streamOptions.setConstraints(constraints);
                                    streamOptions.setTransport(Transport.valueOf(mTransportOutput.getSpinner().getSelectedItem().toString()));

                                    /**
                                     * Stream is created with method Session.createStream().
                                     */
                                    publishStream = session.createStream(streamOptions);

6. Запрос прав на публикацию потока

ActivityCompat.requestPermissions() code

@Override
public void onConnected(final Connection connection) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ...
            ActivityCompat.requestPermissions(StreamingMinActivity.this,
                  new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA},
                  PUBLISH_REQUEST_CODE);
            ...
        }
        ...
    });
});

7. Публикация потока после предоставления соответствующих прав

Stream.publish() code

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[], @NonNull int[] grantResults) {
        switch (requestCode) {
            case PUBLISH_REQUEST_CODE: {
                if (grantResults.length == 0 ||
                        grantResults[0] != PackageManager.PERMISSION_GRANTED ||
                        grantResults[1] != PackageManager.PERMISSION_GRANTED) {
                    muteButton();
                    session.disconnect();
                    Log.i(TAG, "Permission has been denied by user");
                } else {
                    /**
                     * Method Stream.publish() is called to publish stream.
                     */
                    publishStream.publish();
                    Log.i(TAG, "Permission has been granted by user");
                }
                break;
            }
            ...
       }
   }

8. Воспроизведение потока микшера после успешной публикации

Session.createStream(), Stream.play() code

                                    publishStream.on(new StreamStatusEvent() {
                                        @Override
                                        public void onStreamStatus(final Stream stream, final StreamStatus streamStatus) {
                                            runOnUiThread(new Runnable() {
                                                @Override
                                                public void run() {
                                                    if (StreamStatus.PUBLISHING.equals(streamStatus)) {
                                                        /**
                                                         * The options for the stream to play are set.
                                                         * The stream name is passed when StreamOptions object is created.
                                                         */
                                                        String playStreamName = roomName + "-" + login + roomName;
                                                        StreamOptions streamOptions = new StreamOptions(playStreamName);
                                                        streamOptions.setTransport(Transport.valueOf(mTransportOutput.getSpinner().getSelectedItem().toString()));
                                                        playStream = session.createStream(streamOptions);
                                                        ...
                                                        /**
                                                         * Method Stream.play() is called to start playback of the stream.
                                                         */
                                                        playStream.play();
                                                    } else {
                                                        Log.e(TAG, "Can not publish stream " + stream.getName() + " " + streamStatus);
                                                    }
                                                    mStatusView.setText(streamStatus.toString());
                                                }
                                            });
                                        }
                                    });

9. Закрытие соединения.

Session.disconnect() code

        mStartButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                muteButton();
                if (mStartButton.getTag() == null || Integer.valueOf(R.string.action_start).equals(mStartButton.getTag())) {
                    ...
                } else {
                    /**
                     * Connection to WCS server is closed with method Session.disconnect().
                     */
                    session.disconnect();
                }
                ...
            }
        });

10. Получение события, подтверждающего разъединение.

session.onDisconnection() code

                        @Override
                        public void onDisconnection(final Connection connection) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mStatusView.setText(connection.getStatus());
                                    mStatusView.setText(connection.getStatus());
                                    onStopped();
                                }
                            });
                        }

11. Настройки публикации/проигрывания аудио и видео

code

    @NonNull
    private Constraints getConstraints() {
        AudioConstraints audioConstraints = null;
        if (mSendAudio.isChecked()) {
            audioConstraints = new AudioConstraints();
        }
        VideoConstraints videoConstraints = null;
        if (mSendVideo.isChecked()) {
            videoConstraints = new VideoConstraints();
        }
        return new Constraints(audioConstraints, videoConstraints);
    }



  • No labels