Search by

softspring / media-bundle

softspring

A media management bundle

Package info

github.com/softspring/media-bundle

Type:symfony-bundle

pkg:composer/softspring/media-bundle

Statistics

Installs: 12 732

Dependents: 4

Suggesters: 1

Stars: 3

Open Issues: 7

v5.5.13 2026-07-28 10:49 UTC

README

Latest Stable Latest Unstable License PHP Version Downloads CI Coverage

Media library, media versioning, media rendering, and admin media management for Symfony applications.

What It Provides

  • configurable media types for images and videos
  • generated and manual media versions
  • filesystem and Google Cloud Storage drivers
  • Twig rendering helpers for images, pictures, videos, and video sets
  • admin media library screens
  • migration tools when type definitions change

Delayed Google Cloud Storage deletion

Set sfs_media.google_cloud_storage.delayed_deletion_days to a positive integer to keep a removed object available at its existing URL until the configured delay has elapsed:

sfs_media:
    google_cloud_storage:
        bucket: media-bucket
        delayed_deletion_days: 90

The driver sets the object's Custom-Time to the delayed deletion date. Configure the bucket with this Google Cloud Storage lifecycle rule, without a matchesPrefix condition:

{
  "rule": [
    {
      "action": {"type": "Delete"},
      "condition": {"daysSinceCustomTime": 0}
    }
  ]
}

For example, save it as lifecycle.json and apply it with:

gcloud storage buckets update gs://media-bucket --lifecycle-file=lifecycle.json

Without that lifecycle rule, marked objects are not deleted automatically.

This rule only affects objects with Custom-Time set. Ensure that no other process using the same bucket sets Custom-Time, or its objects will also be eligible for deletion when that time is reached.

Armonic

This package is part of Armonic.

Documentation

Armonic Documentation

Picture display dimensions

By default, a rendered <picture> takes its <img> width and height from img.src_version. When that fallback has different dimensions from the responsive sources, use img.dimensions_version to provide the intrinsic display size without changing the fallback URL:

pictures:
    card:
        sources:
            - { srcset: [ { version: card, suffix: '1x' }, { version: card_retina, suffix: '2x' } ] }
        img:
            src_version: fallback
            dimensions_version: card

Explicit image attributes passed to the renderer still take precedence over the configured dimensions version.

Animated image versions

Generated animated versions use ffprobe to validate the source and ffmpeg to resize and encode every frame. Both binaries must be installed in the application runtime. Processing is synchronous; applications should keep duration and frame limits conservative until background generation is available.

sfs_media:
    ffmpeg:
        binary: ffmpeg
        probe_binary: ffprobe
        timeout: 300

    types:
        animation:
            upload_requirements:
                mimeTypes: [image/avif, image/apng, image/gif]
            versions:
                small_avif:
                    type: avif
                    animated: true
                    scale_width: 400
                    avif_quality: 82
                    animation:
                        loop: 0
                        speed: 6
                        max_duration: 3
                        max_frames: 75
                small_webp:
                    type: webp
                    animated: true
                    scale_width: 400
                    webp_quality: 82
                    animation:
                        loop: 0
                        max_duration: 3
                        max_frames: 75

Supported generated targets are AVIF, WebP and APNG. type: keep also preserves animated GIF input. Source timing and frame rate are preserved unless animation.fps is set.

Animated WebP outputs use independent full frames. This is slightly larger than lossy partial-frame animation, but avoids accumulated composition errors that appear as trails or stripes in browsers.

When at least one version uses animated: true, configuration compilation checks that the configured ffmpeg and ffprobe binaries are executable. It fails early with their configured names and installation instructions if either binary is missing. Types without animated versions do not require FFmpeg.

FFmpeg 6.1, currently shipped by Alpine 3.22, can encode animated WebP but cannot reliably demux it as an input. Use AVIF, APNG or GIF uploads with that runtime. Animated WebP can be enabled as an upload source when the deployed FFmpeg build includes its newer animated WebP demuxer.

Animation options:

  • fps: resample the output frame rate, from 1 to 120.
  • loop: output loop count; 0 means infinite.
  • crf: AVIF constant-quality value, from 0 to 63. When omitted, it is derived from avif_quality.
  • speed: AVIF encoding speed (libaom-av1 cpu-used), from 0 to 8.
  • keyframe_interval: encoder GOP size.
  • max_duration: reject longer source animations, in seconds.
  • max_frames: reject sources containing more frames.

The processor only handles generated versions explicitly marked with animated: true. Manual versions keep their uploaded file, and regular generated images continue through the GD processor.

Package Files

Contributing

Use the standard package commands before sending changes:

composer fix
composer test
composer test-bc

See the contributing guide.

Report issues and send Pull Requests

Security

Please report vulnerabilities privately. See SECURITY.md.

License

This package is free and released under the AGPL-3.0 license.