Skip to content

Stream API

Bunny Stream was designed for developers to easily upload, process, and display videos in any type of use-case.

Setup

<?php

require 'vendor/autoload.php';

use ToshY\BunnyNet\Client\BunnyClient;
use ToshY\BunnyNet\StreamAPI;

$bunnyClient = new BunnyClient(
    client: new \Symfony\Component\HttpClient\Psr18Client()
);

// Provide the specific video library API key.
$streamApi = new StreamAPI(
    apiKey: '710d5fb6-d923-43d6-87f8-ea65c09e76dc',
    client: $bunnyClient
);

Usage

Manage Collections

Get Collection

$streamApi->getCollection(
    libraryId: 1,
    collectionId: '97f20caa-649b-4302-9f6e-1d286e0da144',
    query: [
        'includeThumbnails' => true,
    ],
);

Note

  • If the query parameter includeThumbnails is set to true, the response item(s) will include a non-empty array key previewImageUrls containing the URLs for the corresponding image thumbnails.

Update Collection

$streamApi->updateCollection(
    libraryId: 1,
    collectionId: '97f20caa-649b-4302-9f6e-1d286e0da144',
    body: [
        'name' => 'Bunny Hopping Collection V2',
    ],
);

Delete Collection

$streamApi->deleteCollection(
    libraryId: 1,
    collectionId: '97f20caa-649b-4302-9f6e-1d286e0da144',
);

List Collections

$streamApi->listCollections(
    libraryId: 1,
    query: [
        'page' => 1,
        'perPage' => 100,
        'search' => 'bunny',
        'orderBy' => 'date',
        'includeThumbnails' => true,
    ],
);

Note

  • If the query parameter includeThumbnails is set to true, the response item(s) will include a non-empty array key previewImageUrls containing the URLs for the corresponding image thumbnails.

Create Collection

$streamApi->createCollection(
    libraryId: 1,
    body: [
        'name' => 'Bunny Collection',
    ],
);

Manage Videos

Get Video

$streamApi->getVideo(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
);

Update Video

$streamApi->updateVideo(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    body: [
        'title' => 'Bunny Hoppers',
        'collectionId' => '97f20caa-649b-4302-9f6e-1d286e0da144',
        'chapters' => [
            [
                'title' => 'Chapter 1',
                'start' => 0,
                'end' => 300,
            ],
            [
                'title' => 'Chapter 2',
                'start' => 301,
                'end' => 500,
            ],
        ],
        'moments' => [
            [
                'label' => 'Awesome Scene 1',
                'timestamp' => 70,
            ],
            [
                'label' => 'Awesome Scene 2',
                'timestamp' => 120,
            ],
        ],
        'metaTags' => [
            [
                'property' => 'description',
                'value' => 'My Video Description',
            ],
            [
                'property' => 'robots',
                'value' => 'noindex,nofollow',
            ],
        ],
    ],
);

Delete Video

$streamApi->deleteVideo(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
);

Create Video

$streamApi->createVideo(
    libraryId: 1,
    body: [
        'title' => 'Bunny Hoppers',
        'collectionId' => '97f20caa-649b-4302-9f6e-1d286e0da144',
    ],
);

Note

  • The title does not need to match the video filename and/or extension you're intending to upload.
  • A collectionId is not required.
  • The response returns the video's GUID, which is required for video upload (see Upload Video).

Upload Video

/*
 * File contents read into string from the local filesystem.
 */
$content = file_get_contents('./bunny-hop.mp4');

/*
 * File contents handle from a `$filesystem` (Flysystem FtpAdapter).
 */
$content = $filesystem->readStream('./bunny-hop.mp4');

// Upload video.
$streamApi->uploadVideo(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    body: $content,
    query: [
        'enabledResolutions' => '240p,360p,480p,720p,1080p,1440p,2160p',
    ],
);

Get Video Heatmap

$streamApi->getVideoHeatmap(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
);

Warning

  • This endpoint currently returns a 500 status code with the following response:
    Internal Server Error
    A support ticket has been created at bunny.net regarding this issue.

Get Video Play Data

$streamApi->getVideoPlayData(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    query: [
        'token' => 'ead85f9a-578b-42b7-985f-9a578b12b776',
        'expires' => 3600,
    ],
);

Get Video Statistics

$streamApi->getVideoStatistics(
    libraryId: 1,
    query: [
        'dateFrom' => 'm-d-Y',
        'dateTo' => 'm-d-Y',
        'hourly' => false,
        'videoGuid' => 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    ],
);

Re-encode Video

$streamApi->reEncodeVideo(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
);

Repackage Video

$streamApi->repackageVideo(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    query: [
        'keepOriginalFiles' => true,
    ],
);

Note

  • This method allows repackaging of videos for libraries that have Enterprise DRM enabled.

List Videos

$streamApi->listVideos(
    libraryId: 1,
    query: [
        'page' => 1,
        'itemsPerPage' => 100,
        'search' => 'bunny',
        'collection' => '97f20caa-649b-4302-9f6e-1d286e0da144',
        'orderBy' => 'date',
    ],
);

Set Thumbnail

$streamApi->setThumbnail(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    query: [
        'thumbnailUrl' => 'https://cdn.example.com/thumbnail.jpg',
    ],
);

Set Thumbnail (by body)

/*
 * File contents read into string from the local filesystem.
 */
$content = file_get_contents('./thumbnail.jpg');

/*
 * File contents handle from a `$filesystem` (Flysystem FtpAdapter).
 */
$content = $filesystem->readStream('./thumbnail.jpg');

// Set video thumbnail by body contents.
$streamApi->setThumbnailByBody(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    body: $content,
    headers: [
        'Content-Type' => 'image/jpeg',
    ],
);

Note

  • This method allows for uploading a thumbnail based on body contents.

Warning

  • Adding a thumbnail by uploading body contents is not documented in the official Bunny.net API specification for the Set Thumbnail endpoint.

Fetch Video

$streamApi->fetchVideo(
    libraryId: 1,
    body: [
        'url' => 'https://example.com/bunny-hop.mp4',
        'headers' => [
            'newKey' => 'New Value',
            'newKey-1' => 'New Value 1',
            'newKey-2' => 'New Value 2',
        ],
    ],
    query: [
        'collectionId' => '97f20caa-649b-4302-9f6e-1d286e0da144',
    ],
);

Add Caption

$streamApi->addCaption(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    sourceLanguage: 'ja',
    body: [
        'srclang' => 'ja',
        'label' => 'Subtitles (Japanese)',
        'captionsFile' => 'MQowMDowMDowMCwwMDAgLS0+IDAwOjAxOjAwLDAwMApOZXZlciBnb25uYSBnaXZlIHlvdSB1cC4K',
    ],
);

Note

Delete Caption

$streamApi->deleteCaption(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    sourceLanguage: 'ja',
);

Note

Warning

  • If a caption was created with a specific ISO standard for the sourceLanguage, then you have to delete it with the same standard. Example: a caption created with sourceLanguage ISO 639-1 can only be deleted by sending a request with sourceLanguage ISO 639-1.
  • This endpoint will always return a 200 status code, even if the subtitle with specificied sourceLanguage does not exist.

Tip

  • If you (regularly) update captions make sure to purge the captions directory associated with the video. If it's not purged you might notice outdated subtitles displayed on the video. You can get the URL for the captions directory by using the Get Video Play Data endpoint.

Transcribe Video

$streamApi->transcribeVideo(
    libraryId: 1,
    videoId: 'e7e9b99a-ea2a-434a-b200-f6615e7b6abd',
    query: [
        'language' => 'fi',
        'force' => true,
    ],
);

Note

Get OEmbed

$streamApi->getOEmbed(
    query: [
        'url' => 'https://iframe.mediadelivery.net/embed/182595/8a800e53-c949-46d0-8818-af566f032ec1',
        'maxWidth' => 1280,
        'maxHeight' => 720,
        'token' => 'ead85f9a-578b-42b7-985f-9a578b12b776',
        'expires' => 3600,
    ],
);

Note

  • The url is a required query parameter.

Reference