VideohatiDocs
Guides

Guide: Integrate Videohati into a Laravel 11 project

Install the videohati/laravel package, configure your key, upload a video, create a playback session, and embed the player in a Blade view.

This guide wires the official Laravel SDK into a Laravel 11 app. You will upload a video from the server, create a playback session, and render the player with the bundled Blade directive.

Before you start

You need:

  • A Laravel 11 app running on PHP 8.2 or newer.
  • A project API key in test mode (vh_test_...).
  • Your project id (used by the player embed).

1. Install the package

composer require videohati/laravel

The package auto-discovers its service provider and the Videohati facade — no manual registration is needed.

2. Configure your environment

Add your credentials to .env:

VIDEOHATI_API_KEY=vh_test_xxxxxxxxxxxxxxxxxxxxx
VIDEOHATI_PROJECT_ID=01JZ9WV3N8GQ5T2M7K4C6XBARP

Optionally publish the config file to tune the base URL, player URL, or timeout:

php artisan vendor:publish --tag=videohati-config

Keep VIDEOHATI_API_KEY out of version control. The key is project-scoped and grants write access.

3. Upload a video

videos()->upload() runs the full multipart flow: create the video, open the upload session, PUT each part to the upload endpoint, and complete the upload. It returns the completion payload, including the videoId.

use Videohati\Laravel\Facades\Videohati;

$result = Videohati::videos()->upload(
    storage_path('app/lectures/lecture-01.mp4'),
    onProgress: function (int $uploaded, int $total) {
        logger()->info("Uploaded {$uploaded} / {$total} bytes");
    },
);

$videoId = $result['videoId'];

Prefer manual control? The same flow is available as videos()->create(), videos()->startUpload(), the per-part PUT requests, and videos()->completeUpload().

4. Wait until the video is ready

Encoding runs after the upload completes. Poll with videos()->get() and check the DTO's state until it is ready:

use Videohati\Laravel\Facades\Videohati;

do {
    sleep(3);
    $video = Videohati::videos()->get($videoId);
} while (!in_array($video->state, ['ready', 'failed'], true));

abort_if($video->state === 'failed', 422, 'Encoding failed');

5. Create a playback session

Create the session on the server, then pass only the sessionToken to the view — never the API key.

use Videohati\Laravel\Facades\Videohati;

$session = Videohati::playback()->createSession(
    videoId: $videoId,
    viewerDisplayText: auth()->user()->email, // shown in the watermark
);

return view('watch', [
    'videoId' => $videoId,
    'sessionToken' => $session->sessionToken,
]);

The returned PlaybackSessionDto exposes sessionId, manifestUrl, sessionToken, watermarkToken, expiresAt, and heartbeatIntervalSeconds.

6. Embed the player in a Blade view

The package ships a @videohatiPlayer Blade directive that emits the player <script> plus its mount <div>. The projectId defaults to VIDEOHATI_PROJECT_ID.

{{-- resources/views/watch.blade.php --}}
<!doctype html>
<html lang="en" dir="ltr">
  <body>
    @videohatiPlayer([
        'videoId' => $videoId,
        'sessionToken' => $sessionToken,
        'lang' => 'en',
        'autoplay' => 'muted',
    ])
  </body>
</html>

For Arabic, set 'lang' => 'ar' and dir="rtl" on <html>:

<html lang="ar" dir="rtl">
  <body>
    @videohatiPlayer([
        'videoId' => $videoId,
        'sessionToken' => $sessionToken,
        'lang' => 'ar',
    ])
  </body>
</html>

That is the full path: upload on the server, mint a session, and embed the player — all without exposing your API key to the browser.