Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Transcoding Laravel Package

ac/transcoding

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require ac/transcoding
    

    Add to composer.json if not using autoloading:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Ac\\Transcoding\\": "vendor/ac/transcoding/src/"
        }
    }
    

    Run composer dump-autoload.

  2. First Use Case: Transcode an image using FFmpeg (requires FFmpeg installed):

    use Ac\Transcoding\Transcoder;
    use Ac\Transcoding\Adapter\FFmpegAdapter;
    use Ac\Transcoding\Preset\FFmpegPreset;
    
    $transcoder = new Transcoder();
    $inputFile = new \Ac\Transcoding\File('path/to/input.mp4');
    $outputFile = new \Ac\Transcoding\File('path/to/output.webm');
    
    // Register FFmpeg adapter and preset
    $transcoder->registerAdapter('ffmpeg', new FFmpegAdapter());
    $transcoder->registerPreset('webm', new FFmpegPreset([
        'command' => 'ffmpeg -i {input} -c:v libvpx -b:v 1M {output}',
        'input' => ['mp4', 'mov'],
        'output' => ['webm']
    ]));
    
    // Transcode
    $transcoder->transcode($inputFile, $outputFile, 'ffmpeg', 'webm');
    
  3. Where to Look First:

    • src/Ac/Transcoding/Transcoder.php (core logic).
    • src/Ac/Transcoding/Adapter/ (built-in adapters like FFmpegAdapter, ImageMagickAdapter).
    • src/Ac/Transcoding/Preset/ (preset examples and structure).
    • tests/ (real-world usage patterns).

Implementation Patterns

Core Workflow

  1. Register Adapters:

    $transcoder->registerAdapter('ffmpeg', new FFmpegAdapter());
    $transcoder->registerAdapter('imagemagick', new ImageMagickAdapter());
    
    • Adapters handle the actual transcoding (e.g., FFmpeg for video, ImageMagick for images).
    • Extend \Ac\Transcoding\Adapter\AbstractAdapter to create custom adapters.
  2. Define Presets:

    $preset = new FFmpegPreset([
        'command' => 'ffmpeg -i {input} -vf "scale=640:480" {output}',
        'input' => ['mp4', 'avi'],
        'output' => ['mp4']
    ]);
    $transcoder->registerPreset('resize', $preset);
    
    • Presets encapsulate CLI/command options and file type restrictions.
    • Use {input} and {output} placeholders for file paths.
  3. Transcode Files:

    $job = $transcoder->transcode(
        $inputFile,
        $outputFile,
        'ffmpeg',  // Adapter name
        'resize'   // Preset name
    );
    
    • Returns a \Ac\Transcoding\Job object with metadata (success/failure, duration, etc.).
  4. Event Handling (Optional):

    $transcoder->on('pre', function ($job) {
        \Log::info("Starting transcode job: {$job->getInput()->getPathname()}");
    });
    $transcoder->on('post', function ($job) {
        if ($job->isSuccess()) {
            \Log::info("Transcode succeeded!");
        }
    });
    
    • Listen to pre, post, or error events for hooks.

Integration Tips

  1. Laravel Service Provider: Bind the transcoder to the container for dependency injection:

    $this->app->singleton('transcoder', function ($app) {
        $transcoder = new Transcoder();
        $transcoder->registerAdapter('ffmpeg', new FFmpegAdapter());
        // Register presets...
        return $transcoder;
    });
    
  2. Queue Transcoding Jobs: Use Laravel queues to offload transcoding:

    $job = (new TranscodeJob($inputFile, $outputFile, 'ffmpeg', 'resize'))
        ->onQueue('transcodes');
    
  3. Dynamic Presets: Load presets from a database or config:

    $presets = config('transcoding.presets');
    foreach ($presets as $name => $config) {
        $transcoder->registerPreset($name, new FFmpegPreset($config));
    }
    
  4. File Validation: Use File class methods to validate before transcoding:

    if ($inputFile->isSupported('ffmpeg')) {
        $transcoder->transcode(...);
    }
    
  5. Custom Adapters: Example: Create a CustomAdapter for a proprietary tool:

    class CustomAdapter extends AbstractAdapter {
        protected $command = 'custom-tool -i {input} -o {output}';
    
        public function getSupportedInputTypes() {
            return ['custom'];
        }
    
        public function getSupportedOutputTypes() {
            return ['converted'];
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Adapter/Preset Registration:

    • Error: Adapter/Preset not found.
    • Fix: Ensure names match exactly when registering and using:
      $transcoder->registerAdapter('ffmpeg', $adapter); // Must use 'ffmpeg' later
      
  2. File Path Handling:

    • Error: Transcoding fails with "File not found".
    • Fix: Use absolute paths or resolve them:
      $inputFile = new File(storage_path('app/input.mp4'));
      
  3. Command Placeholders:

    • Error: {input} or {output} not replaced in commands.
    • Fix: Verify presets use the correct placeholders (case-sensitive).
  4. FFmpeg/ImageMagick Paths:

    • Error: ffmpeg/convert not found.
    • Fix: Set environment variables or configure adapters:
      $adapter = new FFmpegAdapter(['ffmpeg' => '/usr/local/bin/ffmpeg']);
      
  5. Concurrent Transcoding:

    • Error: Race conditions with output files.
    • Fix: Use unique filenames or queue jobs with delays.

Debugging

  1. Enable Verbose Logging:

    $transcoder->setLogger(new \Monolog\Logger('transcoding', [
        new \Monolog\Handler\StreamHandler(storage_path('logs/transcoding.log'))
    ]));
    
  2. Check Job Status:

    if (!$job->isSuccess()) {
        \Log::error("Transcode failed: " . $job->getError());
    }
    
  3. Validate Presets: Use Preset::validate() to check config before registering:

    if (!$preset->validate()) {
        throw new \InvalidArgumentException("Invalid preset config");
    }
    

Tips

  1. Preset Inheritance: Extend presets for reuse:

    class ResizePreset extends FFmpegPreset {
        public function __construct($width, $height) {
            parent::__construct([
                'command' => 'ffmpeg -i {input} -vf "scale={$width}:{$height}" {output}',
                'input' => ['mp4', 'mov'],
                'output' => ['mp4']
            ]);
        }
    }
    
  2. Environment-Specific Config: Use Laravel's config('transcoding') to switch presets/adapters per environment.

  3. Performance:

    • Cache presets if they’re static.
    • Use Job::setTimeout() to avoid hanging.
  4. Testing: Mock adapters for unit tests:

    $mockAdapter = $this->getMockBuilder(FFmpegAdapter::class)
        ->disableOriginalConstructor()
        ->getMock();
    $transcoder->registerAdapter('mock', $mockAdapter);
    
  5. Security:

    • Validate input/output paths to prevent directory traversal.
    • Restrict adapters to specific file types (e.g., block .php files).
  6. Extending Events: Add custom event listeners for notifications or retries:

    $transcoder->on('error', function ($job) {
        // Send Slack alert or retry logic
    });
    
  7. Legacy PHP Support: For PHP 5.3+, use trait-based event dispatching if needed (check EventDispatcher class).

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
craftcms/url-validator
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony