Weave 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

Mediainfo Bundle Laravel Package

mhor/mediainfo-bundle

mhor/mediainfo-bundle wraps the MediaInfo library for PHP, making it easy to extract technical metadata from audio and video files—codecs, duration, resolution, bitrate, and more—through a clean, bundle-integrated API. Useful for media catalogs, upload validation, and processing pipelines.

View on GitHub
Deep Wiki
Context7

Getting Started

First, a reality check for Laravel developers: mhor/mediainfo-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config file that Laravel's package discovery will pick up. It is a thin DI wrapper around mhor/php-mediainfo, which is the library that actually does the work by shelling out to the mediainfo CLI binary and parsing its XML output.

  • If you are on Symfony: composer require mhor/mediainfo-bundle, register Mhor\MediaInfoBundle\MhorMediaInfoBundle in bundles.php, and set the binary path in config.
  • If you are on Laravel (your stated context): skip the bundle entirely and composer require mhor/php-mediainfo. Bind it in a service provider yourself (see below). The bundle adds essentially nothing you can't wire in ten lines of AppServiceProvider.

The real prerequisite is the system binary, not the Composer package:

# Debian/Ubuntu
apt-get install mediainfo
# macOS
brew install mediainfo
# Alpine (Docker images)
apk add mediainfo

Verify with mediainfo --Version before you write any PHP — the vast majority of "this package doesn't work" issues are a missing binary or a wrong path.

Symfony minimal setup:

# config/packages/mhor_media_info.yaml
mhor_media_info:
    binary: '%env(MEDIAINFO_BINARY)%'   # e.g. /usr/bin/mediainfo
// Autowire the underlying library type
use Mhor\MediaInfo\MediaInfo;

final class ProbeController
{
    public function __construct(private MediaInfo $mediaInfo) {}

    public function show(string $path): void
    {
        $file = $this->mediaInfo->getInfo($path);
        dump($file->getGeneral()->get('duration'));
        dump($file->getVideo()?->get('frame_rate'));
        dump($file->getAudio()?->get('bit_rate'));
    }
}

Laravel equivalent (recommended path):

// composer require mhor/php-mediainfo
// app/Providers/MediaInfoServiceProvider.php
public function register(): void
{
    $this->app->singleton(MediaInfo::class, function () {
        $mediaInfo = new MediaInfo();
        $mediaInfo->setConfig('command', config('services.mediainfo.binary', '/usr/bin/mediainfo'));
        return $mediaInfo;
    });
}
// config/services.php
'mediainfo' => ['binary' => env('MEDIAINFO_BINARY', '/usr/bin/mediainfo')],

First use case to validate the pipeline: probe a single uploaded file (duration, video codec, audio channels, bitrate) and log the raw general block. If that works, everything downstream is just mapping attributes.

Where to look first: the mhor/php-mediainfo README and its src/Type/ classes (File, General, Video, Audio, Text, Menu). The bundle's own docs are sparse and its value is almost entirely "configure the binary path in YAML."

Implementation Patterns

Wrap it in a domain service, never inject MediaInfo directly into controllers/jobs. The library's return types are wide and version-unstable; a thin adapter keeps the blast radius small and gives you a place to normalize units, cache, and handle "no audio stream" gracefully.

final class MediaProbe
{
    public function __construct(private MediaInfo $mediaInfo) {}

    public function probe(string $absolutePath): ProbeResult
    {
        $file = $this->mediaInfo->getInfo($absolutePath);

        return new ProbeResult(
            durationMs: (int) round($file->getGeneral()->get('duration')->getMilliseconds()),
            videoCodec: $file->getVideo()?->get('codec_id')->getShortName(),
            width: $file->getVideo()?->get('width')->getAbsoluteValue(),
            height: $file->getVideo()?->get('height')->getAbsoluteValue(),
            audioChannels: $file->getAudio()?->get('channel_s')->getAbsoluteValue(),
            audioSampleRate: $file->getAudio()?->get('sampling_rate')->getAbsoluteValue(),
            bitrate: $file->getGeneral()->get('overall_bit_rate')->getAbsoluteValue(),
        );
    }
}

getAudio() / getVideo() / getText() return null when the stream type is absent (audio-only files, image files, subtitles). Always null-safe-chain; a video file with no audio track is the classic crash.

Always process in a queued job, never in the request cycle. mediainfo forks a process and for a multi-GB file can take seconds to tens of seconds. In Laravel:

final class ProbeUploadedMedia implements ShouldQueue
{
    public int $timeout = 120;       // mediainfo can be slow on large files
    public int $tries = 3;

    public function __construct(public int $mediaId) {}

    public function handle(MediaProbe $probe, MediaMetadataRepository $repo): void
    {
        $media = Media::findOrFail($this->mediaId);
        $repo->save($media, $probe->probe($media->absolutePath()));
    }
}

Cache aggressively. Metadata for a stored file is immutable (the file's bytes don't change). Key on content hash, not path:

Cache::rememberForever("mediainfo:{$sha1}", fn () => $probe->probe($path)->toArray());

Persist a normalized subset, not the full object. The library's model serializes to a huge nested structure. Store only the fields your UI/validation needs — the raw XML belongs in object storage or a log line, not a json column you'll query.

Centralize the binary path per environment. In Symfony, the bundle config is the right place. In Laravel, config/services.php. Never hardcode /usr/bin/mediainfo in code — dev machines, Docker, and Vapor (which may not have the binary at all) differ.

Prefer the library for new work. The bundle's only jobs are (a) reading config and (b) registering the service. If you're on Laravel, or on Symfony ≥5, just instantiate the library in a provider and skip the compatibility risk.

Gotchas and Tips

The binary is the dependency; composer require is not enough. The most common failure is mediainfo: command not found or an empty result. Check $mediaInfo->getInfo() returns a non-empty File, and log exec failures — the library surfaces very little when the binary is missing. In Docker, add mediainfo to the runtime image, not the builder stage. On Laravel Vapor/serverless, you cannot easily install it — plan for a container-based runtime or an external probe service.

Attribute values are objects, not scalars. get('duration') returns an attribute wrapper; casting it directly to int gives you garbage or 0. Use getAbsoluteValue(), getMilliseconds(), __toString(), or getShortName() (for codec IDs) depending on the field — mixing these up is the second most common bug after the missing binary. Read the attribute class before you trust a value.

Filenames with spaces, quotes, or unicode are a real risk. The wrapper builds a shell command. Keep files on disk under server-generated names (UUIDs / hashes), never under the user-supplied original filename. This sidesteps escaping issues entirely and is good practice regardless.

The "old XML" output mode matters. Some library versions default to the newer XML schema; if attribute names look unfamiliar (or get() returns null for a field the docs mention), toggle the output mode:

$mediaInfo->setConfig('use_oldxml_output', true);

Pin the library version in composer.json and check its changelog before upgrading — the attribute names and return types have moved between major versions.

Symfony bundle compatibility is the elephant in the room. With 6 stars and 0 dependents, this bundle is effectively a one-person side project and likely targets old Symfony versions (2.x/3.x patterns, possibly no autowire-friendly service aliases). On a modern Symfony app, verify the bundle boots before committing to it; otherwise take the provider route. Treat it as "unmaintained" for planning purposes — budget for a fork, or vendor the 30 lines it saves you.

Make it testable. You cannot unit-test against real media without fixtures. Two options:

  • Ship tiny sample files (a 1-second mp4, a wav) in tests/fixtures and gate integration tests on the binary being present (@requires / markTestSkipped).
  • Bind an interface (MediaProbe) and fake it in feature tests so your app logic never touches exec.

Timeout and memory. mediainfo on a large file (or a malformed one) can hang or emit enormous XML. Set a job/invocation timeout, and treat any exception as "metadata unavailable" rather than failing the upload.

Extension point: the cleanest place to customize behavior is your adapter (MediaProbe) plus a cached repository — not the bundle config. If you genuinely need to change how mediainfo is invoked (custom args, containerized binary, remote probe), subclass Mhor\MediaInfo\MediaInfo, override the command construction, and bind that class in your service provider. Do not patch the vendor directory.

Bottom line: the underlying mhor/php-mediainfo library is useful and stable enough for audio/video metadata extraction. The bundle is a convenience wrapper with negligible adoption and uncertain maintenance — for a Laravel codebase, install the library directly, wrap it in a service, and run it in a queued job with a cached result.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route