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 Bundle Laravel Package

ac/transcoding-bundle

Symfony bundle that wires AC\Transcoding\Transcoder as a container service. Configure FFmpeg and/or HandBrakeCLI paths/timeouts, register custom adapters/presets/listeners via tags, and run CLI commands to transcode files or check adapter/preset status.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require ac/transcoding-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        AmericanCouncils\TranscodingBundle\ACTranscodingBundle::class => ['all' => true],
    ];
    
  2. Configure config/packages/ac_transcoding.yaml (or app/config.yml in older Laravel/Symfony):

    ac_transcoding:
        ffmpeg:
            enabled: true
            path: /usr/bin/ffmpeg
            timeout: 30
        handbrake:
            enabled: true
            path: /usr/local/bin/HandBrakeCLI
            timeout: 60
    
  3. First Use Case: Inject the transcoder service into a Laravel service container or controller:

    use AC\Transcoding\Transcoder;
    
    public function __construct(Transcoder $transcoder) {
        $this->transcoder = $transcoder;
    }
    
    public function transcodeVideo(Request $request) {
        $inputFile = $request->file('video')->getRealPath();
        $outputFile = storage_path('app/transcoded/' . uniqid() . '.mp4');
    
        $this->transcoder->transcodeWithPreset($inputFile, 'handbrake.classic', $outputFile);
        return response()->json(['success' => true]);
    }
    

Implementation Patterns

Core Workflows

  1. Basic Transcoding:

    // Transcode with a built-in preset
    $transcoder->transcodeWithPreset($inputPath, 'ffmpeg.h264', $outputPath);
    
    // Transcode with custom options (array)
    $transcoder->transcode($inputPath, [
        'preset' => 'handbrake.classic',
        'output' => $outputPath,
        'custom_flags' => ['-vf', 'scale=1280:720'],
    ]);
    
  2. Dynamic Preset Management:

    • Define custom presets as services tagged transcoding.preset:
      # config/services.yaml
      services:
          app.transcoding.preset.custom:
              class: App\Transcoding\CustomPreset
              tags: ['transcoding.preset']
      
    • Use in code:
      $transcoder->transcodeWithPreset($inputPath, 'app.transcoding.preset.custom', $outputPath);
      
  3. Event-Driven Extensions:

    • Subscribe to transcoding events (e.g., TranscodingEvent::PRE_TRANSCODE):
      use AC\Transcoding\Event\TranscodingEvent;
      
      public function onPreTranscode(TranscodingEvent $event) {
          // Log or modify event data
          $event->setCustomFlag('--some-flag');
      }
      
    • Register as a service:
      services:
          app.transcoding.listener:
              class: App\Transcoding\PreTranscodeListener
              tags: ['transcoding.listener']
      
  4. CLI Integration:

    • Use the transcoder:transcode command for batch processing:
      php bin/console transcoder:transcode /path/to/input.mp4 handbrake.classic /path/to/output.mp4
      
    • Extend with custom commands by implementing TranscodingCommand.
  5. Laravel-Specific Patterns:

    • File Upload Handling:
      public function handleUpload(Request $request) {
          $file = $request->file('video');
          $tempPath = $file->getRealPath();
          $outputPath = storage_path('app/transcoded/' . $file->hashName());
      
          $this->transcoder->transcodeWithPreset($tempPath, 'ffmpeg.h264', $outputPath);
          return response()->file($outputPath);
      }
      
    • Queue Jobs for Async Processing:
      use App\Jobs\TranscodeVideoJob;
      
      TranscodeVideoJob::dispatch($inputPath, 'ffmpeg.h264', $outputPath)->onQueue('transcoding');
      

Gotchas and Tips

Common Pitfalls

  1. Binary Paths:

    • Ensure ffmpeg/HandBrakeCLI paths are correct. Use absolute paths (e.g., /usr/bin/ffmpeg).
    • Debug with:
      which ffmpeg  # Linux/Mac
      where ffmpeg  # Windows
      
  2. Timeouts:

    • Set timeout in config to avoid hanging (e.g., timeout: 30 for 30 seconds).
    • Default 0 means no timeout (risk of server overload).
  3. File Permissions:

    • Ensure the web server user (e.g., www-data, apache) has write permissions for output directories:
      chmod -R 775 storage/app/transcoded
      chown -R www-data:www-data storage/app/transcoded
      
  4. Preset Naming:

    • Built-in presets: ffmpeg.h264, handbrake.classic, handbrake.web.
    • Custom presets must be registered as services with the transcoding.preset tag.
  5. Error Handling:

    • Wrap transcoding in try-catch:
      try {
          $transcoder->transcodeWithPreset($input, 'ffmpeg.h264', $output);
      } catch (\AC\Transcoding\Exception\TranscodingException $e) {
          Log::error('Transcoding failed: ' . $e->getMessage());
          return response()->json(['error' => 'Transcoding failed'], 500);
      }
      

Debugging Tips

  1. Log Output:

    • Enable verbose logging in presets/adapters:
      $transcoder->transcode($input, [
          'preset' => 'ffmpeg.h264',
          'output' => $output,
          'verbose' => true,  // Logs full command output
      ]);
      
  2. Check Command Line:

    • Test FFmpeg/HandBrake directly:
      ffmpeg -i input.mp4 -c:v libx264 output.mp4
      HandBrakeCLI -i input.mp4 -o output.mp4
      
  3. Service Dumping:

    • Dump registered services to verify tags:
      php bin/console debug:container | grep transcoding
      

Extension Points

  1. Custom Adapters:

    • Implement AC\Transcoding\Adapter\AdapterInterface and tag as transcoding.adapter:
      services:
          app.transcoding.adapter.custom:
              class: App\Transcoding\CustomAdapter
              arguments: ['@logger']
              tags: ['transcoding.adapter']
      
  2. Dynamic Preset Loading:

    • Load presets from a database or API:
      $presetConfig = $this->fetchPresetFromDatabase($presetName);
      $transcoder->transcode($input, [
          'preset' => new \AC\Transcoding\Preset\DynamicPreset($presetConfig),
          'output' => $output,
      ]);
      
  3. Laravel Events:

    • Listen to file uploads and trigger transcoding:
      use Illuminate\Http\Events\FileUploaded;
      
      FileUploaded::listen(function ($event) {
          if ($event->file->getClientOriginalExtension() === 'mp4') {
              $this->transcoder->transcodeWithPreset(
                  $event->file->getRealPath(),
                  'ffmpeg.h264',
                  storage_path('app/transcoded/' . $event->file->hashName())
              );
          }
      });
      
  4. Artisan Commands:

    • Extend the bundle’s commands for custom workflows:
      use Symfony\Component\Console\Command\Command;
      use Symfony\Component\Console\Input\InputInterface;
      use Symfony\Component\Console\Output\OutputInterface;
      use AC\Transcoding\Transcoder;
      
      class CustomTranscodeCommand extends Command {
          protected static $defaultName = 'transcoder:custom';
      
          public function __construct(Transcoder $transcoder) {
              $this->transcoder = $transcoder;
              parent::__construct();
          }
      
          protected function execute(InputInterface $input, OutputInterface $output) {
              $this->transcoder->transcodeWithPreset(
                  $input->getArgument('input'),
                  'handbrake.web',
                  $input->getArgument('output')
              );
              $output->writeln('Transcoding complete!');
              return Command::SUCCESS;
          }
      }
      
      Register in config/services.yaml:
      services:
          App\Console\Commands\CustomTranscodeCommand:
              tags: ['console.command']
      
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