├── .gitignore ├── .styleci.yml ├── src ├── Builders │ ├── BuilderInterface.php │ ├── TokenOptionsBuilder.php │ ├── SubscriberBuilder.php │ ├── PublisherBuilder.php │ ├── ConnectionBuilder.php │ ├── SignalPropertiesBuilder.php │ ├── PublishStreamBuilder.php │ ├── SessionPropertiesBuilder.php │ ├── RecordingPropertiesBuilder.php │ └── RecordingBuilder.php ├── Enums │ ├── MediaMode.php │ ├── OpenViduRole.php │ ├── OutputMode.php │ ├── RecordingMode.php │ ├── Uri.php │ ├── RecordingLayout.php │ └── RecordingStatus.php ├── StreamInterface.php ├── Exceptions │ ├── OpenViduException.php │ ├── OpenViduRecordingStatusException.php │ ├── OpenViduStreamCantCloseException.php │ ├── OpenViduRecordingNotFoundException.php │ ├── OpenViduSessionCantCloseException.php │ ├── OpenViduSessionCantCreateException.php │ ├── OpenViduSessionCantRecordingException.php │ ├── OpenViduStreamTypeInvalidException.php │ ├── OpenViduSessionNotFoundException.php │ ├── OpenViduInvalidArgumentException.php │ ├── OpenViduConnectionNotFoundException.php │ ├── OpenViduProblemWithBodyParameterException.php │ ├── OpenViduSessionHasNotConnectedParticipantsException.php │ ├── OpenViduServerRecordingIsDisabledException.php │ ├── OpenViduRecordingResolutionException.php │ └── OpenViduTokenCantCreateException.php ├── Events │ ├── SessionCreated.php │ ├── FilterEventDispatched.php │ ├── SessionDestroyed.php │ ├── ParticipantJoined.php │ ├── ParticipantLeft.php │ ├── WebRTCConnectionCreated.php │ ├── WebRTCConnectionDestroyed.php │ └── RecordingStatusChanged.php ├── Http │ ├── Requests │ │ ├── WebhookEventRequest.php │ │ ├── SignalRequest.php │ │ ├── StartRecordingRequest.php │ │ ├── PublishStreamRequest.php │ │ └── GenerateTokenRequest.php │ ├── routes.php │ └── Controllers │ │ └── OpenViduController.php ├── Facades │ └── OpenVidu.php ├── TokenOptions.php ├── Dispatchers │ └── WebhookEventDispatcher.php ├── SignalProperties.php ├── Providers │ └── OpenViduServiceProvider.php ├── KurentoOptions.php ├── IPCameraOptions.php ├── Subscriber.php ├── SessionProperties.php ├── Recording.php ├── RecordingProperties.php ├── Publisher.php ├── Connection.php ├── Cache │ └── SessionStore.php ├── OpenVidu.php └── Session.php ├── database └── migrations │ └── 2019_12_01_000001_create_openvidu_cache_table.php ├── LICENSE.md └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: laravel -------------------------------------------------------------------------------- /src/Builders/BuilderInterface.php: -------------------------------------------------------------------------------- 1 | (not available yet) The session will attempt to transmit streams 14 | * directly between clients 15 | */ 16 | public const RELAYED = 'RELAYED'; 17 | 18 | /** 19 | * The session will transmit streams using LaravelOpenVidu Media Node 20 | */ 21 | public const ROUTED = 'ROUTED'; 22 | } 23 | -------------------------------------------------------------------------------- /src/Builders/TokenOptionsBuilder.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Builders/SubscriberBuilder.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduStreamCantCloseException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduRecordingNotFoundException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduSessionCantCloseException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduSessionCantCreateException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduSessionCantRecordingException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduStreamTypeInvalidException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduSessionNotFoundException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduInvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduConnectionNotFoundException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduProblemWithBodyParameterException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduSessionHasNotConnectedParticipantsException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Exceptions/OpenViduServerRecordingIsDisabledException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Enums/OpenViduRole.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /database/migrations/2019_12_01_000001_create_openvidu_cache_table.php: -------------------------------------------------------------------------------- 1 | string('key')->unique(); 18 | $table->text('value'); 19 | $table->integer('expiration'); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('openvidu_cache'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Enums/OutputMode.php: -------------------------------------------------------------------------------- 1 | sessionId = $data['sessionId']; 37 | $this->timestamp = $data['timestamp']; 38 | $this->event = $data['event']; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Builders/ConnectionBuilder.php: -------------------------------------------------------------------------------- 1 | - https://www.squareet.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/Exceptions/OpenViduTokenCantCreateException.php: -------------------------------------------------------------------------------- 1 | code}]:{$this->message}\n"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Builders/SignalPropertiesBuilder.php: -------------------------------------------------------------------------------- 1 | 'string|required' 35 | ]; 36 | } 37 | 38 | /** 39 | * Get the error messages for the defined validation rules. 40 | * 41 | * @return array 42 | */ 43 | public function messages() 44 | { 45 | return [ 46 | 'event.required' => /** @scrutinizer ignore-call */ __('validation.webhook_event.required'), 47 | ]; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Enums/RecordingLayout.php: -------------------------------------------------------------------------------- 1 | 'string|required', 34 | 'to' => 'array', 35 | 'to.*' => 'string|distinct', 36 | 'type' => 'string', 37 | 'data' => 'string', 38 | ]; 39 | } 40 | 41 | /** 42 | * Get the error messages for the defined validation rules. 43 | * 44 | * @return array 45 | */ 46 | public function messages() 47 | { 48 | return [ 49 | 'session.required' => /** @scrutinizer ignore-call */ __('validation.signal.session_required'), 50 | 'to.array' => /** @scrutinizer ignore-call */ __('validation.signal.to_array') 51 | ]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Events/FilterEventDispatched.php: -------------------------------------------------------------------------------- 1 | sessionId = $data['sessionId']; 52 | $this->timestamp = $data['timestamp']; 53 | $this->event = $data['event']; 54 | } 55 | } -------------------------------------------------------------------------------- /src/Builders/SessionPropertiesBuilder.php: -------------------------------------------------------------------------------- 1 | 'boolean', 35 | 'hasVideo' => 'boolean', 36 | 'name' => 'string', 37 | 'outputMode' => 'string', 38 | 'recordingLayout' => 'string', 39 | 'customLayout' => 'string', 40 | 'resolution' => 'string' 41 | ]; 42 | } 43 | 44 | /** 45 | * Get the error messages for the defined validation rules. 46 | * 47 | * @return array 48 | */ 49 | public function messages() 50 | { 51 | return [ 52 | 'hasAudio.boolean' => /** @scrutinizer ignore-call */ __('validation.recording.hasAudio_boolean'), 53 | 'hasVideo.boolean' => /** @scrutinizer ignore-call */ __('validation.recording.hasVideo_boolean'), 54 | ]; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Http/Requests/PublishStreamRequest.php: -------------------------------------------------------------------------------- 1 | 'string|required', 35 | 'type' => 'string', 36 | 'adaptativeBitrate' => 'boolean', 37 | 'onlyPlayWithSubscribers' => 'boolean', 38 | 'data' => 'string' 39 | ]; 40 | } 41 | 42 | /** 43 | * Get the error messages for the defined validation rules. 44 | * 45 | * @return array 46 | */ 47 | public function messages() 48 | { 49 | return [ 50 | 'rtspUri.required' => /** @scrutinizer ignore-call */ __('validation.publish.rtspUri_required'), 51 | 'adaptativeBitrate.boolean' => /** @scrutinizer ignore-call */ __('validation.publish.adaptativeBitrate_boolean'), 52 | 'onlyPlayWithSubscribers.boolean' => /** @scrutinizer ignore-call */ __('validation.publish.onlyPlayWithSubscribers_boolean'), 53 | ]; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Events/SessionDestroyed.php: -------------------------------------------------------------------------------- 1 | sessionId = $data['sessionId']; 61 | $this->timestamp = $data['timestamp']; 62 | $this->startTime = $data['startTime']; 63 | $this->duration = $data['duration']; 64 | $this->reason = $data['reason']; 65 | $this->event = $data['event']; 66 | } 67 | } -------------------------------------------------------------------------------- /src/Builders/RecordingPropertiesBuilder.php: -------------------------------------------------------------------------------- 1 | name('openvidu.token'); 6 | Route::get('/sessions', 'OpenViduController@sessions')->name('openvidu.sessions'); 7 | Route::get('/sessions/{sessionId}', 'OpenViduController@session')->name('openvidu.sessions.session'); 8 | Route::get('/sessions/{sessionId}/fetch', 'OpenViduController@fetch')->name('openvidu.sessions.session.fetch'); 9 | Route::get('/sessions/{sessionId}/isBeingRecording', 'OpenViduController@isBeingRecording')->name('openvidu.sessions.session.isBeingRecording'); 10 | Route::get('/sessions/{sessionId}/connections', 'OpenViduController@connections')->name('openvidu.sessions.session.connections'); 11 | Route::post('/sessions/{sessionId}/publish', 'OpenViduController@publish')->name('openvidu.sessions.session.publish'); 12 | Route::delete('/sessions/{sessionId}/forceUnpublish/{streamId}', 'OpenViduController@forceUnpublish')->name('openvidu.sessions.session.forceUnpublish'); 13 | Route::delete('/sessions/{sessionId}/forceDisconnect/{connectionId}', 'OpenViduController@forceDisconnect')->name('openvidu.sessions.session.forceDisconnect'); 14 | Route::patch('/sessions/{sessionId}/close', 'OpenViduController@close')->name('openvidu.sessions.session.close'); 15 | 16 | Route::post('/recordings/start', 'OpenViduController@startRecording')->name('openvidu.recordings.start'); 17 | Route::post('/recordings/{recordingId}/stop', 'OpenViduController@stopRecording')->name('openvidu.recordings.recording.stop'); 18 | Route::get('/recordings/{recordingId}', 'OpenViduController@recording')->name('openvidu.recordings.recording'); 19 | Route::delete('/recordings/{recordingId}', 'OpenViduController@deleteRecording')->name('openvidu.recordings.recording.delete'); 20 | 21 | Route::post('/sendSignal', 'OpenViduController@sendSignal')->name('openvidu.sendsignal'); 22 | 23 | Route::post('/webhook', 'OpenViduController@webhook')->name('openvidu.webhook'); -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squareetlabs/laravel-openvidu", 3 | "description": "Laravel client for controlling your videocalls from your Openvidu server.", 4 | "keywords": [ 5 | "openvidu", 6 | "laravel-openvidu", 7 | "videoconference", 8 | "video-conferencing", 9 | "kurento", 10 | "room", 11 | "chat", 12 | "webrtc" 13 | ], 14 | "homepage": "https://github.com/squareetlabs/laravel-openvidu", 15 | "license": "MIT", 16 | "authors": [ 17 | { 18 | "name": "Jacobo Cantorna Cigarrán", 19 | "email": "jacobo@squareet.com", 20 | "homepage": "https://www.squareet.com", 21 | "role": "Developer" 22 | }, 23 | { 24 | "name": "Alberto Rial Barreiro", 25 | "email": "alberto@squareet.com", 26 | "homepage": "https://www.squareet.com", 27 | "role": "Developer" 28 | } 29 | ], 30 | "require": { 31 | "php": ">=7.2.5", 32 | "ext-json": "*", 33 | "guzzlehttp/guzzle": "^v6.0|~v7.0", 34 | "illuminate/cache": "^v6.0|^v7.0|^v8.0", 35 | "illuminate/config": "^v6.0|^v7.0|^v8.0", 36 | "illuminate/database": "^v6.20.26|^v7.30.6|^v8.0", 37 | "illuminate/events": "^v6.0|^v7.0|^v8.0", 38 | "illuminate/http": "^v6.0|^v7.0|^v8.0", 39 | "illuminate/routing": "^v6.0|^v7.0|^v8.0", 40 | "illuminate/support": "^v6.0|^v7.0|^v8.0", 41 | "illuminate/translation": "^v6.0|^v7.0|^v8.0", 42 | "illuminate/validation": "^v6.0|^v7.0|^v8.0" 43 | }, 44 | "require-dev": { 45 | "squizlabs/php_codesniffer": "3.5.8" 46 | }, 47 | "autoload": { 48 | "psr-4": { 49 | "SquareetLabs\\LaravelOpenVidu\\": "src" 50 | } 51 | }, 52 | "extra": { 53 | "laravel": { 54 | "providers": [ 55 | "SquareetLabs\\LaravelOpenVidu\\Providers\\OpenViduServiceProvider" 56 | ], 57 | "aliases": { 58 | "OpenVidu": "SquareetLabs\\LaravelOpenVidu\\Facades\\OpenVidu" 59 | } 60 | } 61 | }, 62 | "config": { 63 | "sort-packages": true 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Events/ParticipantJoined.php: -------------------------------------------------------------------------------- 1 | sessionId = $data['sessionId']; 65 | $this->timestamp = $data['timestamp']; 66 | $this->participantId = $data['participantId']; 67 | $this->platform = $data['platform']; 68 | $this->clientData = $data['clientData'] ?? ""; 69 | $this->serverData = $data['serverData'] ?? ""; 70 | $this->event = $data['event']; 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/TokenOptions.php: -------------------------------------------------------------------------------- 1 | role = $role; 30 | $this->data = $data; 31 | $this->kurentoOptions = $kurentoOptions; 32 | } 33 | 34 | /** 35 | * Convert the model instance to JSON. 36 | * 37 | * @param int $options 38 | * @return string 39 | * 40 | */ 41 | public function toJson($options = 0): string 42 | { 43 | return json_encode($this->jsonSerialize(), $options); 44 | } 45 | 46 | /** 47 | * Specify data which should be serialized to JSON 48 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 49 | * @return mixed data which can be serialized by json_encode, 50 | * which is a value of any type other than a resource. 51 | * @since 5.4.0 52 | */ 53 | public function jsonSerialize() 54 | { 55 | return $this->toArray(); 56 | } 57 | 58 | /** 59 | * Convert the model instance to an array. 60 | * 61 | * @return array 62 | */ 63 | public function toArray(): array 64 | { 65 | $array = ['role' => $this->role, 'data' => $this->data]; 66 | foreach ($array as $key => $value) { 67 | if (is_null($value) || $value == '') { 68 | unset($array[$key]); 69 | } 70 | } 71 | return $array; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/Dispatchers/WebhookEventDispatcher.php: -------------------------------------------------------------------------------- 1 | session = $session; 32 | $this->data = $data; 33 | $this->type = $type; 34 | $this->to = $to; 35 | } 36 | 37 | /** 38 | * Session name of the recording 39 | * 40 | * @return string 41 | */ 42 | public function session() 43 | { 44 | return $this->session; 45 | } 46 | 47 | /** 48 | * Convert the model instance to JSON. 49 | * 50 | * @param int $options 51 | * @return string 52 | * 53 | */ 54 | public function toJson($options = 0): string 55 | { 56 | return json_encode($this->jsonSerialize(), $options); 57 | } 58 | 59 | /** 60 | * Specify data which should be serialized to JSON 61 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 62 | * @return mixed data which can be serialized by json_encode, 63 | * which is a value of any type other than a resource. 64 | * @since 5.4.0 65 | */ 66 | public function jsonSerialize() 67 | { 68 | return $this->toArray(); 69 | } 70 | 71 | /** 72 | * Convert the model instance to an array. 73 | * 74 | * @return array 75 | */ 76 | public function toArray(): array 77 | { 78 | $array = [ 79 | 'session' => $this->session, 80 | 'data' => $this->data, 81 | 'type' => $this->type, 82 | 'to' => $this->to 83 | ]; 84 | foreach ($array as $key => $value) { 85 | if (is_null($value) || $value == '') { 86 | unset($array[$key]); 87 | } 88 | } 89 | return $array; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/Providers/OpenViduServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton(OpenVidu::class, function () { 24 | return new OpenVidu(/** @scrutinizer ignore-call */ config('services.openvidu')); 25 | }); 26 | 27 | $this->app->alias(OpenVidu::class, 'openVidu'); 28 | //Default parameter added true due to the compatibility 29 | if (config('services.openvidu.use_routes', true)) { 30 | $this->registerRoutes(); 31 | } 32 | } 33 | 34 | /** 35 | * Register the package routes. 36 | * 37 | * @return void 38 | */ 39 | private function registerRoutes() 40 | { 41 | Route::group($this->routeConfiguration(), function () { 42 | $this->loadRoutesFrom(__DIR__.'/../Http/routes.php'); 43 | }); 44 | } 45 | 46 | /** 47 | * Get the SmsUp route group configuration array. 48 | * 49 | * @return array 50 | */ 51 | private function routeConfiguration() 52 | { 53 | return [ 54 | 'domain' => null, 55 | 'namespace' => 'SquareetLabs\LaravelOpenVidu\Http\Controllers', 56 | 'prefix' => 'openvidu' 57 | ]; 58 | } 59 | 60 | /** 61 | * Bootstrap the application services. 62 | * 63 | * @return void 64 | */ 65 | public function boot() 66 | { 67 | if ($this->app->runningInConsole()) { 68 | $this->loadMigrationsFrom(__DIR__.'/../../database/migrations'); 69 | 70 | $this->publishes([ 71 | __DIR__.'/../../database/migrations' => /** @scrutinizer ignore-call */ database_path('migrations'), 72 | ], 'openvidu-migrations'); 73 | 74 | } 75 | Cache::extend('openvidu', function () { 76 | return Cache::repository(new SessionStore(DB::connection(), /** @scrutinizer ignore-call */ config('cache.stores.openvidu.table'))); 77 | }); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Events/ParticipantLeft.php: -------------------------------------------------------------------------------- 1 | sessionId = $data['sessionId']; 86 | $this->timestamp = $data['timestamp']; 87 | $this->participantId = $data['participantId']; 88 | $this->platform = $data['platform']; 89 | $this->clientData = $data['clientData'] ?? ""; 90 | $this->serverData = $data['serverData'] ?? ""; 91 | $this->startTime = $data['startTime']; 92 | $this->duration = $data['duration']; 93 | $this->reason = $data['reason']; 94 | $this->event = $data['event']; 95 | } 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/Http/Requests/GenerateTokenRequest.php: -------------------------------------------------------------------------------- 1 | ['string', Rule::in([MediaMode::ROUTED, MediaMode::RELAYED])], 41 | 'session.recordingMode' => ['string', Rule::in([RecordingMode::MANUAL, RecordingMode::ALWAYS])], 42 | 'session.defaultOutputMode' => ['string', Rule::in([OutputMode::COMPOSED, OutputMode::COMPOSED_QUICK_START, OutputMode::INDIVIDUAL])], 43 | 'session.defaultRecordingLayout' => ['string', Rule::in([RecordingLayout::CUSTOM, RecordingLayout::BEST_FIT])], 44 | 'session.defaultCustomLayout' => 'string', 45 | 'session.customSessionId' => 'string', 46 | 'tokenOptions.data' => 'nullable|string', 47 | 'tokenOptions.role' => ['string', Rule::in([OpenViduRole::MODERATOR, OpenViduRole::PUBLISHER, OpenViduRole::SUBSCRIBER])], 48 | ]; 49 | } 50 | 51 | /** 52 | * Get the error messages for the defined validation rules. 53 | * 54 | * @return array 55 | */ 56 | public function messages() 57 | { 58 | return [ 59 | 'session.mediaMode.in' => /** @scrutinizer ignore-call */ __('validation.session.mediaMode_in'), 60 | 'session.recordingMode.in' => /** @scrutinizer ignore-call */ __('validation.session.recordingMode_in'), 61 | 'session.defaultOutputMode.in' => /** @scrutinizer ignore-call */ __('validation.session.defaultOutputMode_in'), 62 | 'session.defaultRecordingLayout.in' => /** @scrutinizer ignore-call */ __('validation.session.defaultRecordingLayout_in'), 63 | 'session.defaultCustomLayout.in' => /** @scrutinizer ignore-call */ __('validation.session.defaultCustomLayout_in'), 64 | 'tokenOptions.role.in' => /** @scrutinizer ignore-call */ __('validation.session.defaultCustomLayout_in'), 65 | ]; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/KurentoOptions.php: -------------------------------------------------------------------------------- 1 | videoMaxRecvBandwidth = $videoMaxRecvBandwidth; 35 | $this->videoMinRecvBandwidth = $videoMinRecvBandwidth; 36 | $this->videoMaxSendBandwidth = $videoMaxSendBandwidth; 37 | $this->videoMinSendBandwidth = $videoMinSendBandwidth; 38 | $this->allowedFilters = $allowedFilters; 39 | } 40 | 41 | /** 42 | * Convert the model instance to JSON. 43 | * 44 | * @param int $options 45 | * @return string 46 | * 47 | */ 48 | public function toJson($options = 0): string 49 | { 50 | return json_encode($this->jsonSerialize(), $options); 51 | } 52 | 53 | /** 54 | * Specify data which should be serialized to JSON 55 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 56 | * @return mixed data which can be serialized by json_encode, 57 | * which is a value of any type other than a resource. 58 | * @since 5.4.0 59 | */ 60 | public function jsonSerialize() 61 | { 62 | return $this->toArray(); 63 | } 64 | 65 | /** 66 | * Convert the model instance to an array. 67 | * 68 | * @return array 69 | */ 70 | public function toArray(): array 71 | { 72 | $array = ['videoMaxRecvBandwidth' => $this->videoMaxRecvBandwidth, 'videoMinRecvBandwidth' => $this->videoMinRecvBandwidth, 'videoMaxSendBandwidth' => $this->videoMaxSendBandwidth, 'videoMinSendBandwidth' => $this->videoMinSendBandwidth]; 73 | foreach ($this->allowedFilters as $allowed_filter) { 74 | $array['allowedFilters'][] = $allowed_filter; 75 | } 76 | foreach ($array as $key => $value) { 77 | if (is_null($value) || $value == '') { 78 | unset($array[$key]); 79 | } 80 | } 81 | return $array; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/IPCameraOptions.php: -------------------------------------------------------------------------------- 1 | rtspUri = $rtspUri; 35 | $this->type = $type; 36 | $this->adaptativeBitrate = $adaptativeBitrate; 37 | $this->onlyPlayWithSubscribers = $onlyPlayWithSubscribers; 38 | $this->data = $data; 39 | } 40 | 41 | /** 42 | * Convert the model instance to JSON. 43 | * 44 | * @param int $options 45 | * @return string 46 | * 47 | */ 48 | public function toJson($options = 0): string 49 | { 50 | return json_encode($this->jsonSerialize(), $options); 51 | } 52 | 53 | /** 54 | * Specify data which should be serialized to JSON 55 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 56 | * @return mixed data which can be serialized by json_encode, 57 | * which is a value of any type other than a resource. 58 | * @since 5.4.0 59 | */ 60 | public function jsonSerialize() 61 | { 62 | return $this->toArray(); 63 | } 64 | 65 | /** 66 | * Convert the model instance to an array. 67 | * 68 | * @return array 69 | */ 70 | public function toArray(): array 71 | { 72 | $array = ['rtspUri' => $this->rtspUri, 'type' => $this->type, 'adaptativeBitrate' => $this->adaptativeBitrate, 'onlyPlayWithSubscribers' => $this->onlyPlayWithSubscribers, 'data' => $this->data]; 73 | foreach ($array as $key => $value) { 74 | if (is_null($value) || $value == '') { 75 | unset($array[$key]); 76 | } 77 | } 78 | return $array; 79 | } 80 | 81 | /** @return string */ 82 | public function getRtspUri() 83 | { 84 | return $this->rtspUri; 85 | } 86 | 87 | /** @return string */ 88 | public function getType() 89 | { 90 | return $this->type; 91 | } 92 | 93 | /** @return bool */ 94 | public function getAdaptativeBitrate() 95 | { 96 | return $this->adaptativeBitrate; 97 | } 98 | 99 | /** @return bool */ 100 | public function getOnlyPlayWithSubscribers() 101 | { 102 | return $this->onlyPlayWithSubscribers; 103 | } 104 | 105 | /** @return string */ 106 | public function getData() 107 | { 108 | return $this->data; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Events/WebRTCConnectionCreated.php: -------------------------------------------------------------------------------- 1 | sessionId = $data['sessionId']; 97 | $this->timestamp = $data['timestamp']; 98 | $this->participantId = $data['participantId']; 99 | if (array_key_exists('receivingFrom', $data)) { 100 | $this->receivingFrom = $data['receivingFrom']; 101 | } 102 | $this->audioEnabled = $data['audioEnabled']; 103 | $this->videoEnabled = $data['videoEnabled']; 104 | if (array_key_exists('videoSource', $data)) { 105 | $this->videoSource = $data['videoSource']; 106 | $this->videoFramerate = $data['videoFramerate']; 107 | $this->videoDimensions = $data['videoDimensions']; 108 | } 109 | $this->event = $data['event']; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Subscriber.php: -------------------------------------------------------------------------------- 1 | streamId = $streamId; 42 | $this->publisherStreamId = $publisherStreamId; 43 | $this->createdAt = $createdAt; 44 | } 45 | 46 | public function __toString(): string 47 | { 48 | return $this->getStreamId(); 49 | } 50 | 51 | /** 52 | * @return string 53 | */ 54 | public function getStreamId(): string 55 | { 56 | return $this->streamId; 57 | } 58 | 59 | /** 60 | * @return string 61 | */ 62 | public function getPublisherStreamId(): string 63 | { 64 | return $this->publisherStreamId; 65 | } 66 | 67 | 68 | /** 69 | * Convert the model instance to JSON. 70 | * 71 | * @param int $options 72 | * @return string 73 | * 74 | */ 75 | public function toJson($options = 0): string 76 | { 77 | return json_encode($this->jsonSerialize(), $options); 78 | } 79 | 80 | /** 81 | * Specify data which should be serialized to JSON 82 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 83 | * @return mixed data which can be serialized by json_encode, 84 | * which is a value of any type other than a resource. 85 | * @since 5.4.0 86 | */ 87 | public function jsonSerialize() 88 | { 89 | return $this->toArray(); 90 | } 91 | 92 | /** 93 | * Convert the model instance to an array. 94 | * 95 | * @return array 96 | */ 97 | public function toArray(): array 98 | { 99 | $array = [ 100 | 'streamId' => $this->streamId, 101 | 'publisherStreamId' => $this->publisherStreamId, 102 | 'createdAt' => $this->createdAt 103 | ]; 104 | foreach ($array as $key => $value) { 105 | if (is_null($value) || $value == '') { 106 | unset($array[$key]); 107 | } 108 | } 109 | return $array; 110 | } 111 | 112 | /** 113 | * @param Publisher $other 114 | * @return bool 115 | */ 116 | public function equalTo(Publisher $other): bool 117 | { 118 | return ( 119 | $this->streamId === $other->getStreamId() && 120 | $this->createdAt === $other->getCreatedAt() && 121 | $this->publisherStreamId === $other->publisherStreamId() 122 | ); 123 | } 124 | 125 | /** 126 | * @return int 127 | */ 128 | public function getCreatedAt(): int 129 | { 130 | return $this->createdAt; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/Events/WebRTCConnectionDestroyed.php: -------------------------------------------------------------------------------- 1 | sessionId = $data['sessionId']; 118 | $this->timestamp = $data['timestamp']; 119 | $this->participantId = $data['participantId']; 120 | if (array_key_exists('receivingFrom', $data)) { 121 | $this->receivingFrom = $data['receivingFrom']; 122 | } 123 | $this->audioEnabled = $data['audioEnabled']; 124 | $this->videoEnabled = $data['videoEnabled']; 125 | if (array_key_exists('videoSource', $data)) { 126 | $this->videoSource = $data['videoSource']; 127 | $this->videoFramerate = $data['videoFramerate']; 128 | $this->videoDimensions = $data['videoDimensions']; 129 | } 130 | $this->startTime = $data['startTime']; 131 | $this->duration = $data['duration']; 132 | $this->reason = $data['reason']; 133 | $this->event = $data['event']; 134 | } 135 | } -------------------------------------------------------------------------------- /src/Events/RecordingStatusChanged.php: -------------------------------------------------------------------------------- 1 | sessionId = $data['sessionId']; 133 | $this->timestamp = $data['timestamp']; 134 | if (array_key_exists('participantId', $data)) { 135 | $this->participantId = $data['participantId']; 136 | } 137 | $this->startTime = $data['startTime']; 138 | $this->id = $data['id']; 139 | $this->name = $data['name']; 140 | $this->outputMode = $data['outputMode']; 141 | $this->hasAudio = $data['hasAudio']; 142 | $this->hasVideo = $data['hasVideo']; 143 | $this->recordingLayout = $data['recordingLayout']; 144 | $this->resolution = $data['resolution']; 145 | $this->status = $data['status']; 146 | if (array_key_exists('reason', $data)) { 147 | $this->size = $data['size']; 148 | $this->duration = $data['duration']; 149 | $this->reason = $data['reason']; 150 | } 151 | $this->event = $data['event']; 152 | } 153 | } -------------------------------------------------------------------------------- /src/SessionProperties.php: -------------------------------------------------------------------------------- 1 | mediaMode = $mediaMode; 55 | $this->recordingMode = $recordingMode; 56 | $this->defaultOutputMode = $defaultOutputMode; 57 | $this->defaultRecordingLayout = $defaultRecordingLayout; 58 | $this->defaultCustomLayout = $defaultCustomLayout; 59 | $this->customSessionId = $customSessionId; 60 | } 61 | 62 | /** 63 | * @return string 64 | */ 65 | public function getCustomSessionId(): ?string 66 | { 67 | return $this->customSessionId; 68 | } 69 | 70 | /** 71 | * @return string 72 | */ 73 | public function getMediaMode(): string 74 | { 75 | return $this->mediaMode; 76 | } 77 | 78 | /** 79 | * @return string 80 | */ 81 | public function getRecordingMode(): string 82 | { 83 | return $this->recordingMode; 84 | } 85 | 86 | /** 87 | * @return string 88 | */ 89 | public function getDefaultOutputMode(): string 90 | { 91 | return $this->defaultOutputMode; 92 | } 93 | 94 | /** 95 | * @return string 96 | */ 97 | public function getDefaultRecordingLayout(): ?string 98 | { 99 | return $this->defaultRecordingLayout; 100 | } 101 | 102 | /** 103 | * @return string 104 | */ 105 | public function getDefaultCustomLayout(): ?string 106 | { 107 | return $this->defaultCustomLayout; 108 | } 109 | 110 | /** 111 | * Convert the model instance to JSON. 112 | * 113 | * @param int $options 114 | * @return string 115 | * 116 | */ 117 | public function toJson($options = 0): string 118 | { 119 | $json = json_encode($this->jsonSerialize(), $options); 120 | return $json; 121 | } 122 | 123 | /** 124 | * Specify data which should be serialized to JSON 125 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 126 | * @return mixed data which can be serialized by json_encode, 127 | * which is a value of any type other than a resource. 128 | * @since 5.4.0 129 | */ 130 | public function jsonSerialize() 131 | { 132 | return $this->toArray(); 133 | } 134 | 135 | /** 136 | * Convert the model instance to an array. 137 | * 138 | * @return array 139 | */ 140 | public function toArray(): array 141 | { 142 | $array = [ 143 | 'mediaMode' => $this->mediaMode, 144 | 'recordingMode' => $this->recordingMode, 145 | 'defaultOutputMode' => $this->defaultOutputMode, 146 | 'defaultRecordingLayout' => $this->defaultRecordingLayout, 147 | 'defaultCustomLayout' => $this->defaultCustomLayout, 148 | 'customSessionId' => $this->customSessionId 149 | ]; 150 | foreach ($array as $key => $value) { 151 | if (is_null($value) || $value == '') { 152 | unset($array[$key]); 153 | } 154 | } 155 | return $array; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/Recording.php: -------------------------------------------------------------------------------- 1 | id = $id; 55 | $this->sessionId = $sessionId; 56 | $this->createdAt = $createdAt; 57 | $this->size = $size; 58 | $this->duration = $duration; 59 | $this->url = $url; 60 | $this->recordingProperties = $recordingProperties ? $recordingProperties : $this->getDefaultRecordingProperties(); 61 | 62 | } 63 | 64 | /** 65 | * @return RecordingProperties 66 | */ 67 | private function getDefaultRecordingProperties(): RecordingProperties 68 | { 69 | return new RecordingProperties($this->sessionId, $this->sessionId, OutputMode::COMPOSED, RecordingLayout::BEST_FIT); 70 | } 71 | 72 | /** 73 | * Session associated to the recording 74 | * @return string 75 | */ 76 | public function getSessionId(): string 77 | { 78 | return $this->sessionId; 79 | } 80 | 81 | /** 82 | * Time when the recording started in UTC milliseconds 83 | * @return int 84 | */ 85 | public function getCreatedAt(): int 86 | { 87 | return $this->createdAt; 88 | } 89 | 90 | /** 91 | * Size of the recording in bytes (0 until the recording is stopped) 92 | * @return int 93 | */ 94 | public function getSize(): int 95 | { 96 | return $this->size; 97 | } 98 | 99 | /** 100 | * Duration of the recording in seconds (0 until the recording is stopped) 101 | * @return float 102 | */ 103 | public function getDuration(): float 104 | { 105 | return $this->duration; 106 | } 107 | 108 | /** 109 | * URL of the recording. You can access the file from there. It is 110 | * null until recording reaches "ready" or "failed" status. If 111 | * OpenVidu Server configuration property 113 | * openvidu.recording.public-access is false, this path will be 114 | * secured with OpenVidu credentials 115 | */ 116 | public function getUrl(): string 117 | { 118 | return $this->url; 119 | } 120 | 121 | /** 122 | * Status of the recording 123 | * @return RecordingStatus 124 | */ 125 | public function getStatus() 126 | { 127 | return $this->status; 128 | } 129 | 130 | 131 | /** 132 | * Technical properties of the recorded file 133 | * @return RecordingProperties 134 | */ 135 | public function getRecordingProperties(): RecordingProperties 136 | { 137 | return $this->recordingProperties; 138 | } 139 | 140 | /** 141 | * @return string 142 | */ 143 | public function __toString(): string 144 | { 145 | return $this->getId(); 146 | } 147 | 148 | /** 149 | * Recording unique identifier 150 | * @return string 151 | */ 152 | public function getId(): string 153 | { 154 | return $this->id; 155 | } 156 | 157 | /** 158 | * Convert the model instance to JSON. 159 | * 160 | * @param int $options 161 | * @return string 162 | * 163 | */ 164 | public function toJson($options = 0): string 165 | { 166 | $json = json_encode($this->jsonSerialize(), $options); 167 | return $json; 168 | } 169 | 170 | /** 171 | * Specify data which should be serialized to JSON 172 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 173 | * @return mixed data which can be serialized by json_encode, 174 | * which is a value of any type other than a resource. 175 | * @since 5.4.0 176 | */ 177 | public function jsonSerialize() 178 | { 179 | return $this->toArray(); 180 | } 181 | 182 | /** 183 | * Convert the model instance to an array. 184 | * 185 | * @return array 186 | */ 187 | public function toArray(): array 188 | { 189 | $array = ['id' => $this->id, 'sessionId' => $this->sessionId, 'size' => $this->size, 'status' => $this->status, 'duration' => $this->duration, 'resolution' => $this->getResolution(), 'hasAudio' => $this->hasAudio(), 'hasVideo' => $this->hasVideo(), 'url' => $this->url, 'createdAt' => $this->createdAt]; 190 | foreach ($array as $key => $value) { 191 | if (is_null($value) || $value == '') { 192 | unset($array[$key]); 193 | } 194 | } 195 | return $array; 196 | } 197 | 198 | /** 199 | * Resolution of the video file. Only defined if OutputMode of the Recording is 200 | * set to {@see OutputMode::COMPOSED} 201 | */ 202 | public function getResolution(): string 203 | { 204 | return $this->recordingProperties->resolution(); 205 | } 206 | 207 | /** 208 | * true if the recording has an audio track, false 209 | * otherwise (currently fixed to true) 210 | */ 211 | public function hasAudio(): bool 212 | { 213 | return $this->recordingProperties->hasAudio(); 214 | } 215 | 216 | /** 217 | * true if the recording has a video track, false 218 | * otherwise (currently fixed to true) 219 | */ 220 | public function hasVideo(): bool 221 | { 222 | return $this->recordingProperties->hasVideo(); 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /src/RecordingProperties.php: -------------------------------------------------------------------------------- 1 | session = $session; 46 | $this->hasAudio = $hasAudio; 47 | $this->hasVideo = $hasVideo; 48 | $this->name = $name; 49 | $this->outputMode = $outputMode; 50 | if ($this->outputMode === OutputMode::COMPOSED && $this->hasVideo) { 51 | $this->resolution = $resolution ? $resolution : '1920x1080'; 52 | $this->recordingLayout = $recordingLayout ? $recordingLayout : RecordingLayout::BEST_FIT; 53 | 54 | if ($this->recordingLayout === RecordingLayout::CUSTOM) { 55 | $this->customLayout = $customLayout; 56 | } 57 | } 58 | } 59 | 60 | /** 61 | * Session name of the recording 62 | * 63 | * @return string 64 | */ 65 | public function session() 66 | { 67 | return $this->session; 68 | } 69 | 70 | /** 71 | * Defines the name you want to give to the video file. You can access this same 72 | * value in your clients on recording events (recordingStarted, 73 | * recordingStopped) 74 | * 75 | * @return string 76 | */ 77 | public function name() 78 | { 79 | return $this->name; 80 | } 81 | 82 | /** 83 | * Defines the mode of recording: {@see OutputMode::COMPOSED} or {@see OutputMode::COMPOSED_QUICK_START} for a 84 | * single archive in a grid layout or {@@see OutputMode::INDIVIDUAL} 85 | * for one archive for each stream.
86 | *
87 | * 88 | * Default to {@see OutputMode::COMPOSED} 89 | * 90 | * @return OutputMode|string 91 | */ 92 | public function outputMode() 93 | { 94 | return $this->outputMode; 95 | } 96 | 97 | /** 98 | * Defines the layout to be used in the recording.
99 | * Will only have effect if has been cealled with value {@see OutputMode::COMPOSED} or {@see OutputMode::COMPOSED_QUICK_START}.
100 | *
101 | * 102 | * Default to {@see RecordingLayout#BEST_FIT} 103 | * 104 | * @return RecordingLayout|string 105 | */ 106 | public function recordingLayout() 107 | { 108 | return $this->recordingLayout; 109 | } 110 | 111 | /** 112 | * If {@see RecordingProperties::$recordingLayout} is 113 | * set to {@see RecordingLayout::CUSTOM}, this property 114 | * defines the relative path to the specific custom layout you want to use.
115 | * See Custom recording layouts to learn more 116 | * 117 | * @return string|null 118 | */ 119 | public function customLayout() 120 | { 121 | return $this->customLayout; 122 | } 123 | 124 | /** 125 | * Defines the resolution of the recorded video.
126 | * Will only have effect if has been called with value 127 | * {@see outputMode::COMPOSED}. 128 | * {@see OutputMode::COMPOSED_QUICK_START} 129 | * {@see OutputMode::INDIVIDUAL} 130 | *
131 | * 132 | * Default to "1920x1080" 133 | * @return string 134 | */ 135 | public function resolution(): string 136 | { 137 | return $this->resolution; 138 | } 139 | 140 | /** 141 | * Defines whether to record audio or not. Cannot be set to false at the same 142 | * time as {@see hasVideo()}.
143 | *
144 | * 145 | * Default to true 146 | * 147 | * @return bool 148 | */ 149 | public function hasAudio() 150 | { 151 | return $this->hasAudio; 152 | } 153 | 154 | /** 155 | * Defines whether to record video or not. Cannot be set to false at the same 156 | * time as {@see hasAudio()}.
157 | *
158 | * 159 | * Default to true 160 | * 161 | * @return bool 162 | */ 163 | public function hasVideo() 164 | { 165 | return $this->hasVideo; 166 | } 167 | 168 | /** 169 | * Convert the model instance to JSON. 170 | * 171 | * @param int $options 172 | * @return string 173 | * 174 | */ 175 | public function toJson($options = 0): string 176 | { 177 | return json_encode($this->jsonSerialize(), $options); 178 | } 179 | 180 | /** 181 | * Specify data which should be serialized to JSON 182 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 183 | * @return mixed data which can be serialized by json_encode, 184 | * which is a value of any type other than a resource. 185 | * @since 5.4.0 186 | */ 187 | public function jsonSerialize() 188 | { 189 | return $this->toArray(); 190 | } 191 | 192 | /** 193 | * Convert the model instance to an array. 194 | * 195 | * @return array 196 | */ 197 | public function toArray(): array 198 | { 199 | $array = [ 200 | 'session' => $this->session, 201 | 'hasAudio' => $this->hasAudio, 202 | 'hasVideo' => $this->hasVideo, 203 | 'name' => $this->name, 204 | 'outputMode' => $this->outputMode, 205 | 'recordingLayout' => $this->recordingLayout, 206 | 'resolution' => $this->resolution, 207 | 'customLayout' => $this->customLayout 208 | ]; 209 | foreach ($array as $key => $value) { 210 | if (is_null($value) || $value == '') { 211 | unset($array[$key]); 212 | } 213 | } 214 | return $array; 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/Publisher.php: -------------------------------------------------------------------------------- 1 | streamId = $streamId; 89 | $this->createdAt = $createdAt; 90 | $this->hasAudio = $hasAudio; 91 | $this->hasVideo = $hasVideo; 92 | $this->audioActive = $audioActive; 93 | $this->videoActive = $videoActive; 94 | $this->frameRate = $frameRate; 95 | $this->typeOfVideo = $typeOfVideo; 96 | $this->videoDimensions = $videoDimensions; 97 | 98 | } 99 | 100 | public function __toString(): string 101 | { 102 | return $this->getStreamId(); 103 | } 104 | 105 | /** 106 | * @return string 107 | */ 108 | public function getStreamId(): string 109 | { 110 | return $this->streamId; 111 | } 112 | 113 | /** 114 | * Convert the model instance to JSON. 115 | * 116 | * @param int $options 117 | * @return string 118 | * 119 | */ 120 | public function toJson($options = 0): string 121 | { 122 | return json_encode($this->jsonSerialize(), $options); 123 | } 124 | 125 | /** 126 | * Specify data which should be serialized to JSON 127 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 128 | * @return mixed data which can be serialized by json_encode, 129 | * which is a value of any type other than a resource. 130 | * @since 5.4.0 131 | */ 132 | public function jsonSerialize() 133 | { 134 | return $this->toArray(); 135 | } 136 | 137 | /** 138 | * Convert the model instance to an array. 139 | * 140 | * @return array 141 | */ 142 | public function toArray(): array 143 | { 144 | $array = [ 145 | 'streamId' => $this->streamId, 146 | 'createdAt' => $this->createdAt, 147 | 'hasAudio' => $this->hasAudio, 148 | 'hasVideo' => $this->hasVideo, 149 | 'audioActive' => $this->audioActive, 150 | 'videoActive' => $this->videoActive, 151 | 'frameRate' => $this->frameRate, 152 | 'typeOfVideo' => $this->typeOfVideo, 153 | 'videoDimensions' => $this->videoDimensions 154 | ]; 155 | foreach ($array as $key => $value) { 156 | if (is_null($value) || $value == '') { 157 | unset($array[$key]); 158 | } 159 | } 160 | return $array; 161 | } 162 | 163 | /** 164 | * @param Publisher $other 165 | * @return bool 166 | */ 167 | public function equalTo(Publisher $other): bool 168 | { 169 | return ( 170 | $this->streamId === $other->getStreamId() && 171 | $this->createdAt === $other->getCreatedAt() && 172 | $this->hasAudio === $other->hasAudio() && 173 | $this->hasVideo === $other->hasVideo() && 174 | $this->audioActive === $other->isAudioActive() && 175 | $this->videoActive === $other->isVideoActive() && 176 | $this->frameRate === $other->getFrameRate() && 177 | $this->typeOfVideo === $other->getTypeOfVideo() && 178 | $this->videoDimensions === $other->getVideoDimensions() 179 | ); 180 | } 181 | 182 | /** 183 | * @return int 184 | */ 185 | public function getCreatedAt(): int 186 | { 187 | return $this->createdAt; 188 | } 189 | 190 | /** 191 | * @return bool 192 | */ 193 | public function hasAudio(): bool 194 | { 195 | return $this->hasAudio; 196 | } 197 | 198 | /** 199 | * @return bool 200 | */ 201 | public function hasVideo(): bool 202 | { 203 | return $this->hasVideo; 204 | } 205 | 206 | /** 207 | * @return bool 208 | */ 209 | public function isAudioActive(): bool 210 | { 211 | return $this->audioActive; 212 | } 213 | 214 | /** 215 | * @return bool 216 | */ 217 | public function isVideoActive(): bool 218 | { 219 | return $this->videoActive; 220 | } 221 | 222 | /** 223 | * @return int 224 | */ 225 | public function getFrameRate(): int 226 | { 227 | return $this->frameRate; 228 | } 229 | 230 | /** 231 | * @return string 232 | */ 233 | public function getTypeOfVideo(): string 234 | { 235 | return $this->typeOfVideo; 236 | } 237 | 238 | /** 239 | * @return string 240 | */ 241 | public function getVideoDimensions(): string 242 | { 243 | return $this->videoDimensions; 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /src/Http/Controllers/OpenViduController.php: -------------------------------------------------------------------------------- 1 | get('session'))); 39 | $token = $session->generateToken(TokenOptionsBuilder::build($request->get('tokenOptions'))); 40 | return Response::json(['token' => $token], 200); 41 | } 42 | 43 | /** 44 | * @param string $sessionId 45 | * @return string 46 | */ 47 | public function session(string $sessionId) 48 | { 49 | $session = OpenVidu::getSession($sessionId); 50 | return Response::json(['session' => $session], 200); 51 | } 52 | 53 | /** 54 | * @return string 55 | */ 56 | public function sessions() 57 | { 58 | $sessions = OpenVidu::getActiveSessions(); 59 | return Response::json(['sessions' => $sessions], 200); 60 | } 61 | 62 | /** 63 | * @param string $sessionId 64 | * @return string 65 | */ 66 | public function connections(string $sessionId) 67 | { 68 | $session = OpenVidu::getSession($sessionId); 69 | $connections = $session->getActiveConnections(); 70 | return Response::json(['connections' => $connections], 200); 71 | } 72 | 73 | /** 74 | * @param string $sessionId 75 | * @return string 76 | * @throws OpenViduException 77 | */ 78 | public function close(string $sessionId) 79 | { 80 | $session = OpenVidu::getSession($sessionId); 81 | $closed = $session->close(); 82 | return Response::json(['closed' => $closed], 200); 83 | } 84 | 85 | 86 | /** 87 | * @param string $sessionId 88 | * @return string 89 | */ 90 | public function fetch(string $sessionId) 91 | { 92 | $session = OpenVidu::getSession($sessionId); 93 | $hasChanges = $session->fetch(); 94 | return Response::json(['session' => $session, 'hasChanges' => $hasChanges], 200); 95 | } 96 | 97 | 98 | /** 99 | * @param string $sessionId 100 | * @return string 101 | */ 102 | public function isBeingRecording(string $sessionId) 103 | { 104 | $session = OpenVidu::getSession($sessionId); 105 | $isBeingRecording = $session->isBeingRecorded(); 106 | return Response::json(['isBeingRecording' => $isBeingRecording], 200); 107 | } 108 | 109 | 110 | /** 111 | * @param string $sessionId 112 | * @param PublishStreamRequest $request 113 | * @return string 114 | * @throws OpenViduException 115 | * @throws OpenViduSessionNotFoundException 116 | * @throws OpenViduStreamTypeInvalidException 117 | */ 118 | public function publish(string $sessionId, PublishStreamRequest $request) 119 | { 120 | $session = OpenVidu::getSession($sessionId); 121 | $connection = $session->publish(PublishStreamBuilder::build($request->all())); 122 | return Response::json(['connection' => $connection], 200); 123 | } 124 | 125 | 126 | /** 127 | * @param string $sessionId 128 | * @param string $streamId 129 | * @return string 130 | * @throws OpenViduConnectionNotFoundException 131 | * @throws OpenViduException 132 | * @throws OpenViduSessionNotFoundException 133 | */ 134 | public function forceUnpublish(string $sessionId, string $streamId) 135 | { 136 | $session = OpenVidu::getSession($sessionId); 137 | $session->forceUnpublish($streamId); 138 | return Response::json(['unpublished' => true], 200); 139 | } 140 | 141 | /** 142 | * @param string $sessionId 143 | * @param string $connectionId 144 | * @return string 145 | * @throws OpenViduException 146 | */ 147 | public function forceDisconnect(string $sessionId, string $connectionId) 148 | { 149 | $session = OpenVidu::getSession($sessionId); 150 | $session->forceDisconnect($connectionId); 151 | return Response::json(['disconnected' => true], 200); 152 | } 153 | 154 | 155 | /** 156 | * @param StartRecordingRequest $request 157 | * @return string 158 | * @throws OpenViduInvalidArgumentException 159 | */ 160 | public function startRecording(StartRecordingRequest $request) 161 | { 162 | $recording = OpenVidu::startRecording(RecordingPropertiesBuilder::build($request->all())); 163 | return Response::json(['recording' => $recording], 200); 164 | } 165 | 166 | 167 | /** 168 | * @param string $recordingId 169 | * @return string 170 | */ 171 | public function stopRecording(string $recordingId) 172 | { 173 | $recording = OpenVidu::stopRecording($recordingId); 174 | return Response::json(['recording' => $recording], 200); 175 | } 176 | 177 | /** 178 | * @param string $recordingId 179 | * @return string 180 | */ 181 | public function recording(string $recordingId) 182 | { 183 | $recording = OpenVidu::getRecording($recordingId); 184 | return Response::json(['recording' => $recording], 200); 185 | } 186 | 187 | 188 | /** 189 | * @param string $recordingId 190 | * @return string 191 | */ 192 | public function deleteRecording(string $recordingId) 193 | { 194 | $recording = OpenVidu::deleteRecording($recordingId); 195 | return Response::json(['recording' => $recording], 200); 196 | } 197 | 198 | /** 199 | * @param SignalRequest $request 200 | * @return string 201 | * @throws OpenViduInvalidArgumentException 202 | */ 203 | public function signal(SignalRequest $request) 204 | { 205 | $sent = OpenVidu::sendSignal(SignalPropertiesBuilder::build($request->all())); 206 | return Response::json(['sent' => $sent], 200); 207 | } 208 | 209 | /** 210 | * @param WebhookEventRequest $request 211 | * @return string 212 | */ 213 | public function webhook(WebhookEventRequest $request) 214 | { 215 | WebhookEventDispatcher::dispatch($request->all()); 216 | return Response::json(['success' => true], 200); 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /src/Connection.php: -------------------------------------------------------------------------------- 1 | PRO 39 | * Geo location of the connection, with the following format: `"CITY, COUNTRY"` (`"unknown"` if it wasn't possible to locate it) 40 | */ 41 | private $location; 42 | 43 | /** @var string 44 | * A complete description of the platform used by the participant to connect to the session 45 | */ 46 | private $platform; 47 | 48 | /** @var string 49 | * Data associated to the connection on the server-side. This value is set with {@uses TokenOptions::$data} when calling {@see Session::generateToken()} 50 | */ 51 | private $serverData; 52 | 53 | /** @var string 54 | * Data associated to the connection on the client-side. This value is set with second parameter of method 55 | * {@method Session.connect}(/api/openvidu-browser/classes/session.html#connect) in OpenVidu Browser 56 | */ 57 | private $clientData; 58 | 59 | /** @var array 60 | * Array of Publisher objects this particular Connection is publishing to the Session (each Publisher object has one Stream, uniquely 61 | * identified by its `streamId`). You can call {@uses Session::forceUnpublish} passing any of this values as parameter 62 | */ 63 | private $publishers = []; 64 | 65 | /** @var array 66 | * Array of streams (their `streamId` properties) this particular Connection is subscribed to. Each one always corresponds to one 67 | * Publisher of some other Connection: each string of this array must be equal to one [[Publisher.streamId]] of other Connection 68 | */ 69 | private $subscribers = []; 70 | 71 | /** 72 | * Connection constructor. 73 | * @param string $connectionId 74 | * @param int $createdAt 75 | * @param string $role 76 | * @param string $token 77 | * @param string $location 78 | * @param string $platform 79 | * @param string $serverData 80 | * @param string $clientData 81 | * @param array $publishers 82 | * @param array $subscribers 83 | */ 84 | public function __construct(string $connectionId, int $createdAt, string $role, string $token, string $location, string $platform, string $serverData, string $clientData, array $publishers, array $subscribers) 85 | { 86 | $this->connectionId = $connectionId; 87 | $this->createdAt = $createdAt; 88 | $this->role = $role; 89 | $this->token = $token; 90 | $this->location = $location; 91 | $this->platform = $platform; 92 | $this->serverData = $serverData; 93 | $this->clientData = $clientData; 94 | $this->publishers = $publishers; 95 | $this->subscribers = $subscribers; 96 | 97 | } 98 | 99 | /** 100 | * @return string 101 | */ 102 | public function getClientData(): string 103 | { 104 | return $this->clientData; 105 | } 106 | 107 | public function __toString(): string 108 | { 109 | return $this->getConnectionId(); 110 | } 111 | 112 | /** 113 | * @return string 114 | */ 115 | public function getConnectionId(): string 116 | { 117 | return $this->connectionId; 118 | } 119 | 120 | /** 121 | * Remove publishers based on streamId 122 | * @param string $streamId 123 | */ 124 | public function unpublish(string $streamId) 125 | { 126 | $this->publishers = array_filter($this->publishers, function (Publisher $publisher) use ($streamId) { 127 | return $streamId !== $publisher->getStreamId(); 128 | }); 129 | } 130 | 131 | /** 132 | * Remove subscribers based on publisher streamId 133 | * @param string $streamId 134 | */ 135 | public function unsubscribe(string $streamId) 136 | { 137 | if (!empty($this->subscribers)) { 138 | $this->subscribers = array_filter($this->subscribers, function (Subscriber $subscriber) use ($streamId) { 139 | return $subscriber->getPublisherStreamId() !== $streamId; 140 | }); 141 | } 142 | } 143 | 144 | /** 145 | * Convert the model instance to JSON. 146 | * 147 | * @param int $options 148 | * @return string 149 | * 150 | */ 151 | public function toJson($options = 0): string 152 | { 153 | $json = json_encode($this->jsonSerialize(), $options); 154 | return $json; 155 | } 156 | 157 | /** 158 | * Specify data which should be serialized to JSON 159 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 160 | * @return mixed data which can be serialized by json_encode, 161 | * which is a value of any type other than a resource. 162 | * @since 5.4.0 163 | */ 164 | public function jsonSerialize() 165 | { 166 | return $this->toArray(); 167 | } 168 | 169 | /** 170 | * Convert the model instance to an array. 171 | * 172 | * @return array 173 | */ 174 | public function toArray(): array 175 | { 176 | $array = [ 177 | 'connectionId' => $this->connectionId, 178 | 'createdAt' => $this->createdAt, 179 | 'role' => $this->role, 180 | 'token' => $this->token, 181 | 'location' => $this->location, 182 | 'platform' => $this->platform, 183 | 'serverData' => $this->serverData, 184 | 'clientData' => $this->clientData, 185 | 'subscribers' => $this->subscribers 186 | ]; 187 | foreach ($this->publishers as $publisher) { 188 | $array['publishers'][] = $publisher->toArray(); 189 | } 190 | 191 | 192 | foreach ($array as $key => $value) { 193 | if (is_null($value) || $value == '') { 194 | unset($array[$key]); 195 | } 196 | } 197 | return $array; 198 | } 199 | 200 | /** 201 | * @param string $json 202 | * @return Connection 203 | */ 204 | public function fromJson(string $json): Connection 205 | { 206 | return $this->fromArray(json_decode($json, true)); 207 | } 208 | 209 | /** 210 | * @param array $connectionArray 211 | * @return Connection 212 | */ 213 | public function fromArray(array $connectionArray): Connection 214 | { 215 | $this->connectionId = $connectionArray['connectionId']; 216 | $this->createdAt = $connectionArray['createdAt'] ?? null; 217 | $this->role = $connectionArray['role'] ?? null; 218 | $this->token = $connectionArray['token'] ?? null; 219 | $this->location = $connectionArray['location'] ?? null; 220 | $this->platform = $connectionArray['platform'] ?? null; 221 | $this->serverData = $connectionArray['serverData'] ?? null; 222 | $this->clientData = $connectionArray['clientData'] ?? null; 223 | 224 | 225 | if (array_key_exists('subscribers', $connectionArray)) { 226 | $this->subscribers = $connectionArray['subscribers']; 227 | } 228 | return $this; 229 | } 230 | 231 | /** 232 | * @return int 233 | */ 234 | public function getCreatedAt(): int 235 | { 236 | return $this->createdAt; 237 | } 238 | 239 | /** 240 | * @return string 241 | */ 242 | public function getRole(): string 243 | { 244 | return $this->role; 245 | } 246 | 247 | /** 248 | * @return string 249 | */ 250 | public function getToken(): string 251 | { 252 | return $this->token; 253 | } 254 | 255 | /** 256 | * @return string 257 | */ 258 | public function getLocation(): string 259 | { 260 | return $this->location; 261 | } 262 | 263 | /** 264 | * @return string 265 | */ 266 | public function getPlatform(): string 267 | { 268 | return $this->platform; 269 | } 270 | 271 | /** 272 | * @return string 273 | */ 274 | public function getServerData(): string 275 | { 276 | return $this->serverData; 277 | } 278 | 279 | /** 280 | * @return array 281 | */ 282 | public function getSubscribers(): array 283 | { 284 | return $this->subscribers; 285 | } 286 | 287 | /** 288 | * @return array 289 | */ 290 | public function getPublishers(): array 291 | { 292 | return $this->publishers; 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /src/Cache/SessionStore.php: -------------------------------------------------------------------------------- 1 | table = $table; 43 | $this->connection = $connection; 44 | } 45 | 46 | /** 47 | * Update an item from the cache by key. 48 | * 49 | * @param string $key 50 | * @param $value 51 | * @return mixed 52 | */ 53 | public function update($key, $value) 54 | { 55 | if ($this->table()->where('key', '=', $key)->exists()) { 56 | $value = $this->serialize($value); 57 | $this->table()->where('key', $key)->update(compact('value')); 58 | return $this->get($key); 59 | } 60 | return; 61 | } 62 | 63 | /** 64 | * Get a query builder for the cache table. 65 | * 66 | * @return Builder 67 | */ 68 | protected function table() 69 | { 70 | return $this->connection->table($this->table); 71 | } 72 | 73 | /** 74 | * Serialize the given value. 75 | * 76 | * @param mixed $value 77 | * @return string 78 | */ 79 | protected function serialize($value) 80 | { 81 | $result = serialize($value); 82 | 83 | if ($this->connection instanceof PostgresConnection && Str::contains($result, "\0")) { 84 | $result = base64_encode($result); 85 | } 86 | 87 | return $result; 88 | } 89 | 90 | /** 91 | * Retrieve an item from the cache by key. 92 | * 93 | * @param string $key 94 | * @return mixed 95 | */ 96 | public function get($key) 97 | { 98 | $cache = $this->table()->where('key', '=', $key)->first(); 99 | // If we have a cache record we will check the expiration time against current 100 | // time on the system and see if the record has expired. If it has, we will 101 | // remove the records from the database table so it isn't returned again. 102 | if (is_null($cache)) { 103 | return; 104 | } 105 | 106 | $cache = is_array($cache) ? (object) $cache : $cache; 107 | 108 | // If this cache expiration date is past the current time, we will remove this 109 | // item from the cache. Then we will return a null value since the cache is 110 | // expired. We will use "Carbon" to make this comparison with the column. 111 | if ($this->currentTime() >= $cache->expiration) { 112 | $this->forget($key); 113 | 114 | return; 115 | } 116 | 117 | return $this->unserialize($cache->value); 118 | } 119 | 120 | /** 121 | * Remove an item from the cache. 122 | * 123 | * @param string $key 124 | * @return bool 125 | */ 126 | public function forget($key) 127 | { 128 | $this->table()->where('key', '=', $key)->delete(); 129 | 130 | return true; 131 | } 132 | 133 | /** 134 | * Unserialize the given value. 135 | * 136 | * @param string $value 137 | * @return mixed 138 | */ 139 | protected function unserialize($value) 140 | { 141 | if ($this->connection instanceof PostgresConnection && !Str::contains($value, [':', ';'])) { 142 | $value = base64_decode($value); 143 | } 144 | 145 | return unserialize($value); 146 | } 147 | 148 | /** 149 | * Retrieve all items from the cache. 150 | * 151 | * @return mixed 152 | */ 153 | public function getAll() 154 | { 155 | 156 | $cache = $this->table()->get(); 157 | 158 | // If we have a cache record we will check the expiration time against current 159 | // time on the system and see if the record has expired. If it has, we will 160 | // remove the records from the database table so it isn't returned again. 161 | if (is_null($cache)) { 162 | return; 163 | } 164 | 165 | $cache = is_array($cache) ? (object) $cache : $cache; 166 | // If this cache expiration date is past the current time, we will remove this 167 | // item from the cache. Then we will return a null value since the cache is 168 | // expired. We will use "Carbon" to make this comparison with the column. 169 | $entries = []; 170 | foreach ($cache as $entry) { 171 | if ($this->currentTime() >= $entry->expiration) { 172 | $this->forget($entry->key); 173 | } else { 174 | $entries[] = $this->unserialize($entry->value); 175 | } 176 | 177 | 178 | } 179 | return $entries; 180 | } 181 | 182 | /** 183 | * Increment the value of an item in the cache. 184 | * 185 | * @param string $key 186 | * @param mixed $value 187 | * @return int|bool 188 | * @throws Throwable 189 | */ 190 | public function increment($key, $value = 1) 191 | { 192 | return $this->incrementOrDecrement($key, $value, function ($current, $value) { 193 | return $current + $value; 194 | }); 195 | } 196 | 197 | /** 198 | * Increment or decrement an item in the cache. 199 | * 200 | * @param string $key 201 | * @param mixed $value 202 | * @param Closure $callback 203 | * @return int|bool 204 | * @throws Throwable 205 | */ 206 | protected function incrementOrDecrement($key, $value, Closure $callback) 207 | { 208 | return $this->connection->transaction(function () use ($key, $value, $callback) { 209 | 210 | 211 | $cache = $this->table()->where('key', $key) 212 | ->lockForUpdate()->first(); 213 | 214 | // If there is no value in the cache, we will return false here. Otherwise the 215 | // value will be decrypted and we will proceed with this function to either 216 | // increment or decrement this value based on the given action callbacks. 217 | if (is_null($cache)) { 218 | return false; 219 | } 220 | 221 | $cache = is_array($cache) ? (object) $cache : $cache; 222 | 223 | $current = $this->unserialize($cache->value); 224 | 225 | // Here we'll call this callback function that was given to the function which 226 | // is used to either increment or decrement the function. We use a callback 227 | // so we do not have to recreate all this logic in each of the functions. 228 | $new = $callback((int) $current, $value); 229 | 230 | if (!is_numeric($current)) { 231 | return false; 232 | } 233 | 234 | // Here we will update the values in the table. We will also encrypt the value 235 | // since database cache values are encrypted by default with secure storage 236 | // that can't be easily read. We will return the new value after storing. 237 | $this->table()->where('key', $key)->update([ 238 | 'value' => $this->serialize($new), 239 | ]); 240 | 241 | return $new; 242 | }); 243 | } 244 | 245 | /** 246 | * Decrement the value of an item in the cache. 247 | * 248 | * @param string $key 249 | * @param mixed $value 250 | * @return int|bool 251 | * @throws Throwable 252 | */ 253 | public function decrement($key, $value = 1) 254 | { 255 | return $this->incrementOrDecrement($key, $value, function ($current, $value) { 256 | return $current - $value; 257 | }); 258 | } 259 | 260 | /** 261 | * Store an item in the cache indefinitely. 262 | * 263 | * @param string $key 264 | * @param mixed $value 265 | * @return bool 266 | */ 267 | public function forever($key, $value) 268 | { 269 | return $this->put($key, $value, 315360000); 270 | } 271 | 272 | /** 273 | * Store an item in the cache for a given number of seconds. 274 | * 275 | * @param string $key 276 | * @param mixed $value 277 | * @param int $seconds 278 | * @return bool 279 | */ 280 | public function put($key, $value, $seconds) 281 | { 282 | 283 | $value = $this->serialize($value); 284 | 285 | $expiration = $this->getTime() + $seconds; 286 | 287 | try { 288 | return $this->table()->insert(compact('key', 'value', 'expiration')); 289 | } catch (Exception $e) { 290 | $result = $this->table()->where('key', $key)->update(compact('value', 'expiration')); 291 | 292 | return $result > 0; 293 | } 294 | } 295 | 296 | /** 297 | * Get the current system time. 298 | * 299 | * @return int 300 | */ 301 | protected function getTime() 302 | { 303 | return $this->currentTime(); 304 | } 305 | 306 | /** 307 | * Remove all items from the cache. 308 | * 309 | * @return bool 310 | */ 311 | public function flush() 312 | { 313 | $this->table()->delete(); 314 | 315 | return true; 316 | } 317 | 318 | /** 319 | * Get the underlying database connection. 320 | * 321 | * @return ConnectionInterface 322 | */ 323 | public function getConnection() 324 | { 325 | return $this->connection; 326 | } 327 | 328 | /** 329 | * Get the cache key prefix. 330 | * 331 | * @return string 332 | */ 333 | public function getPrefix() 334 | { 335 | return ''; 336 | } 337 | 338 | /** 339 | * Retrieve multiple items from the cache by key. 340 | * 341 | * Items not found in the cache will have a null value. 342 | * 343 | * @param array $keys 344 | * @return void 345 | */ 346 | public function many(array $keys) 347 | { 348 | // TODO: Implement many() method. 349 | } 350 | 351 | /** 352 | * Store multiple items in the cache for a given number of seconds. 353 | * 354 | * @param array $values 355 | * @param int $seconds 356 | * @return void 357 | */ 358 | public function putMany(array $values, $seconds) 359 | { 360 | // TODO: Implement putMany() method. 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /src/OpenVidu.php: -------------------------------------------------------------------------------- 1 | config = $config; 46 | } 47 | 48 | /** 49 | * @param SessionProperties|null $properties 50 | * @return Session 51 | * @throws Exceptions\OpenViduException 52 | */ 53 | public function createSession(?SessionProperties $properties = null): Session 54 | { 55 | $session = new Session($this->client(), null, $properties); 56 | Cache::store('openvidu')->forever($session->getSessionId(), $session->toJson()); 57 | return $session; 58 | } 59 | 60 | /** 61 | * @return Client 62 | */ 63 | private function client(): Client 64 | { 65 | if ($this->client) { 66 | return $this->client; 67 | } 68 | 69 | $client = new Client([ 70 | 'headers' => [ 71 | 'Content-Type' => 'application/json', 72 | 'Accept' => 'application/json', 73 | ], 74 | 'auth' => [ 75 | $this->config['app'], $this->config['secret'] 76 | ], 77 | 'base_uri' => $this->config['domain'] . ':' . $this->config['port'], 78 | 'debug' => $this->config['debug'], 79 | 'http_errors' => false, 80 | 'verify' => false 81 | ]); 82 | return $client; 83 | } 84 | 85 | /** 86 | * @param Client $client 87 | */ 88 | public function setClient(Client $client) 89 | { 90 | $this->client = $client; 91 | } 92 | 93 | /** 94 | * Starts the recording of a {@see Session} 95 | * @param RecordingProperties $properties 96 | * @return Recording 97 | * @throws OpenViduException 98 | * @throws OpenViduRecordingResolutionException 99 | * @throws OpenViduServerRecordingIsDisabledException 100 | * @throws OpenViduSessionCantRecordingException 101 | * @throws OpenViduSessionHasNotConnectedParticipantsException 102 | * @throws OpenViduSessionNotFoundException 103 | * @throws InvalidArgumentException 104 | * @throws Exceptions\OpenViduInvalidArgumentException 105 | */ 106 | public function startRecording(RecordingProperties $properties): Recording 107 | { 108 | $activeSession = $this->getSession($properties->session()); 109 | if ($activeSession->isBeingRecorded()) { 110 | $lastRecordingId = $activeSession->getLastRecordingId(); 111 | if (!$lastRecordingId) { 112 | throw new OpenViduSessionCantRecordingException("The session is not configured for using media routed or has recording problems"); 113 | } 114 | return $this->getRecording($lastRecordingId); 115 | } 116 | $response = $this->client()->post(Uri::RECORDINGS_START, [ 117 | RequestOptions::JSON => $properties->toArray() ?? null 118 | ]); 119 | switch ($response->getStatusCode()) { 120 | case 200: 121 | $recording = RecordingBuilder::build(json_decode($response->getBody()->getContents(), true)); 122 | 123 | if ($activeSession != null) { 124 | $activeSession->setIsBeingRecorded(true); 125 | $activeSession->setLastRecordingId($recording->getId()); 126 | } 127 | return $recording; 128 | case 404: 129 | throw new OpenViduSessionNotFoundException(); 130 | case 406: 131 | throw new OpenViduSessionHasNotConnectedParticipantsException(); 132 | case 409: 133 | throw new OpenViduSessionCantRecordingException("The session is not configured for using media routed or it is already being recorded"); 134 | case 422: 135 | throw new OpenViduRecordingResolutionException(); 136 | case 501: 137 | throw new OpenViduServerRecordingIsDisabledException(); 138 | default: 139 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 140 | } 141 | } 142 | 143 | /** 144 | * Gets an existing {@see Session} 145 | * @param string $sessionId 146 | * @return Session 147 | * @throws OpenViduException 148 | * @throws OpenViduSessionNotFoundException 149 | * @throws InvalidArgumentException 150 | */ 151 | public function getSession(string $sessionId): Session 152 | { 153 | if (Cache::store('openvidu')->has($sessionId)) { 154 | return (new Session($this->client(), $sessionId))->fromJson(Cache::store('openvidu')->get($sessionId)); 155 | } 156 | throw new OpenViduSessionNotFoundException(); 157 | } 158 | 159 | /** 160 | * Gets an existing {@see Recording} 161 | * @param string $recordingId The `id` property of the {@see Recording} you want to retrieve 162 | * @return Recording 163 | * @throws Exceptions\OpenViduInvalidArgumentException 164 | * @throws OpenViduException 165 | * @throws OpenViduRecordingNotFoundException 166 | */ 167 | public function getRecording(string $recordingId): Recording 168 | { 169 | $response = $this->client()->get(Uri::RECORDINGS_URI . '/' . $recordingId); 170 | switch ($response->getStatusCode()) { 171 | case 200: 172 | return RecordingBuilder::build(json_decode($response->getBody()->getContents(), true)); 173 | case 404: 174 | throw new OpenViduRecordingNotFoundException(); 175 | default: 176 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 177 | } 178 | } 179 | 180 | /** 181 | * Check if exists {@see Session} 182 | * @param string $sessionId 183 | * @return bool 184 | * @throws InvalidArgumentException 185 | */ 186 | public function existsSession(string $sessionId): bool 187 | { 188 | return Cache::store('openvidu')->has($sessionId); 189 | } 190 | 191 | /** 192 | * Stops the recording of a {@see Session} 193 | * @param string $recordingId The `id` property of the {@see Recording} you want to stop 194 | * @return Recording 195 | * @throws OpenViduException 196 | * @throws OpenViduRecordingNotFoundException 197 | * @throws OpenViduRecordingStatusException 198 | * @throws OpenViduSessionNotFoundException 199 | * @throws InvalidArgumentException 200 | * @throws Exceptions\OpenViduInvalidArgumentException 201 | */ 202 | public function stopRecording(string $recordingId): Recording 203 | { 204 | $response = $this->client()->post(Uri::RECORDINGS_STOP . '/' . $recordingId); 205 | switch ($response->getStatusCode()) { 206 | case 200: 207 | $recording = RecordingBuilder::build(json_decode($response->getBody()->getContents(), true)); 208 | $activeSession = $this->getSession($recording->getSessionId()); 209 | if ($activeSession != null) { 210 | $activeSession->setIsBeingRecorded(false); 211 | $activeSession->setLastRecordingId($recordingId); 212 | } 213 | return $recording; 214 | case 404: 215 | throw new OpenViduRecordingNotFoundException(); 216 | case 406: 217 | throw new OpenViduRecordingStatusException("The recording has `starting` status. Wait until `started` status before stopping the recording."); 218 | default: 219 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 220 | } 221 | } 222 | 223 | /** 224 | * Gets an array with all existing recordings 225 | * @return array 226 | * @throws OpenViduException 227 | * @throws Exceptions\OpenViduInvalidArgumentException 228 | */ 229 | public function getRecordings(): array 230 | { 231 | $recordings = []; 232 | $response = $this->client()->get(Uri::RECORDINGS_URI); 233 | switch ($response->getStatusCode()) { 234 | case 200: 235 | $items = json_decode($response->getBody()->getContents(), true); 236 | foreach ($items as $item) { 237 | $recordings[] = RecordingBuilder::build($item); 238 | } 239 | return $recordings; 240 | default: 241 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 242 | } 243 | } 244 | 245 | 246 | /** 247 | * Deletes a {@see Recording}. The recording must have status `stopped`, `ready` or `failed` 248 | * @param string $recordingId The `id` property of the {@see Recording} you want to delete 249 | * @return bool 250 | * @throws OpenViduException 251 | * @throws OpenViduRecordingNotFoundException 252 | * @throws OpenViduRecordingStatusException 253 | */ 254 | public function deleteRecording(string $recordingId): bool 255 | { 256 | $response = $this->client()->delete(Uri::RECORDINGS_URI . '/' . $recordingId); 257 | 258 | switch ($response->getStatusCode()) { 259 | case 200: 260 | return true; 261 | case 404: 262 | throw new OpenViduRecordingNotFoundException(); 263 | break; 264 | case 409: 265 | throw new OpenViduRecordingStatusException("The recording has `started` status. Stop it before deletion."); 266 | break; 267 | default: 268 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 269 | } 270 | } 271 | 272 | /** 273 | * Returns the list of active sessions. This value will remain unchanged 274 | * since the last time method {@link SquareetLabs\LaravelOpenVidu#fetch()} 275 | * was called. Exceptions to this rule are: 276 | * 292 | *
293 | * To get the list of active sessions with their current actual value, you must 294 | * call first {@see OpenVidu::fetch()} and then 295 | * {@see OpenVidu::getActiveSessions()} 296 | * @throws OpenViduException 297 | */ 298 | public function getActiveSessions(): array 299 | { 300 | try { 301 | return Cache::store('openvidu')->getAll(); 302 | } catch (Exception $e) { 303 | throw new OpenViduException("Make sure you have correctly configured the openvidu cache driver.", 500); 304 | } 305 | } 306 | 307 | /** 308 | * Sends signal to session with given SignalProperties 309 | * @param SignalProperties $properties 310 | * @return bool 311 | * @throws OpenViduException 312 | * @throws OpenViduProblemWithBodyParameterException 313 | * @throws OpenViduSessionHasNotConnectedParticipantsException 314 | * @throws OpenViduSessionNotFoundException 315 | */ 316 | public function sendSignal(SignalProperties $properties): bool 317 | { 318 | $response = $this->client()->post(Uri::SIGNAL_URI, [ 319 | RequestOptions::JSON => $properties->toArray() ?? null 320 | ]); 321 | switch ($response->getStatusCode()) { 322 | case 200: 323 | return true; 324 | case 400: 325 | throw new OpenViduProblemWithBodyParameterException(); 326 | case 404: 327 | throw new OpenViduSessionNotFoundException(); 328 | case 406: 329 | throw new OpenViduSessionHasNotConnectedParticipantsException(); 330 | default: 331 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 332 | } 333 | } 334 | } 335 | 336 | -------------------------------------------------------------------------------- /src/Session.php: -------------------------------------------------------------------------------- 1 | client = $client; 64 | if (!$sessionId) { 65 | $this->properties = $properties ? $properties : new SessionProperties(MediaMode::ROUTED, RecordingMode::MANUAL, OutputMode::COMPOSED, RecordingLayout::BEST_FIT); 66 | $this->sessionId = $this->getSessionId(); 67 | } 68 | } 69 | 70 | /** 71 | * @return string 72 | * @throws OpenViduException 73 | */ 74 | public function getSessionId() 75 | { 76 | if (empty($this->sessionId)) { 77 | $response = $this->client->post(Uri::SESSION_URI, [ 78 | RequestOptions::JSON => $this->properties->toArray() 79 | ]); 80 | switch ($response->getStatusCode()) { 81 | case 200: 82 | return json_decode($response->getBody()->getContents())->id; 83 | case 400: 84 | throw new OpenViduProblemWithBodyParameterException(); 85 | case 409: 86 | return $this->properties->getCustomSessionId(); 87 | default: 88 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 89 | } 90 | } else { 91 | return $this->sessionId; 92 | } 93 | } 94 | 95 | /** 96 | ** Gets a new token associated to Session object with default values for 97 | * {@see TokenOptions}. This always translates into a 98 | * new request to OpenVidu Server 99 | * 100 | * @param TokenOptions|null $tokenOptions 101 | * @return string The generated token 102 | * @throws OpenViduException 103 | */ 104 | public function generateToken(?TokenOptions $tokenOptions = null) 105 | { 106 | $this->getSessionId(); 107 | try { 108 | if (!$tokenOptions) { 109 | $tokenOptions = new TokenOptions(OpenViduRole::PUBLISHER); 110 | } 111 | $response = $this->client->post(Uri::TOKEN_URI, [ 112 | RequestOptions::JSON => array_merge($tokenOptions->toArray(), ['session' => $this->sessionId]) 113 | ]); 114 | switch ($response->getStatusCode()) { 115 | case 200: 116 | return json_decode($response->getBody()->getContents()); 117 | case 400: 118 | throw new OpenViduProblemWithBodyParameterException(); 119 | case 404: 120 | throw new OpenViduSessionNotFoundException(); 121 | default: 122 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 123 | } 124 | } catch (Exception $e) { 125 | throw new OpenViduTokenCantCreateException($e->getMessage(), $e); 126 | } 127 | } 128 | 129 | /** 130 | * Gracefully closes the Session: unpublishes all streams and evicts every 131 | * participant 132 | * @throws OpenViduException 133 | */ 134 | public function close() 135 | { 136 | $response = $this->client->delete(Uri::SESSION_URI . '/' . $this->sessionId); 137 | switch ($response->getStatusCode()) { 138 | case 204: 139 | Cache::store('openvidu')->forget($this->sessionId); 140 | return true; 141 | case 404: 142 | throw new OpenViduSessionNotFoundException(); 143 | default: 144 | throw new OpenViduException("Invalid response status code ".$response->getStatusCode(), $response->getStatusCode()); 145 | } 146 | } 147 | 148 | /** 149 | * Updates every property of the Session with the current status it has in 150 | * OpenVidu Server. This is especially useful for getting the list of active 151 | * connections to the Session 152 | * ({@see getActiveConnections()}) and use 153 | * those values to call 154 | * {@see forceDisconnect(Connection)} or 155 | * {@link forceUnpublish(Publisher)}.
156 | * 157 | * To update every Session object owned by OpenVidu object, call 158 | * {@see fetch()} 159 | * 160 | * @return bool true if the Session status has changed with respect to the server, 161 | * false if not. This applies to any property or sub-property of the object 162 | */ 163 | 164 | public function fetch() 165 | { 166 | $response = $this->client->get(Uri::SESSION_URI . '/' . $this->sessionId, [ 167 | 'headers' => [ 168 | 'Content-Type' => 'application/x-www-form-urlencoded', 169 | 'Accept' => 'application/json', 170 | ] 171 | ]); 172 | if ($response->getStatusCode() === 200) { 173 | $beforeJSON = $this->toJson(); 174 | $this->fromJson($response->getBody()->getContents()); 175 | $afterJSON = $this->toJson(); 176 | if ($beforeJSON !== $afterJSON) { 177 | Cache::store('openvidu')->update($this->sessionId, $this->toJson()); 178 | return true; 179 | } 180 | } 181 | return false; 182 | } 183 | 184 | /** 185 | * Convert the model instance to JSON. 186 | * 187 | * @param int $options 188 | * @return string 189 | * 190 | */ 191 | public function toJson($options = 0): string 192 | { 193 | $json = json_encode($this->jsonSerialize(), $options); 194 | return $json; 195 | } 196 | 197 | /** 198 | * Specify data which should be serialized to JSON 199 | * @link https://php.net/manual/en/jsonserializable.jsonserialize.php 200 | * @return mixed data which can be serialized by json_encode, 201 | * which is a value of any type other than a resource. 202 | * @since 5.4.0 203 | */ 204 | public function jsonSerialize() 205 | { 206 | return $this->toArray(); 207 | } 208 | 209 | /** 210 | * Convert the model instance to an array. 211 | * 212 | * @return array 213 | */ 214 | public function toArray(): array 215 | { 216 | $array = ['sessionId' => $this->sessionId, 'properties' => $this->properties->toArray(), 'recording' => $this->recording, 'createdAt' => $this->createdAt]; 217 | foreach ($this->activeConnections as $connection) { 218 | $array['activeConnections'][] = $connection->toArray(); 219 | } 220 | 221 | foreach ($array as $key => $value) { 222 | if (is_null($value) || $value == '') { 223 | unset($array[$key]); 224 | } 225 | } 226 | return $array; 227 | } 228 | 229 | /** 230 | * @param string $json 231 | * @return Session 232 | */ 233 | public function fromJson(string $json): Session 234 | { 235 | return $this->fromArray(json_decode($json, true)); 236 | } 237 | 238 | /** 239 | * @param array $sessionArray 240 | * @return Session 241 | */ 242 | public function fromArray(array $sessionArray): Session 243 | { 244 | $this->sessionId = $sessionArray['sessionId']; 245 | $this->createdAt = $sessionArray['createdAt'] ?? null; 246 | $this->recording = $sessionArray['recording'] ?? null; 247 | 248 | if (array_key_exists('properties', $sessionArray)) { 249 | $this->properties = SessionPropertiesBuilder::build($sessionArray['properties']); 250 | } 251 | 252 | $this->activeConnections = []; 253 | if (array_key_exists('connections', $sessionArray)) { 254 | foreach ($sessionArray['connections']['content'] as $connection) { 255 | $publishers = []; 256 | $ensure = $connection['content'] ?? $connection; 257 | foreach ($ensure['publishers'] as $publisher) { 258 | $publishers[] = PublisherBuilder::build($publisher); 259 | } 260 | $subscribers = []; 261 | 262 | foreach ($ensure['subscribers'] as $subscriber) { 263 | $subscribers[] = SubscriberBuilder::build($subscriber); 264 | } 265 | $this->activeConnections[] = ConnectionBuilder::build($ensure, $publishers, $subscribers); 266 | } 267 | } 268 | return $this; 269 | } 270 | 271 | /** 272 | * Forces the user with Connection `connectionId` to leave the session. OpenVidu Browser will trigger the proper events on the client-side 273 | * (`streamDestroyed`, `connectionDestroyed`, `sessionDisconnected`) with reason set to `"forceDisconnectByServer"` 274 | * 275 | * 276 | * @param string $connectionId 277 | * @throws OpenViduException 278 | */ 279 | public function forceDisconnect(string $connectionId) 280 | { 281 | $response = $this->client->delete(Uri::SESSION_URI . '/' . $this->sessionId . '/connection/' . $connectionId, [ 282 | 'headers' => [ 283 | 'Content-Type' => 'application/x-www-form-urlencoded', 284 | 'Accept' => 'application/json', 285 | ] 286 | ]); 287 | switch ($response->getStatusCode()) { 288 | case 204: 289 | $this->leaveSession($connectionId); 290 | Cache::store('openvidu')->update($this->sessionId, $this->toJson()); 291 | break; 292 | case 400: 293 | throw new OpenViduSessionNotFoundException(); 294 | case 404: 295 | throw new OpenViduConnectionNotFoundException(); 296 | default: 297 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 298 | } 299 | } 300 | 301 | /** 302 | * Get `connection` parameter from activeConnections array {@see Connection::getConnectionId()} for getting each `connectionId` property). 303 | * Remember to call {@see fetch()} before to fetch the current actual properties of the Session from OpenVidu Server 304 | * @param string $connectionId 305 | */ 306 | 307 | private function leaveSession(string $connectionId) 308 | { 309 | $connectionClosed = null; 310 | $this->activeConnections = array_filter($this->activeConnections, function (Connection $connection) use (&$connectionClosed, $connectionId) { 311 | if ($connection->getConnectionId() !== $connectionId) { 312 | return true; 313 | } 314 | $connectionClosed = $connection; 315 | return false; 316 | }); 317 | if ($connectionClosed != null) { 318 | foreach ($connectionClosed->getPublishers() as $publisher) { 319 | foreach ($this->activeConnections as $con) { 320 | $con->unsubscribe($publisher->getStreamId()); 321 | } 322 | } 323 | } 324 | } 325 | 326 | 327 | /** 328 | * Allows publish a Stream (For now can only be IPCAM). 329 | * Remember to call 330 | * {@see fetch()} before to fetch the current 331 | * actual properties of the Session from OpenVidu Server 332 | * 333 | * @param IPCameraOptions $IPCameraOptions 334 | * @return Connection 335 | * @throws OpenViduException 336 | * @throws OpenViduSessionNotFoundException 337 | */ 338 | public function publish(IPCameraOptions $IPCameraOptions) 339 | { 340 | $response = $this->client->post(Uri::SESSION_URI . '/' . $this->sessionId . '/connection', [ 341 | RequestOptions::JSON => array_merge($IPCameraOptions->toArray()) 342 | ]); 343 | switch ($response->getStatusCode()) { 344 | case 200: 345 | return json_decode($response->getBody()->getContents()); 346 | case 400: 347 | throw new OpenViduProblemWithBodyParameterException(); 348 | case 404: 349 | throw new OpenViduSessionNotFoundException(); 350 | default: 351 | throw new OpenViduException("Unexpected error when publishing the IP camera stream into the session."); 352 | } 353 | } 354 | 355 | /** 356 | * Forces some user to unpublish a Stream. OpenVidu Browser will trigger the 357 | * proper events on the client-side (streamDestroyed) with reason 358 | * set to "forceUnpublishByServer".
359 | * 360 | * You can get streamId parameter with 361 | * {@see Session::getActiveConnections()} and then for 362 | * each Connection you can call 363 | * {@see Connection::getPublishers()}. Finally 364 | * {@see Publisher::getStreamId()}) will give you the 365 | * streamId. Remember to call 366 | * {@see fetch()} before to fetch the current 367 | * actual properties of the Session from OpenVidu Server 368 | * 369 | * @param string $streamId 370 | * @return void 371 | * @throws OpenViduConnectionNotFoundException 372 | * @throws OpenViduException 373 | * @throws OpenViduSessionNotFoundException 374 | */ 375 | public function forceUnpublish(string $streamId) 376 | { 377 | $response = $this->client->delete(Uri::SESSION_URI . '/' . $this->sessionId . '/stream/' . $streamId, [ 378 | 'headers' => [ 379 | 'Content-Type' => 'application/x-www-form-urlencoded', 380 | 'Accept' => 'application/json', 381 | ] 382 | ]); 383 | switch ($response->getStatusCode()) { 384 | case 204: 385 | foreach ($this->activeConnections as $connection) { 386 | $connection->unpublish($streamId); 387 | $connection->unsubscribe($streamId); 388 | } 389 | Cache::store('openvidu')->update($this->sessionId, $this->toJson()); 390 | break; 391 | case 400: 392 | throw new OpenViduSessionNotFoundException(); 393 | case 404: 394 | throw new OpenViduConnectionNotFoundException(); 395 | case 405: 396 | throw new OpenViduStreamCantCloseException("You cannot directly delete the stream of an IPCAM participant"); 397 | default: 398 | throw new OpenViduException("Invalid response status code " . $response->getStatusCode(), $response->getStatusCode()); 399 | } 400 | } 401 | 402 | /** 403 | * Returns the list of active connections to the session. This value 404 | * will remain unchanged since the last time method 405 | * {@see fetch()} was called. 406 | * Exceptions to this rule are: 407 | * 413 | *
414 | * To get the list of active connections with their current actual value, you 415 | * must call first {@see Session::fetch()} and then 416 | * {@see Session::getActiveConnections()} 417 | */ 418 | public function getActiveConnections(): array 419 | { 420 | return $this->activeConnections; 421 | } 422 | 423 | /** 424 | * Returns whether the session is being recorded or not 425 | */ 426 | public function isBeingRecorded(): bool 427 | { 428 | return !!$this->recording; 429 | } 430 | 431 | /** 432 | * Set value 433 | * @param bool $recording 434 | */ 435 | public function setIsBeingRecorded(bool $recording) 436 | { 437 | $this->recording = $recording; 438 | Cache::store('openvidu')->update($this->sessionId, $this->toJson()); 439 | } 440 | 441 | public function getLastRecordingId() 442 | { 443 | return $this->lastRecordingId; 444 | } 445 | 446 | public function setLastRecordingId(string $lastRecordingId) 447 | { 448 | $this->lastRecordingId = $lastRecordingId; 449 | Cache::store('openvidu')->update($this->sessionId, $this->toJson()); 450 | } 451 | 452 | /** 453 | * @return string 454 | * @throws OpenViduException 455 | */ 456 | public function __toString(): string 457 | { 458 | return $this->getSessionId(); 459 | } 460 | } 461 | --------------------------------------------------------------------------------