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

Php Mediainfo Laravel Package

mhor/php-mediainfo

A PHP wrapper around the MediaInfo CLI for reading detailed metadata from audio and video files. It provides a clean object-oriented API for codecs, duration, bitrate, resolution, channels, and track details, returning parsed output for easy inspection.

Deep Wiki
Context7

Getting Started

mhor/php-mediainfo is a thin object-oriented wrapper around the mediainfo binary. It does not parse media itself — it shells out, reads the XML, and hydrates typed containers. So step zero is installing the CLI:

# Debian/Ubuntu
apt-get install mediainfo
# macOS
brew install mediainfo
# verify it's on PATH for the PHP user (php-fpm, queue workers, cron)
mediainfo --Version

Then:

composer require mhor/php-mediainfo

Minimal first use case — you have an upload and need duration, resolution and codec:

use Mhor\MediaInfo\MediaInfo;

$mediaInfo = new MediaInfo();
$mediaInfo->setConfig('command', '/usr/bin/mediainfo'); // absolute path is safer than relying on PATH

$container = $mediaInfo->getInfo('/storage/app/videos/clip.mp4', true); // true = treat as local file

$general = $container->getGeneral();
$video   = $container->getVideos()[0] ?? null;

$durationMs = $general->get('duration')?->getMilliseconds();
$width      = $video?->get('width')?->getAbsoluteValue();

Where to look first, in order:

  1. Mhor\MediaInfo\MediaInfo — config keys and the getInfo() entry point.
  2. Mhor\MediaInfo\Container\MediaInfoContainer — the getGeneral() / getVideos() / getAudios() / getSubtitles() accessors.
  3. Mhor\MediaInfo\Model\* (General, Video, Audio, Text, Image, Menu) — each is a keyed bag of attributes with get(), getAttributes().
  4. Mhor\MediaInfo\Attribute\* (Duration, Size, Ratio, Mode, Rate) — the typed value objects you'll actually be formatting.

Implementation Patterns

Wrap it in a single application service. Don't scatter new MediaInfo() through controllers. Bind a configured instance and expose a narrow API:

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

    public function probe(string $absolutePath): MediaMetadata
    {
        $c = $this->mediaInfo->getInfo($absolutePath, true);
        // map container -> your own DTO, so the rest of the app
        // never depends on the package's object graph
    }
}

The DTO mapping is the single highest-value habit with this package: it lets you swap in ffprobe later without touching call sites, and it isolates the XML-version quirks below.

Treat tracks as plural. The package returns arrays because a single MKV or HLS master can carry many streams. Always design for getAudios() returning 0..n and pick deliberately:

$audios = $container->getAudios();
$primaryAudio = $audios[0] ?? null;              // or filter by language / default flag
$hasSubtitles = count($container->getSubtitles()) > 0;

Probe once, persist. MediaInfo reads headers, not the whole file, so it's fast — but on a 5,000-item import it still means 5,000 proc_open calls. Store the extracted JSON on the model (media_metadata column) at upload time and read from there in views. For imports, probe inside a queued job, chunked.

Batch loops with guard clauses. A corrupt or zero-byte file won't necessarily throw — you get a container with an empty general track. Check before you index:

$general = $container->getGeneral();
if (!$container->getVideos() || !$general->get('duration')) {
    throw new UnprocessableMediaException($path);
}

Testing. Unit tests should not require the binary. Either (a) build MediaInfoContainer/model objects directly from fixture arrays captured from real output, or (b) mock MediaInfo so getInfo() returns a hand-built container. Keep a small tests/fixtures/ set of real XML dumps (one MP4, one MKV with two audio tracks, one with subtitles) and assert your DTO mapping against them.

Formatting for UI. Attribute objects are inconsistent about output — some are __toString-able human strings, some need explicit getters. Normalise in one presenter:

$size = $general->get('file_size');        // Size
$human = (string) $size;                   // "1.32 GiB"-ish, MediaInfo-formatted
$bytes = $size->getAbsoluteValue();

Gotchas and Tips

The second argument to getInfo() is not optional in spirit. getInfo($path) defaults to treating the string as something other than a local file (URL/stream handling). Always pass true for a filesystem path, or you'll get confusing empty results on paths that clearly exist.

Old XML vs new XML output is the #1 breakage. MediaInfo changed its XML schema around v0.7.83+; field names, unit conventions (notably duration in ms vs seconds) and casing shifted. The wrapper exposes setConfig('use_oldxml_output', true|false) — set it explicitly to match the binary version your containers ship with, and pin the binary in your Docker base image. Never rely on "whatever apt gives us."

Key names are not always what you expect. Keys come straight from MediaInfo's output (bit_rate, frame_rate, format_profile, duration), and the same logical field can be named differently across track types. When something returns null, dump array_keys($track->getAttributes()) — that is the fastest debugging trick available here. get() returns null silently rather than throwing.

Binary/path failures surface as exceptions from the process layer. In php-fpm the PATH is often shorter than your shell's, so mediainfo: not found at runtime is a classic. Set command to an absolute path, and add a health check or a deploy smoke test that probes a bundled 1-second fixture file.

Attribute values vary in type. get('duration') gives a Duration object with getMilliseconds(); get('bit_rate') typically gives a scalar. Don't assume uniformity — wrap every read in a typed helper. Also beware Duration on old-XML output being an integer millisecond count while new-XML gives fractional seconds; assert this in your fixtures.

Large/complex sources are slow or sparse. Blu-ray structures, ISO images, HLS manifests and remote URLs are slower and often return partial data (menus, images, multiple video tracks). Set a sensible timeout on your queue job; the package doesn't expose a probe timeout, so bound it at the process/job level.

Extension points are thin. MediaInfoBuilder exists for constructing containers programmatically (useful in tests), but there's no plugin system for custom attribute parsers — unknown fields land as plain strings. If you need a typed field MediaInfo emits but the package doesn't model, read it as a string and cast in your own mapper.

Maintenance reality check. The package is mature but low-activity, MIT-licensed, with no recent releases. That's fine for a stable CLI wrapper, but pin the version in composer.json, keep your MediaProbe abstraction thin, and know that ffprobe with -print_format json is a drop-in escape hatch if you ever need to leave.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package