https://a.storyblok.com/f/270183/44277/0b8c74ced9/blog_online-classroom_laravel_1200x600.png

Criação de uma sala de aula online no Laravel com a Video API da Vonage

Publicado em December 11, 2020

Tempo de leitura: 15 minutos

Este artigo demonstrará como configurar uma sala de aula virtual/de Video em tempo real usando a Video API da Vonage , na qual o professor pode estar em qualquer lugar do mundo e, mesmo assim, se comunicar e ministrar aulas para o aluno em tempo real.

O que é exatamente a Video API da Vonage?

A Video API da Vonage é um serviço que facilita aos desenvolvedores a criação de Applications que utilizam WebRTC e Web Sockets para oferecer comunicação em tempo real por Video, texto, áudio e outros meios para aplicativos da web, aplicativos móveis e até mesmo dispositivos de mesa. Eles fornecem SDKs robustos para diversas plataformas, a fim de implementar e disponibilizar aos usuários a API para uso em seus aplicativos.

Como isso funciona?

Todas as aplicações que utilizam a Video API da Vonage são compostas por três componentes principais, e tudo o que você faz gira em torno deles. São eles:

  1. Sessões

  2. Servidor

  3. Cliente

Vamos examinar cada um deles com um pouco mais de detalhes:

Sessões

Uma sessão pode ser vista como a sala de bate-papo virtual onde as comunicações ocorrem. Para que dois computadores possam trocar Video ou áudio, eles precisam estar conectados à mesma sessão. As sessões são hospedadas/armazenadas na nuvem da API da Vonage e todas possuem um ID exclusivo. As sessões gerenciam os fluxos dos usuários (transmissão de vídeo e áudio) e registram todos os eventos (como quando os usuários entram, saem ou enviam uma mensagem de texto).

Servidor

Os servidores são o código de back-end que você escreve para gerenciar as sessões em seu aplicativo. Para que a comunicação ocorra, seu servidor precisa se comunicar com a nuvem da API da Vonage para criar uma sessão e usar o ID da sessão recebido para gerar tokens que os clientes (navegadores e celulares) possam então utilizar para ingressar na sessão e trocar fluxos. Para que seu servidor funcione, você precisará usar um dos diversos SDKs do lado do servidor da API da Vonage, disponíveis para várias linguagens de programação do lado do servidor.

Cliente

Clientes são os navegadores ou dispositivos móveis com os quais os usuários interagem diretamente para trocar transmissões de Video e áudio. Os clientes sempre precisam de um token (gerado pelo seu servidor) para participar de uma sessão, a fim de que possam interagir com outros clientes na mesma sessão.

Quando um cliente está conectado, ele pode publicar (enviar transmissão de Video/áudio) e se inscrever (receber transmissão de áudio/Video) em outros clientes na mesma sessão. Um cliente pode atuar como emissor, assinante ou moderador.

Os editores têm permissão para enviar e receber transmissões de áudio/Video. Os assinantes não têm permissão para enviar, mas recebem transmissões de áudio/Video. Os moderadores têm permissão para fazer tudo o que os editores podem fazer, além de impedir que outros clientes se inscrevam.

Para recapitular, é isso que acontece para que a comunicação ocorra ao usar a API da Vonage:

Seu servidor cria uma sessão na Vonage API Cloud com um ID exclusivo. Quando um cliente deseja participar, seu servidor usa o ID da sessão para gerar um token para esse cliente. O cliente entra na sessão e publica fluxos nela. Quando outro cliente entra, o servidor gera um novo token, e os dois clientes podem se inscrever para receber os fluxos um do outro na sessão e receber os fluxos um do outro.

Configurando nossa aula online com a API da Vonage

Neste tutorial, vamos configurar uma transmissão de vídeo básica com a API da Vonage para permitir que os clientes enviem áudio e vídeo. A API da Vonage oferece um SDK para PHP, e vamos usá-lo para criar nossa aula virtual.

Configurar um projeto Laravel

O primeiro passo para criar nossa aula virtual é configurar um projeto Laravel.

É importante observar que, no momento da redação deste artigo, a API da Vonage não funciona com a versão mais recente do Laravel* *(8.x). Isso ocorre porque o SDK PHP da API da Vonage depende da versão 6 do GuzzleHTTP, mas o Laravel 8 usa a versão 7 do GuzzleHTTP. Portanto, para este tutorial, instale a versão 7 do Laravel. Você pode fazer isso executando o comando de instalação da seguinte maneira:

composer create-project --prefer-dist laravel/laravel:^7.0 virtual_classroom

Ou você também pode acompanhar o processo clonando o repositório aqui.

Instalando o SDK PHP da API da Vonage

O próximo passo é instalar o SDK PHP da API da Vonage. Para isso, instalamos o pacote no nosso projeto usando o Composer.

composer require opentok/opentok 4.4.x -W

Definindo nossas migrações e modelos

Agora precisamos definir nossos professores e alunos para que eles tenham permissões diferentes em nossa sala de aula virtual. Nosso aplicativo utilizaria duas tabelas — `users`, para armazenar todos os professores e alunos, e `virtual_classes`, para armazenar os IDs das sessões de nossas aulas, de modo que os alunos possam ver a aula em andamento ao fazerem login e participarem dela. Estas são as migrações para ambas as tabelas:

Abra a migração de usuários em database/migrations/xxxxxx_create_users_xxxx.php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */

    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();

            // This enum field tells us if the current user is a teacher or student

            $table->enum('user_type', ['Student', 'Teacher']);
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */

    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Abra a migração `virtual_classes` em database/migrations/xxxxxx_create_virtual_classes_xxxx.php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateVirtualClassesTable extends Migration
{
   /**
     * Run the migrations.
     *
     * @return void
     */

    public function up()
    {
        Schema::create('virtual_classes', function (Blueprint $table) {
            $table->id();
            $table->string("name");

            // User id to know which teacher created the class

            $table->integer("user_id");            `
            $table->string("session_id");
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */

    public function down()
    {
        Schema::dropIfExists('classes');
    }
}

Depois de fazer isso, precisaremos criar uma pasta chamada Models no diretório do aplicativo e mover nossos modelos para lá. Em seguida, atualizaremos o namespace para App\Models em nossos modelos. Por fim, atualizaremos o modelo User para adicionar user_type ao array $fillable e criaremos uma relação com as classes virtuais para que possamos acessá-las facilmente.

Abra o modelo User em app/Models/Users.php

//REMEMBER TO UPDATE THE NAMESPACE AFTER MOVING THE FILE

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */

    // DON'T FORGET TO ADD THE USER_TYPE TO THIS ARRAY

    protected $fillable = [
        'name', 'email', 'password', 'user_type'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */

    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    // Relationship tying a virtual class to a user (teacher in our case)

    public function myClass() {
        return $this->hasOne(VirtualClass::class);
    }
}

Autenticação

Agora que já configuramos a arquitetura do nosso modelo, precisamos permitir que os usuários se cadastrem e façam login. A primeira coisa a fazer é editar os provedores na configuração do nosso projeto. Como alteramos a localização do modelo User, precisamos refletir essa mudança. Primeiro, vamos até o arquivo config/auth.php, editamos a matriz de provedores e executamos os comandos para gerar a estrutura de autenticação.

'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class, // New location of User model
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

// Rest of auth.php file

Depois de fazer isso, basta executar o scaffold padrão de autenticação do Laravel:

composer require laravel/ui:^2.4
php artisan ui vue --auth
npm install
npm run dev

Depois de executar todos os quatro comandos nessa ordem, o Laravel deve adicionar as visualizações necessárias para configurar a autenticação. A etapa final na configuração da nossa autenticação é editar o RegisterController e o arquivo register.blade.php para verificar se um usuário é aluno ou professor no momento do cadastro.

Primeiro, o app/Http/Controllers/Auth/RegisterController arquivo:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;

// PLEASE REMEMBER TO CHANGE THE IMPORT STATEMENT HERE

use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default, this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */

    protected $redirectTo = RouteServiceProvider::HOME;

    /**
     * Create a new controller instance.
     *
     * @return void
     */

    public function __construct()
    {
        $this->middleware('guest');
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param array $data
     * @return \Illuminate\Contracts\Validation\Validator
     */

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],

            // Add the user_type here for validation.
            'user_type' => ['required', 'string', 'in:Student,Teacher'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param array $data
     * @return \App\User
     */

    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'user_type' => $data['user_type'],
            'password' => Hash::make($data['password']),
        ]);
    }
}

Em seguida, a visualização do registro. Ela se encontra em resources/views/auth/register.blade.php:

@extends('layouts.app')
@section('content')

<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Register') }}</div>


                <div class="card-body">
                   <form method="POST" action="{{ route('register') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>


                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>

                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="user_type" class="col-md-4 col-form-label text-md-right">{{ __('User Type') }}</label>

{{--                        Note the select box here???--}}

                            <div class="col-md-6">
                                <select id="user_type" type="text" class="form-control @error('user_type') is-invalid @enderror" name="user_type" required>
                                    <option value="Student">Student</option>
                                    <option value="Teacher">Teacher</option>
                                </select>

                                @error('user_type')

                                <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">

                                @error('password')
                                   <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>

                            <div class="col-md-6">
                                <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Register') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>

@endsection

Feito isso, deveremos conseguir nos cadastrar e fazer login como professor ou aluno.

Configurando nosso servidor

Antes de configurar seu servidor, você precisará de uma chave e um segredo da API do projeto. Para obtê-los, é necessário criar um Account gratuito da API da Vonage. Para isso, clicando neste link. Depois de concluir o processo e criar um projeto, volte aqui e continue :)

Primeiro, vamos armazenar nossa chave de API e nosso segredo de API no arquivo .env do nosso projeto Laravel:

### ADD THESE LINES AT THE BOTTOM OF YOUR .env FILE, OR WHEREVER REALLY ###

VONAGE_API_KEY=your_api_key
VONAGE_API_SECRET=your_api_secret

### REST OF .ENV FILE ###

Agora, precisaremos configurar um controlador para, de fato, estabelecer sessões e gerar tokens para novos usuários. Vamos criar um e chamá-lo de SessionsController:

php artisan make:controller SessionsController

Vamos preenchê-la com os métodos necessários em app/Http/Controllers/SessionsController.php:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\VirtualClass;

#Import necessary classes from the Vonage API (AKA OpenTok)

use OpenTok\OpenTok;
use OpenTok\MediaMode;
use OpenTok\Role;

class SessionsController extends Controller
{
    /** Creates a new virtual class for teachers
     *
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse
     */

    public function createClass(Request $request)
    {
        // Get the currently signed-in user
        $user = $request->user();
        // Throw 403 if student tries to create a class
        if ($user->user_type === "Student") return back(403);
        // Instantiate a new OpenTok object with our api key & secret
        $opentok = new OpenTok(env('VONAGE_API_KEY'), env('VONAGE_API_SECRET'));
        // Creates a new session (Stored in the Vonage API cloud)
        $session = $opentok->createSession(array('mediaMode' => MediaMode::ROUTED));
        // Create a new virtual class that would be stored in db
        $class = new VirtualClass();
        // Generate a name based on the name the teacher entered
        $class->name = $user->name . "'s " . $request->input("name") . " class";
        // Store the unique ID of the session
        $class->session_id = $session->getSessionId();
        // Save this class as a relationship to the teacher
        $user->myClass()->save($class);
        // Send the teacher to the classroom where real-time video goes on
        return redirect()->route('classroom', ['id' => $class->id]);
    }

    public function showClassRoom(Request $request, $id)
    {
        // Get the currently authenticated user
        $user = $request->user();
        // Find the virtual class associated by provided id
        $virtualClass = VirtualClass::findOrFail($id);
        // Gets the session ID
        $sessionId = $virtualClass->session_id;
        // Instantiates new OpenTok object
        $opentok = new OpenTok(env('VONAGE_API_KEY'), env('VONAGE_API_SECRET'));
        // Generates token for client as a publisher that lasts for one week
        $token = $opentok->generateToken($sessionId, ['role' => Role::PUBLISHER, 'expireTime' => time() + (7 * 24 * 60 * 60)]);
        // Open the classroom with all needed info for clients to connect
        return view('classroom', compact('token', 'user', 'sessionId'));
    }
}

Ao criar o token, podemos definir a função que o cliente atual pode desempenhar. Ela pode ser “Editor”, “Assinante” ou “Moderador”. As funções estão explicadas acima. No trecho de código acima, estamos atribuindo a todos os usuários o status de editor, o que significa que todos os usuários podem enviar e receber transmissões (feed de Video e áudio).

Precisaremos criar um classroom.blade.php arquivo na nossa pasta resources/views para o showClassroom método.

Também precisaremos criar rotas para o controlador. Vamos adicionar essas rotas no arquivo routes/web.php:

<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

// Add this to your web.php file

// This line makes all routes in it to use the auth middleware, meaning only signed-in users can access these routes

Route::middleware('auth')->group(function () {

    // This route creates classes for teachers

    Route::post("/create_class", 'SessionsController@createClass')
        ->name('create_class');

    // This route is used by both teachers and students to join a class

    Route::get("/classroom/{id}", 'SessionsController@showClassRoom')
        ->where('id', '[0-9]+')
        ->name('classroom');
});

Por fim, em nosso painel, precisamos oferecer aos professores um recurso para criar turmas e fornecer aos alunos a lista de turmas nas quais podem se inscrever. Para isso, precisaremos atualizar o HomeController e o arquivo home.blade.php. Vamos lá; espero que todos ainda estejam me acompanhando 🙂

Vamos começar pelo arquivo app/Http/Controllers/HomeController:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\ClassModel as VirtualClass;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */

    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */

    public function index(Request $request)
    {
        $user = $request->user();
        $classes = [];

        // If user is a student, give her a list of virtual classes

        if ($user->user_type === "Student") {
            $classes = VirtualClass::orderBy('name', 'asc')->get();
        }

        return view('home', compact('user', 'classes'));
    }
}

Próximo resources/views/home.blade.php:

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">{{$user->user_type}} {{ __('Dashboard') }}</div>

                    <div class="card-body">
                        @if (session('status'))
                            <div class="alert alert-success" role="alert">
                                {{ session('status') }}
                            </div>
                        @endif
                        @if($user->user_type === "Student")
                            <h3>These are the ongoing classes available on the system</h3>
                            @foreach($classes as $key=>$class)
                                <a href="{{route('classroom', ['id' => $class->id])}}">{{$key + 1}}. {{$class->name}}</a>
                                <br />
                            @endforeach
                        @else
                            <h4>Welcome {{$user->name}}. Fill the form below to create a class</h4>
                            <form method="POST" action="{{ route('create_class') }}">
                                @csrf

                                <div class="form-group row">
                                    <label for="name" class="col-md-12 col-form-label">{{ __('Class Name') }}</label>

                                    <div class="col-md-6">
                                        <input id="name" type="text"
                                               class="form-control @error('name') is-invalid @enderror" name="name"
                                               value="{{ old('name') }}" required autocomplete="name" autofocus>

                                        @error('name')
                                        <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                        @enderror

                                    </div>
                                </div>

                                <div class="form-group row mb-0">
                                    <div class="col-md-6">
                                        <button type="submit" class="btn btn-primary">
                                            {{ __('Create Class') }}
                                        </button>
                                    </div>
                                </div>
                            </form>

                        @endif

                    </div>
                </div>
            </div>
        </div>
    </div>

@endsection

Isso exibe um formulário para criar uma turma, caso o usuário seja um professor, ou uma lista de turmas virtuais, caso o usuário seja um aluno.

Configurando nosso cliente e transmitindo ao vivo o feed de Video e áudio

Para configurar o cliente (que utilizaria o SDK da web), precisaremos criar um arquivo Blade chamado resources/views/classroom.blade.php para corresponder ao showClassroom() método em nosso SessionsController. O arquivo precisaria conter um link para o CDN do SDK. Nossa interface deve ficar assim:

    <html>
    <head>
        <title> OpenTok Getting Started </title>
        <style>
          body, html {
              background-color: gray;
              height: 100%;
          }

          #videos {
              position: relative;
              width: 100%;
              height: 100%;
              margin-left: auto;
              margin-right: auto;
          }

          #subscriber {
              position: absolute;
              left: 0;
              top: 0;
              width: 100%;
              height: 100%;
              z-index: 10;
          }

          #publisher {
              position: absolute;
              width: 360px;
              height: 240px;
              bottom: 10px;
              left: 10px;
              z-index: 100;
              border: 3px solid white;
              border-radius: 3px;
          }

        </style>

        <script src="https://static.opentok.com/v2/js/opentok.min.js"></script>

    </head>

    <body>
        <div id="videos">
            <div id="subscriber"></div>
            <div id="publisher"></div>
        </div>

        <script type="text/javascript">
            var session;
            var connectionCount = 0;
            var apiKey = "{{env('VONAGE_API_KEY')}}";
            var sessionId = "{{$sessionId}}";
            var token = "{{$token}}";
            var publisher;

            function connect() {

                // Replace apiKey and sessionId with your own values:

                session = OT.initSession(apiKey, sessionId);
                session.on("streamCreated", function (event) {
                    console.log("New stream in the session: " + event.stream.streamId);
                    session.subscribe(event.stream, 'subscriber', {
                        insertMode: 'append',
                        width: '100%',
                        height: '100%'
                    });
                });

                session.on({
                    connectionCreated: function (event) {
                        connectionCount++;
                        alert(connectionCount + ' connections.');
                    },
                    connectionDestroyed: function (event) {
                        connectionCount--;
                        alert(connectionCount + ' connections.');
                    },
                    sessionDisconnected: function sessionDisconnectHandler(event) {
                        // The event is defined by the SessionDisconnectEvent class
                        alert('Disconnected from the session.');
                        document.getElementById('disconnectBtn').style.display = 'none';
                        if (event.reason == 'networkDisconnected') {
                            alert('Your network connection terminated.')
                        }
                    }
                });

                var publisher = OT.initPublisher('publisher', {
                    insertMode: 'append',
                    width: '100%',
                    height: '100%'
                }, error => {
                    if (error) {
                        alert(error.message);
                    }
                });

                // Replace token with your own value:
                session.connect(token, function (error) {
                    if (error) {
                        alert('Unable to connect: ', error.message);
                    } else {
                        // document.getElementById('disconnectBtn').style.display = 'block';
                        alert('Connected to the session.');
                        connectionCount = 1;

                        if (session.capabilities.publish == 1) {
                            session.publish(publisher);
                        } else {

                            alert("You cannot publish an audio-video stream.");
                        }
                    }
                });
            }
            connect();

        </script>
    </body>
</html>
   

Para testar o aplicativo, execute o seguinte comando no diretório raiz do seu projeto.

php artisan serve

Acesse http://localhost:8000/ no seu navegador e clique no menu de login.

Se tudo for feito corretamente, você deverá fazer login com uma conta de professor e uma conta de aluno e trocar transmissões de áudio e Video.

Log in with a teacher account and a student account and exchange audio and video feedLog in with a teacher account and a student account and exchange audio and video feed

Ao se conectar com um aluno, você deverá ver esta tela.

Connected with a studentConnected with a student

Conclusão

Aplicativos em tempo real são incríveis. Elas estão unindo o mundo, e agora que o mundo está se tornando cada vez mais distante, a demanda por essas Applications é alta.

Trabalhar com WebRTC e WebSockets para comunicação em tempo real pode ser complicado, mas a API da Vonage oferece métodos auxiliares fáceis de usar para uma ampla variedade de casos de uso. Este artigo demonstrou como configurar uma transmissão de vídeo usando o Laravel. Você pode clonar o repositório aqui.

Compartilhar:

https://a.storyblok.com/f/270183/250x250/5e3dc7b6d8/solomon-eseme.png
Solomon EsemeAutor convidado

Um desenvolvedor de software focado na criação de produtos inovadores e de alto desempenho, seguindo as melhores práticas e os padrões do setor. Ele também adora escrever sobre desenvolvimento de back-end.