cranbri/livepeer-laravel

Laravel integration for Livepeer Studio API

dev-main 2025-05-06 07:15 UTC

This package is auto-updated.

Last update: 2025-05-06 07:19:29 UTC


README

Latest Version on Packagist Total Downloads License

A Laravel integration for the Livepeer Studio API. This package provides a convenient way to integrate Livepeer's video streaming and processing services into your Laravel application, including webhook handling.

Table of Contents

Installation

You can install the package via composer:

composer require cranbri/livepeer-laravel

The package will automatically register the service provider and facade.

Configuration

Publish the configuration file:

php artisan vendor:publish --provider="Cranbri\Laravel\Livepeer\LivepeerServiceProvider" --tag="livepeer-config"

Add your Livepeer API key to your .env file:

LIVEPEER_API_KEY=your-api-key

If you plan to use webhooks, also add a webhook signing secret:

LIVEPEER_WEBHOOK_SECRET=your-webhook-signing-secret

Usage

Basic Usage

This package provides a Facade for easy access to the Livepeer API:

use Cranbri\Laravel\Livepeer\Facades\Livepeer;

// List all assets
$assets = Livepeer::listAssets();

// Get a specific asset
$asset = Livepeer::getAsset('asset-id');

You can also inject the Livepeer client directly:

use Cranbri\Livepeer\Livepeer;

class VideoController extends Controller
{
    public function index(Livepeer $livepeer)
    {
        $assets = $livepeer->listAssets();
        
        return view('videos.index', compact('assets'));
    }
}

Working with Assets

Upload an asset from a URL:

use Cranbri\Livepeer\Data\Asset\UrlUploadAssetData;
use Cranbri\Livepeer\Data\PlaybackPolicyData;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

$data = new UrlUploadAssetData(
    name: 'My Video',
    url: 'https://example.com/video.mp4',
    playbackPolicy: PlaybackPolicyData::public()
);

$response = Livepeer::uploadAssetFromUrl($data);

Request an upload URL for direct upload:

use Cranbri\Livepeer\Data\Asset\UploadAssetData;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

$data = new UploadAssetData(
    name: 'My Video',
    staticMp4: true
);

$response = Livepeer::requestAssetUpload($data);

// The response contains the upload URL and asset details
$uploadUrl = $response['url'];
$assetId = $response['asset']['id'];

Update an asset:

use Cranbri\Livepeer\Data\Asset\UpdateAssetData;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

$data = new UpdateAssetData(name: 'Updated Video Name');
$response = Livepeer::updateAsset('asset-id', $data);

Delete an asset:

$response = Livepeer::deleteAsset('asset-id');

Working with Livestreams

Create a new livestream:

use Cranbri\Livepeer\Data\Livestream\CreateLivestreamData;
use Cranbri\Livepeer\Data\PlaybackPolicyData;
use Cranbri\Livepeer\Data\StreamProfileData;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

$data = new CreateLivestreamData(
    name: 'My Livestream',
    playbackPolicy: PlaybackPolicyData::public(),
    profiles: [
        StreamProfileData::hd720(),
        StreamProfileData::sd480()
    ],
    record: true
);

$response = Livepeer::createLivestream($data);

// The response contains stream details
$streamId = $response['id'];
$streamKey = $response['streamKey'];
$playbackId = $response['playbackId'];

List all livestreams:

$livestreams = Livepeer::listLivestreams();

// With filters
$activeStreams = Livepeer::listLivestreams([
    'streamsonly' => true,
    'filters' => ['active']
]);

Update a livestream:

use Cranbri\Livepeer\Data\Livestream\UpdateLivestreamData;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

$data = new UpdateLivestreamData(
    name: 'Updated Stream Name',
    record: true
);

$response = Livepeer::updateLivestream('stream-id', $data);

Terminate a livestream:

$response = Livepeer::terminateLivestream('stream-id');

Create a clip from a livestream:

use Cranbri\Livepeer\Data\Livestream\CreateClipData;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

$data = new CreateClipData(
    playbackId: 'playback-id',
    startTime: 60000,  // in milliseconds
    endTime: 120000,   // in milliseconds
    name: 'My Clip'
);

$response = Livepeer::createClip($data);

Working with Multistreaming

Create a multistream target:

use Cranbri\Livepeer\Data\Multistream\CreateTargetData;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

$data = new CreateTargetData(
    url: 'rtmp://example.com/live',
    name: 'YouTube Target'
);

$response = Livepeer::createMultistreamTarget($data);

Add a multistream target to a livestream:

use Cranbri\Livepeer\Data\AddMultistreamTargetData;
use Cranbri\Livepeer\Data\Livestream\CreateMultistreamTargetData;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

// Use an existing target
$data = new AddMultistreamTargetData(
    profile: 'source',
    id: 'target-id'
);

// Or create a new target inline
$data = new AddMultistreamTargetData(
    profile: 'source',
    spec: new CreateMultistreamTargetData(
        url: 'rtmp://example.com/live',
        name: 'Facebook Target'
    )
);

$response = Livepeer::addMultistreamTarget('stream-id', $data);

Remove a multistream target:

$response = Livepeer::removeMultistreamTarget('stream-id', 'target-id');

Working with Sessions and Playback

Get session details:

$session = Livepeer::getSession('session-id');

List all sessions:

$sessions = Livepeer::listSessions();

List recorded sessions for a stream:

$recordedSessions = Livepeer::listRecordedSessions('stream-id');

Get playback information:

$playbackInfo = Livepeer::getPlaybackInfo('playback-id');

Working with Webhooks

Register a webhook endpoint in your routes:

// routes/web.php or routes/api.php
Route::livepeerWebhooks('webhooks/livepeer');

Create a webhook in Livepeer pointing to your endpoint:

use Cranbri\Livepeer\Data\Webhook\CreateWebhookData;
use Cranbri\Livepeer\Enums\WebhookEvent;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

$data = new CreateWebhookData(
    name: 'My Webhook',
    url: 'https://example.com/webhooks/livepeer',
    events: [
        WebhookEvent::STREAM_STARTED,
        WebhookEvent::STREAM_IDLE,
        WebhookEvent::RECORDING_READY
    ]
);

$response = Livepeer::createWebhook($data);

Update a webhook:

use Cranbri\Livepeer\Data\Webhook\UpdateWebhookData;
use Cranbri\Livepeer\Enums\WebhookEvent;

$data = new UpdateWebhookData(
    name: 'Updated Webhook',
    url: 'https://example.com/webhooks/livepeer',
    events: [
        WebhookEvent::STREAM_STARTED,
        WebhookEvent::STREAM_IDLE,
        WebhookEvent::RECORDING_READY,
        WebhookEvent::ASSET_READY
    ]
);

$response = Livepeer::updateWebhook('webhook-id', $data);

List all webhooks:

$webhooks = Livepeer::listWebhooks();

Delete a webhook:

$response = Livepeer::deleteWebhook('webhook-id');

Working with Access Control

Create a signing key:

$key = Livepeer::createSigningKey();

List signing keys:

$keys = Livepeer::listSigningKeys();

Update a signing key:

use Cranbri\Livepeer\Data\AccessControl\UpdateSigningKeyData;

$data = new UpdateSigningKeyData(
    name: 'Updated Key',
    disabled: false
);

$response = Livepeer::updateSigningKey('key-id', $data);

Working with Analytics

Query realtime viewership:

$viewers = Livepeer::queryRealtimeViewership([
    'playbackId' => 'playback-id',
    'breakdownBy' => 'country'
]);

Query viewership metrics:

$viewershipMetrics = Livepeer::queryViewershipMetrics([
    'fromTime' => '2024-01-01T00:00:00Z',
    'toTime' => '2024-01-31T23:59:59Z',
    'playbackId' => 'playback-id',
    'breakdownBy' => 'browser'
]);

Query usage metrics:

$usageMetrics = Livepeer::queryUsageMetrics([
    'fromTime' => '2024-01-01T00:00:00Z',
    'toTime' => '2024-01-31T23:59:59Z',
    'timeStep' => '1d'
]);

Webhook Jobs

This package includes a convenient command to generate job classes for handling Livepeer webhook events.

Generating Webhook Job Classes

To generate job classes for handling Livepeer webhook events, run:

php artisan livepeer:webhook-jobs

This will prompt you to select which webhook events you want to generate job classes for. You can select multiple events by providing a comma-separated list of numbers.

To generate job classes for all webhook events:

php artisan livepeer:webhook-jobs --all

By default, the job classes will be created in the app/Jobs/Livepeer directory. You can specify a custom path using the --path option:

php artisan livepeer:webhook-jobs --path=app/Jobs/Custom/Path

You can also specify a custom namespace for the job classes:

php artisan livepeer:webhook-jobs --namespace="App\\Jobs\\CustomNamespace"

Automatic Config Updates

The command can automatically update your config/livepeer.php file to register the generated job classes:

php artisan livepeer:webhook-jobs --auto-update-config

This will add or update the webhook_jobs array in your config file with the appropriate class mappings.

You can combine multiple options:

php artisan livepeer:webhook-jobs --all --auto-update-config --path=app/Jobs/Custom

If you don't use the --auto-update-config flag, the command will ask if you want to update the config file automatically after generating the job classes.

Available Webhook Events

Livepeer supports the following webhook events:

  • stream.started - Fired when a livestream starts
  • stream.idle - Fired when a livestream becomes idle
  • recording.ready - Fired when a recording is ready
  • recording.started - Fired when a recording starts
  • recording.waiting - Fired when a recording is waiting
  • multistream.connected - Fired when a multistream target connects
  • multistream.error - Fired when there's an error with a multistream target
  • multistream.disconnected - Fired when a multistream target disconnects
  • playback.accessControl - Fired for playback access control events
  • asset.created - Fired when an asset is created
  • asset.updated - Fired when an asset is updated
  • asset.failed - Fired when asset processing fails
  • asset.ready - Fired when an asset is ready
  • asset.deleted - Fired when an asset is deleted
  • task.spawned - Fired when a task is spawned
  • task.updated - Fired when a task is updated
  • task.completed - Fired when a task is completed
  • task.failed - Fired when a task fails

Advanced Usage

Stream Profiles

Livepeer allows you to specify transcoding profiles for your streams:

use Cranbri\Livepeer\Data\StreamProfileData;
use Cranbri\Livepeer\Enums\EncoderType;

// Use predefined profiles
$profiles = [
    StreamProfileData::hd720(),
    StreamProfileData::sd480(),
    StreamProfileData::hd1080(),
    StreamProfileData::uhd4k()
];

// Or create custom profiles
$customProfile = new StreamProfileData(
    bitrate: 2500000,
    name: 'custom-720p',
    width: 1280,
    height: 720,
    fps: 30,
    encoder: EncoderType::H264
);

Playback Policies

Control who can access your content with playback policies:

use Cranbri\Livepeer\Data\PlaybackPolicyData;
use Cranbri\Livepeer\Enums\PlaybackPolicyType;

// Public playback (default)
$publicPolicy = PlaybackPolicyData::public();

// JWT playback (requires signing key)
$jwtPolicy = PlaybackPolicyData::jwt();

// Webhook playback
$webhookPolicy = PlaybackPolicyData::webhook(
    webhookId: 'webhook-id',
    webhookContext: ['user' => 'user-123']
);

// With custom allowed origins
$customPolicy = new PlaybackPolicyData(
    type: PlaybackPolicyType::PUBLIC,
    allowedOrigins: ['https://example.com', 'https://app.example.com']
);

Error Handling

All API errors are converted to LivepeerException instances:

use Cranbri\Livepeer\Exceptions\LivepeerException;
use Cranbri\Laravel\Livepeer\Facades\Livepeer;

try {
    $asset = Livepeer::getAsset('invalid-asset-id');
} catch (LivepeerException $e) {
    report($e);
    
    return back()->withError('Unable to retrieve asset: ' . $e->getMessage());
}

For webhook errors, the package includes a WebhookFailed exception:

use Cranbri\Laravel\Livepeer\Exceptions\WebhookFailed;

try {
    // Process webhook
} catch (WebhookFailed $e) {
    report($e);
    
    return response()->json(['error' => $e->getMessage()], 400);
}

Testing

composer test

Credits and Acknowledgements

Webhook Implementation

The webhook handling functionality in this package is heavily inspired by Spatie's Laravel Stripe Webhooks package. We've adapted their excellent approach specifically for Livepeer webhooks, building on their proven architecture for secure and reliable webhook processing.

Key features adapted from Spatie's Stripe webhook implementation include:

  • Secure webhook signature validation
  • Queued webhook processing
  • Webhook storage and retry functionality
  • Job-based architecture for processing webhook events

Our implementation uses Spatie's Laravel Webhook Client as its foundation, which is the same underlying library that powers their Stripe webhooks package.

We highly recommend checking out Spatie's other Laravel packages at spatie.be/open-source.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email security@cranbri.agency instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.