PHPackages                             arbet/laravel-sora - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. arbet/laravel-sora

ActiveLibrary[API Development](/categories/api)

arbet/laravel-sora
==================

Laravel package for OpenAI Video API integration

v1.0.1(7mo ago)03MITHTMLPHP ^8.2CI passing

Since Oct 11Pushed 6mo agoCompare

[ Source](https://github.com/arbet/laravel-sora)[ Packagist](https://packagist.org/packages/arbet/laravel-sora)[ RSS](/packages/arbet-laravel-sora/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (6)Versions (3)Used By (0)

OpenAI Video for Laravel
========================

[](#openai-video-for-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/bc8c5d6c3aa8054acfb7d2ff9eb9b4546f16f7d5177726b5ffa287ee0d8f6818/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f61726265742f6c61726176656c2d736f72612e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/arbet/laravel-sora)[![Total Downloads](https://camo.githubusercontent.com/909fe3a1e736694ee8380e267e64202ae2606a7153801011b566a91993c89960/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f61726265742f6c61726176656c2d736f72612e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/arbet/laravel-sora)

Easy integration of OpenAI Video API with Laravel applications. This package provides a simple and elegant way to interact with OpenAI's Video API endpoints.

Features
--------

[](#features)

- 🎥 Generate videos from text prompts
- 🖼️ Generate videos with reference images
- 🎬 Remix existing videos with new prompts
- 📤 Upload video files to OpenAI
- 🔍 Analyze video content with AI
- 📊 Check video generation status
- 💾 Download generated videos
- 🎯 Laravel-friendly facade interface
- ⚡ Built on Guzzle HTTP client
- 🛡️ Custom exception handling

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- Laravel 10.x or 11.x
- OpenAI API key

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require arbet/laravel-sora
```

Configuration
-------------

[](#configuration)

### Publish Configuration File

[](#publish-configuration-file)

Publish the configuration file to your application:

```
php artisan vendor:publish --tag=openai-video-config
```

This will create a `config/openai-video.php` file in your application.

### Environment Variables

[](#environment-variables)

Add your OpenAI API key to your `.env` file:

```
OPENAI_API_KEY=your-openai-api-key-here
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_TIMEOUT=120
OPENAI_VIDEO_MODEL=gpt-4o
```

Usage
-----

[](#usage)

### Using the Facade

[](#using-the-facade)

```
use Arbet\OpenAIVideo\Facades\OpenAIVideo;

// Generate a video from a text prompt
$result = OpenAIVideo::generate('A serene sunset over the ocean', [
    'size' => '1920x1080',
    'duration' => 10,
]);

// Upload a video file
$upload = OpenAIVideo::upload('/path/to/video.mp4', 'assistants');

// Analyze video content
$analysis = OpenAIVideo::analyze(
    'https://example.com/video.mp4',
    'Describe what is happening in this video'
);

// Check generation status
$status = OpenAIVideo::getStatus($result['id']);

// Download generated video
$path = OpenAIVideo::download($result['url'], 'videos/generated.mp4');
```

### Using Dependency Injection

[](#using-dependency-injection)

```
use Arbet\OpenAIVideo\OpenAIVideo;

class VideoController extends Controller
{
    public function __construct(
        protected OpenAIVideo $openAIVideo
    ) {}

    public function generate(Request $request)
    {
        try {
            $result = $this->openAIVideo->generate($request->input('prompt'), [
                'size' => $request->input('size', '1920x1080'),
            ]);

            return response()->json($result);
        } catch (\Arbet\OpenAIVideo\Exceptions\OpenAIVideoException $e) {
            return response()->json([
                'error' => $e->getMessage()
            ], 500);
        }
    }
}
```

Available Methods
-----------------

[](#available-methods)

### `generate(string $prompt, array $options = []): array`

[](#generatestring-prompt-array-options---array)

Generate a video from a text prompt.

```
$result = OpenAIVideo::generate('A cat playing piano', [
    'model' => 'gpt-4o',
    'size' => '1920x1080',
]);
```

#### Generating Videos with Reference Images

[](#generating-videos-with-reference-images)

You can pass a reference image to guide the video generation by including the `image` parameter in the options array. The image parameter should contain the file ID of an image that has been uploaded to OpenAI.

**Step 1: Upload the reference image**

```
// Upload an image file (use 'vision' as the purpose)
$imageUpload = OpenAIVideo::upload('/path/to/reference-image.jpg', 'vision');
// Returns: ['id' => 'file-abc123', 'object' => 'file', 'purpose' => 'vision', ...]
```

**Step 2: Generate video with the reference image**

```
// Pass the uploaded image file ID in the options array
$result = OpenAIVideo::generate('Animate this image with flowing water', [
    'image' => $imageUpload['id'],
    'size' => '1920x1080',
    'duration' => 10,
]);
```

**Complete Example:**

```
use Arbet\OpenAIVideo\Facades\OpenAIVideo;

// Upload reference image
$imageUpload = OpenAIVideo::upload(storage_path('app/reference-image.jpg'), 'vision');

// Generate video using the reference image
$result = OpenAIVideo::generate(
    'Transform this scene into a vibrant sunset with moving clouds',
    [
        'image' => $imageUpload['id'],
        'size' => '1920x1080',
        'duration' => 15,
    ]
);

// Check the generation status
$status = OpenAIVideo::getStatus($result['id']);

// Download when ready
if ($status['status'] === 'completed') {
    $path = OpenAIVideo::download($status['url'], 'videos/generated.mp4');
}
```

**Supported Image Formats:**

- JPEG (.jpg, .jpeg)
- PNG (.png)
- GIF (.gif)
- WebP (.webp)

### Supported Parameters

[](#supported-parameters)

The `generate()` method supports all parameters from the OpenAI Video API through the `$options` array:

#### **`prompt`** (string, required)

[](#prompt-string-required)

The text description of the video you want to generate. Passed as the first argument.

```
OpenAIVideo::generate('A serene sunset over the ocean')
```

#### **`model`** (string, optional)

[](#model-string-optional)

The AI model to use for video generation. Defaults to the value in your config file.

```
OpenAIVideo::generate('A sunset', [
    'model' => 'sora-1.0',
])
```

**Available models:**

- `sora-1.0` (or check OpenAI's documentation for latest models)

#### **`size`** (string, optional)

[](#size-string-optional)

The dimensions of the generated video.

```
OpenAIVideo::generate('A sunset', [
    'size' => '1920x1080',
])
```

**Common sizes:**

- `1920x1080` (Full HD)
- `1280x720` (HD)
- `720x480` (SD)

#### **`duration`** (integer, optional)

[](#duration-integer-optional)

The duration of the video in seconds.

```
OpenAIVideo::generate('A sunset', [
    'duration' => 15,  // 15 seconds
])
```

#### **`image`** (string, optional)

[](#image-string-optional)

File ID of a reference image to guide the video generation. The image must first be uploaded using the `upload()` method.

```
$imageUpload = OpenAIVideo::upload('/path/to/reference.jpg', 'vision');

OpenAIVideo::generate('Animate this scene', [
    'image' => $imageUpload['id'],
])
```

See [Generating Videos with Reference Images](#generating-videos-with-reference-images) for complete examples.

---

### Complete Parameter Example

[](#complete-parameter-example)

```
use Arbet\OpenAIVideo\Facades\OpenAIVideo;

// Upload reference image (optional)
$imageUpload = OpenAIVideo::upload(
    storage_path('app/reference.jpg'),
    'vision'
);

// Generate video with all parameters
$result = OpenAIVideo::generate(
    'Create an epic cinematic scene from this image',
    [
        'model' => 'sora-1.0',
        'image' => $imageUpload['id'],
        'size' => '1920x1080',
        'duration' => 20,
    ]
);

// The result contains:
// - 'id' => Generation ID
// - 'status' => 'processing' | 'completed' | 'failed'
// - Other metadata from OpenAI
```

### `remix(string $videoId, string $prompt, array $options = []): array`

[](#remixstring-videoid-string-prompt-array-options---array)

Remix an existing completed video by applying a new text prompt to transform it.

**Important**: The video must be in `completed` status before you can remix it.

```
// First, generate a video
$result = OpenAIVideo::generate('A person walking in a park');

// Wait for it to complete (check status)
$status = OpenAIVideo::getStatus($result['id']);

// Once completed, remix it with a new prompt
if ($status['status'] === 'completed') {
    $remix = OpenAIVideo::remix(
        $status['id'],
        'Transform into a vintage 1980s style with neon colors'
    );
}
```

#### Response Structure

[](#response-structure)

The method returns a video job object with the following structure:

```
[
    'id' => 'video_abc123',                    // Unique identifier for the remix job
    'object' => 'video',                        // Always 'video'
    'status' => 'processing',                   // 'processing', 'completed', or 'failed'
    'created_at' => 1634567890,                // Unix timestamp (seconds)
    'model' => 'sora-1.0',                     // The video generation model used
    'size' => '1920x1080',                     // Resolution of the video
    'seconds' => '10',                         // Duration in seconds
    'progress' => 45,                          // Approximate completion percentage
    'remixed_from_video_id' => 'video_xyz789',// ID of the source video
    'completed_at' => null,                    // Unix timestamp when finished (if completed)
    'expires_at' => 1634654290,               // Unix timestamp when assets expire
    'error' => null,                           // Error object (if failed)
]
```

#### Complete Example

[](#complete-example)

```
use Arbet\OpenAIVideo\Facades\OpenAIVideo;

// Step 1: Generate original video
$original = OpenAIVideo::generate('A serene sunset over the ocean', [
    'size' => '1920x1080',
    'duration' => 10,
]);

echo "Original video ID: {$original['id']}\n";

// Step 2: Poll for completion
do {
    sleep(10); // Wait 10 seconds between checks
    $status = OpenAIVideo::getStatus($original['id']);
    echo "Status: {$status['status']} - Progress: {$status['progress']}%\n";
} while ($status['status'] === 'processing');

// Step 3: Remix the completed video
if ($status['status'] === 'completed') {
    $remix = OpenAIVideo::remix(
        $status['id'],
        'Apply vintage film effect with enhanced warm colors'
    );

    echo "Remix job ID: {$remix['id']}\n";
    echo "Remixed from: {$remix['remixed_from_video_id']}\n";

    // Step 4: Wait for remix to complete
    do {
        sleep(10);
        $remixStatus = OpenAIVideo::getStatus($remix['id']);
        echo "Remix status: {$remixStatus['status']} - Progress: {$remixStatus['progress']}%\n";
    } while ($remixStatus['status'] === 'processing');

    // Step 5: Download the remixed video
    if ($remixStatus['status'] === 'completed') {
        $path = OpenAIVideo::download($remixStatus['url'], 'videos/remixed.mp4');
        echo "Downloaded to: {$path}\n";
    }
}
```

#### Error Handling

[](#error-handling)

```
try {
    $remix = OpenAIVideo::remix('video_123', 'New style prompt');
} catch (\Arbet\OpenAIVideo\Exceptions\OpenAIVideoException $e) {
    // Handle errors (e.g., video not found, video not completed, API error)
    echo "Error: {$e->getMessage()}\n";
}
```

#### Common Error Cases

[](#common-error-cases)

- **Video not found**: The provided `video_id` doesn't exist
- **Video not completed**: Attempting to remix a video that's still processing
- **Invalid prompt**: The prompt doesn't meet OpenAI's requirements

### `upload(string $filePath, string $purpose = 'assistants'): array`

[](#uploadstring-filepath-string-purpose--assistants-array)

Upload a video or image file to OpenAI.

```
// Upload a video file
$upload = OpenAIVideo::upload('/path/to/video.mp4', 'assistants');

// Upload an image file for video generation
$imageUpload = OpenAIVideo::upload('/path/to/image.jpg', 'vision');
```

### `analyze(string $videoUrl, string $prompt, array $options = []): array`

[](#analyzestring-videourl-string-prompt-array-options---array)

Analyze video content with AI.

```
$analysis = OpenAIVideo::analyze(
    'https://example.com/video.mp4',
    'What objects are visible in this video?',
    ['max_tokens' => 500]
);
```

### `getStatus(string $generationId): array`

[](#getstatusstring-generationid-array)

Get the status of a video generation request.

```
$status = OpenAIVideo::getStatus('gen_abc123');
```

### `download(string $url, string $savePath): string`

[](#downloadstring-url-string-savepath-string)

Download a generated video to your storage.

```
$path = OpenAIVideo::download(
    'https://api.openai.com/v1/videos/abc123',
    'videos/my-video.mp4'
);
```

Error Handling
--------------

[](#error-handling-1)

The package throws `OpenAIVideoException` for all API-related errors:

```
use Arbet\OpenAIVideo\Facades\OpenAIVideo;
use Arbet\OpenAIVideo\Exceptions\OpenAIVideoException;

try {
    $result = OpenAIVideo::generate('My video prompt');
} catch (OpenAIVideoException $e) {
    Log::error('OpenAI Video Error: ' . $e->getMessage());
    // Handle the error
}
```

Configuration Options
---------------------

[](#configuration-options)

The `config/openai-video.php` file contains the following options:

- `api_key`: Your OpenAI API key (from `.env`)
- `base_url`: The OpenAI API base URL (default: `https://api.openai.com/v1`)
- `timeout`: Request timeout in seconds (default: `120`)
- `default_model`: Default model to use for video operations (default: `gpt-4o`)

Testing
-------

[](#testing)

This package includes a comprehensive test suite to ensure reliability and quality before each release.

### Running Tests

[](#running-tests)

Run the full test suite:

```
composer test
```

Run tests with coverage report:

```
composer test-coverage
```

After running with coverage, open `coverage/index.html` in your browser to view the detailed coverage report.

### Running Specific Test Groups

[](#running-specific-test-groups)

Run only unit tests:

```
vendor/bin/phpunit tests/Unit
```

Run only feature tests:

```
vendor/bin/phpunit tests/Feature
```

Run integration tests (requires real API key):

```
vendor/bin/phpunit --group integration
```

### Test Structure

[](#test-structure)

The test suite is organized into three categories:

- **Unit Tests** (`tests/Unit/`): Test individual methods and classes in isolation using mocked dependencies
- **Feature Tests** (`tests/Feature/`): Test Laravel integration, service provider, and facade functionality
- **Integration Tests** (`tests/Integration/`): Optional tests that make real API calls (skipped by default)

### Running Tests Before Release

[](#running-tests-before-release)

Follow these steps before each release:

1. **Run the full test suite**: `composer test`
2. **Check code coverage**: `composer test-coverage`
3. **Verify all tests pass**: Ensure no failures or warnings
4. **Review coverage report**: Aim for 80%+ code coverage
5. **Run integration tests** (optional): If you have API credentials

### Continuous Integration

[](#continuous-integration)

This package uses GitHub Actions for automated testing. Tests run automatically on:

- Every push to `main` or `develop` branches
- Every pull request to `main` or `develop` branches
- Multiple PHP versions (8.1, 8.2, 8.3)
- Multiple Laravel versions (10.x, 11.x)

### Writing New Tests

[](#writing-new-tests)

When adding new features, always include corresponding tests:

1. Add unit tests for new methods in `tests/Unit/`
2. Add feature tests for Laravel integration in `tests/Feature/`
3. Use mocked HTTP responses to avoid real API calls in unit tests
4. Follow the existing test naming convention: `it_can_do_something` or `it_throws_exception_when_...`

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

Security
--------

[](#security)

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

Credits
-------

[](#credits)

- [Arbet](https://github.com/arbet)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

Support
-------

[](#support)

For support, please open an issue on GitHub or contact .

Related Packages
----------------

[](#related-packages)

- [OpenAI PHP Client](https://github.com/openai-php/client)
- [Laravel OpenAI](https://github.com/openai-php/laravel)

Disclaimer
----------

[](#disclaimer)

This package is not officially affiliated with OpenAI. Make sure to review OpenAI's terms of service and pricing before using their API.

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance66

Regular maintenance activity

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

212d ago

PHP version history (2 changes)v1.0.0PHP ^8.1

v1.0.1PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/91649b9993c190f2a263555fe2a3f44acfa213890dabc2870163cfe45512515c?d=identicon)[arbet](/maintainers/arbet)

---

Top Contributors

[![arbet](https://avatars.githubusercontent.com/u/1234119?v=4)](https://github.com/arbet "arbet (9 commits)")

---

Tags

apilaravelvideoopenai

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/arbet-laravel-sora/health.svg)

```
[![Health](https://phpackages.com/badges/arbet-laravel-sora/health.svg)](https://phpackages.com/packages/arbet-laravel-sora)
```

###  Alternatives

[openai-php/laravel

OpenAI PHP for Laravel is a supercharged PHP API client that allows you to interact with the Open AI API

3.7k7.6M74](/packages/openai-php-laravel)[smodav/mpesa

M-Pesa API implementation

16363.7k1](/packages/smodav-mpesa)[ardakilic/mutlucell

Mutlucell SMS API wrapper for sending sms text messages for Laravel

457.3k](/packages/ardakilic-mutlucell)[dariusiii/tmdb-laravel

Laravel Package for TMDB ( The Movie Database ) API. Provides easy access to the wtfzdotnet/php-tmdb-api library.

1821.1k](/packages/dariusiii-tmdb-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
