Media Handling
==============
Django Cast provides comprehensive media management for images, audio, video, and generic files. All media is user-owned and integrates seamlessly with Wagtail's admin interface and Django's storage backends.
Overview
--------
Media handling features:
- **User ownership**: All media is associated with the uploading user
- **Multiple formats**: Support for various image, audio, and video formats
- **Automatic processing**: Image renditions, audio duration, video posters
- **Storage flexibility**: Works with local storage, S3, or any Django storage backend
- **Performance optimized**: Rendition caching, metadata storage, bulk operations
- **API access**: Full REST API for media operations
Media Types
-----------
Images
~~~~~~
Django Cast extends Wagtail's image handling with responsive image generation.
**Features**:
- Automatic rendition generation for multiple screen sizes
- Modern format support (AVIF, WebP, JPEG, PNG)
- Responsive images with srcset and sizes attributes
- User-based filtering in admin
- Bulk rendition creation
**Configuration**:
.. code-block:: python
# Image formats to generate (default)
CAST_IMAGE_FORMATS = ["jpeg", "avif"]
# Regular image slots
CAST_REGULAR_IMAGE_SLOT_DIMENSIONS = [
(1110, 740),
]
# Gallery image slots
CAST_GALLERY_IMAGE_SLOT_DIMENSIONS = [
(1110, 740), # Modal image
(120, 80), # Thumbnail
]
Each tuple defines a target slot in the layout. django-cast then generates the
responsive rendition widths needed for multiple pixel densities, so one slot
still produces multiple image files in ``srcset``.
Audio
~~~~~
Comprehensive audio file management with podcast support.
**Supported Formats**:
- **MP3**: Universal compatibility
- **M4A**: Apple ecosystem
- **OGA**: Ogg Vorbis
- **OPUS**: Modern codec
**Features**:
- Automatic duration detection (requires FFprobe)
- Multiple format upload support
- Chapter marks with timestamps
- Transcript association
- Podlove Web Player integration
- Metadata caching for performance
**Audio Metadata**:
.. code-block:: python
# Automatically extracted
audio.duration # Duration as timedelta
audio.data # JSON metadata including file sizes
Video
~~~~~
Video file support with automatic poster generation.
**Features**:
- Automatic poster frame extraction (requires FFmpeg)
- Configurable poster timestamp
- Dimension detection
- Format support: Any format browsers can play
- MIME type detection
**Poster Generation**:
.. code-block:: python
# Customize poster extraction time
video.poster_seconds = 5.0 # Extract at 5 seconds
video.create_poster() # Regenerate poster
Files
~~~~~
Generic file storage for other document types.
**Features**:
- Simple file upload and storage
- User association
- Path tracking for cleanup
Storage Configuration
---------------------
Django Cast supports flexible storage backends.
Local Storage
~~~~~~~~~~~~~
Default configuration using Django's file storage:
.. code-block:: python
# Media files served from
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
S3 Storage
~~~~~~~~~~
Configure S3 for production:
.. code-block:: python
# Using django-storages
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# Disable Wagtail's automatic cleanup for S3
DELETE_WAGTAIL_IMAGES = False
Multiple Storage Backends
~~~~~~~~~~~~~~~~~~~~~~~~~
Configure separate storage backends through Django's ``STORAGES`` setting:
.. code-block:: python
STORAGES = {
"default": {
"BACKEND": "storages.backends.s3boto3.S3Boto3Storage",
},
"production": {
"BACKEND": "storages.backends.s3boto3.S3Boto3Storage",
},
"backup": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
"OPTIONS": {
"location": "/backup/media",
},
},
}
Image Renditions
----------------
Responsive Image Generation
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cast automatically generates responsive images:
.. code-block:: html
Rendition Filters
~~~~~~~~~~~~~~~~~
Custom rendition generation:
.. code-block:: python
# Generate specific rendition
rendition = image.get_rendition('fill-300x300')
# Bulk create renditions
gallery.create_renditions()
Performance Optimization
~~~~~~~~~~~~~~~~~~~~~~~~
- Renditions are cached after first generation
- Bulk operations for multiple images
- Repository pattern prefetches renditions
- Minimal database queries
Audio Features
--------------
Chapter Marks
~~~~~~~~~~~~~
Add navigable chapters to audio:
.. code-block:: python
from cast.models import ChapterMark
ChapterMark.objects.create(
audio=audio,
start="00:05:30",
title="Introduction",
link="https://example.com",
image="https://example.com/chapter.jpg"
)
Transcripts
~~~~~~~~~~~
Multiple transcript format support:
.. code-block:: python
from cast.models import Transcript
transcript = Transcript.objects.create(
audio=audio,
podlove=podlove_file, # JSON format
vtt=vtt_file, # WebVTT format
dote=dote_file # DOTe JSON format
)
Player Integration
~~~~~~~~~~~~~~~~~~
Audio data formatted for Podlove Web Player:
.. code-block:: python
# Automatic player data generation
player_data = {
"audio": audio.audio, # Format list
"chapters": audio.chapters, # Chapter marks
"title": audio.title,
"subtitle": audio.subtitle,
}
Video Processing
----------------
Poster Generation
~~~~~~~~~~~~~~~~~
Automatic poster frame extraction:
.. code-block:: python
# Generate poster at upload
video = Video.objects.create(
user=request.user,
title="My Video",
original=video_file
)
# Poster created automatically
# Regenerate with different timestamp
video.poster_seconds = 10.0
video.create_poster()
Dimension Detection
~~~~~~~~~~~~~~~~~~~
Video dimensions and orientation:
.. code-block:: python
width, height = video._get_video_dimensions()
is_portrait = height > width
Management Commands
-------------------
Media Maintenance
~~~~~~~~~~~~~~~~~
Find orphaned media files::
python manage.py media_stale
python manage.py media_stale --delete # Remove orphaned files
Backup and Restore
~~~~~~~~~~~~~~~~~~
Sync media between storages::
# Backup from production to backup storage
python manage.py media_backup
# Restore from backup to production
python manage.py media_restore
Media Analysis
~~~~~~~~~~~~~~
Analyze storage usage::
python manage.py media_sizes
Rendition Management
~~~~~~~~~~~~~~~~~~~~
Create missing renditions::
python manage.py sync_renditions
Regenerate video posters::
python manage.py recalc_video_posters
User Ownership
--------------
Access Control
~~~~~~~~~~~~~~
All media is filtered by user:
.. code-block:: python
# In views
images = Image.objects.filter(user=request.user)
# In admin
# Automatically filtered by logged-in user
Search Integration
~~~~~~~~~~~~~~~~~~
Media is searchable:
.. code-block:: python
from wagtail.search.backends import get_search_backend
search_backend = get_search_backend()
results = search_backend.search("podcast", Audio)
API Integration
---------------
Upload via API
~~~~~~~~~~~~~~
.. code-block:: python
# POST /api/audios/
{
"title": "Episode 1",
"file":
}
Media in StreamField
~~~~~~~~~~~~~~~~~~~~
Media blocks in post content:
.. code-block:: python
body = StreamField([
("image", ImageChooserBlock()),
("gallery", GalleryBlock()),
("video", VideoChooserBlock()),
("audio", AudioChooserBlock()),
])
Best Practices
--------------
Maintenance
~~~~~~~~~~~
1. Run `media_stale` periodically to clean orphaned files
2. Backup media files regularly
3. Test restore procedures
Troubleshooting
---------------
Common Issues
~~~~~~~~~~~~~
**FFmpeg/FFprobe not found**:
Install FFmpeg for audio/video processing::
# Ubuntu/Debian
sudo apt-get install ffmpeg
# macOS
brew install ffmpeg
**Large file uploads failing**:
Adjust Django settings:
.. code-block:: python
# Increase upload limits
DATA_UPLOAD_MAX_MEMORY_SIZE = 50 * 1024 * 1024 # 50MB
FILE_UPLOAD_MAX_MEMORY_SIZE = 50 * 1024 * 1024 # 50MB
**Renditions not generating**:
Check Pillow installation and image format support::
python -m PIL --version
**S3 permissions errors**:
Ensure bucket policy allows required operations:
- GetObject
- PutObject
- DeleteObject (if DELETE_WAGTAIL_IMAGES is True)