Media Management
User guide for the Media Management feature in GeoHazardWatch.
Table of Contents
- Overview
- Prerequisites
- Browsing Media by Year
- Browsing by Keyword
- Searching Media
- Item Detail Page
- Embedding Media in Pages (MediaPlugin)
- Embedding a Single Photo with Image or ATTACH
- Thumbnails
- Supported File Formats
- Admin: Configuring and Scanning
- Configuration Reference
- Limitations
Overview
The Media Management feature allows GeoHazardWatch to browse, search, and display media files — photos and videos — stored on external drives or local folders, without moving or modifying the source files. It is designed for large personal or family photo libraries (500,000+ files).
Key facts at a glance
| Property | Value |
|---|---|
| Source files | Never modified or moved |
| Index | Persistent JSON, updated on demand |
| Metadata | EXIF / IPTC / XMP (via ExifTool) |
| Thumbnails | Generated on first request; cached |
| Browse | By year, by keyword, or full-text search |
| Private awareness | Items linked to private pages are hidden from unauthorised users |
The feature is disabled by default. An administrator must enable it and configure at least one media folder before it is accessible.
Prerequisites
The Media Management feature must be enabled and configured by an administrator before users can browse media.
ngdpbase.media.enabledmust be set totrue- At least one folder must be listed in
ngdpbase.media.folders - A full scan must have been triggered at least once (see Admin: Configuring and Scanning)
If these prerequisites are not met, all /media/* URLs return 503 Service Unavailable.
Browsing Media by Year
URL: /media
The media home page displays a grid of years for which at least one media item has been indexed. Click any year to see the items from that year.
URL: /media/year/{year}
The year page displays a thumbnail grid of all items indexed for that year, sorted by filename. Each card shows:
- A 300×300 thumbnail (images only; videos show a film icon)
- The original filename
Click any card to open the Item Detail Page.
Browsing by Keyword
URL: /media/keyword/{keyword}
The keyword album page displays a thumbnail grid of all indexed media items whose EXIF/IPTC/XMP keyword list contains the specified keyword. Keyword matching is exact and case-sensitive.
The page shows:
- A heading with the matched keyword
- An item count
- A responsive grid of thumbnail cards (2–5 columns depending on screen width)
- Each card links to the Item Detail page, passing
?keyword={keyword}so that Prev / Next navigation stays within the keyword album rather than the year
How to reach a keyword album
- From the Item Detail page: click the album icon ( ) next to any keyword in the metadata panel — for example, the keyword
Mollywill show an album icon that navigates to/media/keyword/Molly. - From a page that uses the
[{MediaPlugin format='album-link' keyword='...'}]plugin syntax (see Embedding Media in Pages). - By navigating directly to
/media/keyword/{keyword}in the browser.
Searching Media
URL: /media/search
The search page provides a free-text search across the media index. All query words must appear somewhere in the item's metadata for the item to appear in results (AND semantics).
Fields searched
| Field | Example |
|---|---|
| Filename | IMG_1234.jpg |
| Year | 2023 |
| EXIF title | Summer Vacation |
| EXIF description | At the beach |
| EXIF/IPTC keywords | family, holiday |
Tips
- Search is case-insensitive.
- Use multiple words to narrow results:
birthday 2022finds items matching bothbirthdayand2022. - Partial words match:
birthmatchesbirthday.
Item Detail Page
URL: /media/item/{id}
The item detail page shows:
- A large preview (up to 800×600) for image files.
- An inline HTML5 video player for video files (mp4, mov, m4v, mkv and other browser-supported formats). The player uses HTTP Range support for seeking.
- A placeholder icon for other file types, with a download link.
- Prev / Next navigation within the current album context:
- If you arrived via a keyword album (URL has
?keyword=), Prev/Next moves within that keyword's items. - Otherwise, Prev/Next moves within the same year.
- If you arrived via a keyword album (URL has
- A metadata panel with:
- Filename and MIME type
- Year (links to the year browse page)
- Camera make and model (from EXIF)
- Title and description (from EXIF/IPTC/XMP)
- Keywords — each keyword is shown as a page link (blue if the page exists, red if it does not). Next to each keyword is an album icon linking to
/media/keyword/{keyword}to browse all media with that keyword. - GPS coordinates (when present) — links to OpenStreetMap
- Linked page name (when the item is associated with a page)
- The source directory path.
- A collapsible Media Information panel (click the "Media Information" button to expand):
- Item ID with copy button
- Direct URL with copy button
- Plugin Syntax — ready-to-paste
[{MediaPlugin ...}]snippets for each keyword on the item. Copy a snippet and paste it into any page to embed a list or album of items with that keyword. If no keywords are present, a generic[{MediaPlugin format='list' keyword='current'}]snippet is shown. - Image dimensions and file size (when available)
- Absolute file path with copy button
JSON API
For programmatic access, the same data is available as JSON:
GET /media/api/item/{id} — single item metadata
GET /media/api/year/{year} — all items for a year
Embedding Media in Pages (MediaPlugin)
The [{MediaPlugin}] plugin lets you embed live media counts, lists, or thumbnail galleries on any page.
Basic syntax
[{MediaPlugin}]
[{MediaPlugin format='count'}]
[{MediaPlugin format='list'}]
[{MediaPlugin format='album'}]
[{MediaPlugin format='album-link'}]
Parameters
| Parameter | Values | Description |
|---|---|---|
format | count (default), list, album, album-link | Output format |
keyword | any keyword string, or 'current' | Filter by EXIF/XMP keyword |
page | any page name, or 'current' | Filter by linked page name |
year | four-digit year | Filter by year |
max | integer | Maximum number of items to display |
Only one filter (keyword, page, or year) should be used at a time. If none is given, all indexed items are included.
format='count'
Outputs the number of matching items as plain text.
[{MediaPlugin}]
Outputs: 14327 (the total number of indexed items)
[{MediaPlugin format='count' keyword='current'}]
Outputs: the count of items whose keywords include the current page name.
format='list'
Outputs a bulleted list of filenames, each linking to its item detail page.
[{MediaPlugin format='list' keyword='Molly'}]
[{MediaPlugin format='list' year='2023' max='10'}]
[{MediaPlugin format='list' page='current'}]
format='album'
Outputs an inline thumbnail grid. Each thumbnail links to the item detail page, and the link includes ?keyword={keyword} when a keyword filter is active so that Prev/Next navigation on the detail page stays within the album context.
[{MediaPlugin format='album' keyword='current'}]
[{MediaPlugin format='album' keyword='Summer 2024' max='20'}]
For keywords that contain an apostrophe, use double quotes around the value:
[{MediaPlugin format='album' keyword="Molly's Cooking"}]
format='album-link'
Outputs a styled button that links to the /media/keyword/{keyword} album page. The button shows the keyword name and item count.
[{MediaPlugin format='album-link' keyword='current'}]
[{MediaPlugin format='album-link' keyword="Molly's Cooking"}]
Note: format='album-link' requires a keyword= parameter. It returns an error message if no keyword is provided.
keyword='current' and page='current'
Both keyword='current' and page='current' resolve to the current page's name at render time. This makes the plugin portable — you can add the same snippet to many pages and each page will automatically show its own related media.
[{MediaPlugin format='album' keyword='current'}]
On the page named Molly, this is equivalent to:
[{MediaPlugin format='album' keyword='Molly'}]
Examples
Show a count of all indexed media items:
This platform has [{MediaPlugin}] media items indexed.
Show a thumbnail album of photos tagged with the current page's name:
[{MediaPlugin format='album' keyword='current'}]
Show a link button to a specific keyword album:
[{MediaPlugin format='album-link' keyword='Family Holidays'}]
Show the first 10 items from 2022 as a list:
[{MediaPlugin format='list' year='2022' max='10'}]
Show all media linked to the current page by page association:
[{MediaPlugin format='count' page='current'}] photos are linked to this page.
[{MediaPlugin format='list' page='current'}]
Embedding a Single Photo with Image or ATTACH
To embed a single media library photo inline in page content — rather than a full album — use the media:// URI with Using ImagePlugin or Using AttachPlugin:
[{Image src='media://IMG_1234.jpg' caption='Family Trip 2024' align='center'}]
[{Image src='media://DSC_0042.jpg' align='left' display='float'}]
[{ATTACH src='media://vacation.jpg' caption='Summer 2024'}]
Use the original filename (e.g. IMG_1234.jpg) exactly as it appears in the media index. The file is served from /media/file/:id; items linked to Private Pages are only visible to authorised users.
For layout options (align, display, caption, width, etc.) see Attachments, Using ImagePlugin, or Using AttachPlugin.
Thumbnails
URL: /media/thumb/{id}?size={WxH}
Thumbnails are generated on the first request and cached to disk. Subsequent requests for the same item and size are served from the cache instantly.
Default sizes used by the browser UI: 300x300 (grid), 800x600 (detail).
Any WxH value can be requested via the API. Thumbnails are always JPEG at 85% quality, cropped to fit the requested dimensions (cover mode).
Video files do not have thumbnails in the current version — a film icon placeholder is shown instead. Video playback is available on the item detail page via the HTML5 <video> element.
Supported File Formats
The list of indexed file extensions is configurable via the ngdpbase.media.extensions config key. The default set is shown below.
Images
| Extension | Format |
|---|---|
| jpg, jpeg | JPEG |
| png | PNG |
| gif | GIF |
| heic, heif | HEIF / HEIC (Apple) |
| tiff, tif | TIFF |
| webp | WebP |
| raw, orf, cr2, nef, arw, dng | Camera RAW formats |
| bmp | Bitmap |
Videos
| Extension | Format |
|---|---|
| mp4 | MPEG-4 |
| mov | QuickTime |
| avi | AVI |
| mkv | Matroska |
| m4v | iTunes Video |
| wmv | Windows Media Video |
| 3gp | 3GPP Mobile Video |
To add or remove extensions, set ngdpbase.media.extensions to the desired list in your instance configuration. For example, to also index .flv and .webm files:
ngdpbase.media.extensions = ["jpg", "jpeg", "png", "mp4", "mov", "flv", "webm"]
The leading dot is optional — both "jpg" and ".jpg" are accepted. Values are normalised to lowercase.
Admin: Configuring and Scanning
Enabling the feature
In your instance configuration (or app-custom-config.json), set:
ngdpbase.media.enabled = true
ngdpbase.media.folders = ["/path/to/photos", "/path/to/more-photos"]
Restart the server after changing these settings.
Triggering a scan
URL: GET /admin/media
The admin media page shows the current index statistics (number of years indexed, year range) and a Trigger Rescan button.
Clicking Trigger Rescan sends a POST /admin/media/rescan request. The scan runs synchronously and the page shows a summary of the result:
- Scanned — total files examined
- Added — new items added to the index
- Updated — existing items whose file content changed
- Errors — files that could not be processed (check the server log for details)
For very large libraries the scan may take several minutes. The browser will wait for the response.
Automatic background scans
The server automatically re-scans all configured folders on a schedule. The default interval is every hour (3600000 ms). Configure with:
ngdpbase.media.scaninterval = 3600000
Set to 0 to disable background scanning.
Configuration Reference
All settings live in the ngdpbase.media.* namespace.
| Key | Default | Description |
|---|---|---|
ngdpbase.media.enabled | false | Enable the media feature |
ngdpbase.media.folders | [] | Absolute paths to media root folders |
ngdpbase.media.maxdepth | 5 | Maximum directory depth (0 = unlimited) |
ngdpbase.media.scaninterval | 3600000 | Background rescan interval in ms |
ngdpbase.media.ignoredirs | [".dtrash", ".ts"] | Directory names to skip during scan |
ngdpbase.media.ignorefiles | [".photoviewignore", ".plexignore"] | Sentinel files that exclude a directory |
ngdpbase.media.extensions | *(see Supported File Formats)* | File extensions to index (overrides built-in list) |
ngdpbase.media.index.file | *(data dir)* | Absolute path to media-index.json |
ngdpbase.media.thumbnail.dir | *(data dir)* | Absolute path to thumbnail cache directory |
ngdpbase.media.thumbnail.sizes | 300x300,150x150 | Comma-separated size specs |
ngdpbase.media.metadata.priority | ["EXIF","IPTC","XMP"] | Metadata extraction priority |
ignoredirs and ignorefiles
ignoredirs— any directory whose name exactly matches an entry in this list is skipped entirely (and its children are not scanned).ignorefiles— if a directory contains a file with one of these names, the entire directory (and its children) is skipped. This is compatible with the.photoviewignoreand.plexignoreconventions used by other photo management tools.
Limitations
Video thumbnails
Thumbnail generation for video files requires FFmpeg, which is not currently bundled. Video items show a placeholder icon in the grid and detail views. Video playback is supported in the item detail page via the browser's native HTML5 <video> player.
Write access
The media feature is strictly read-only. It never modifies, moves, renames, or deletes source media files.
First scan required
The index is empty until the first scan completes. Year browsing and search return no results before then.
Incremental scans
Background scans compare each file's modification time against the index. If you replace a file with new content but preserve the modification time, the change will not be detected unless you trigger a forced rescan from the admin page.
See Media for an overview, Attachments for uploading files, and Using ImagePlugin, Using AttachPlugin, and Using MediaPlugin for plugin parameter references.
No comments yet.