Skip to main content

Film types and length rules

Ten types. Most are a date range with a filter on it. Trip, album, holiday and special day are not, and those are the ones worth reading about. Every type works on a plain NAS: the default install uses Immich metadata and the locally prepared picture facts (dates, places, faces, favourites and context heads).

TypeCoversTargetNeeds
year_in_reviewone calendar year10 minnothing extra
monthly_highlightsone month60 snothing extra
seasonone season of one yearabout 3 min 15 snothing extra
person_spotlighta range, one person60 s a month, capped at 10 mina named face in Immich
multi_persona range, several people60 s a month, capped at 10 minnamed faces in Immich
on_this_daytoday's date in every earlier year45 sa few years of library
holidayone recurring date across several years60 sa few years of library
tripone trip found from GPS30 s + 10 s an active dayGPS on your pictures, and a home base
albumone Immich album30 s + 10 s an active dayan album
special_dayone day the library says something happened on30 s + 6 s an active hournothing, or the discover-days catalogue

Two setup steps make every type better, not only trips: a home base, so the editor can tell a week away from a week at home, and who's who, so it knows which people to prioritise. Set them in Home and people.

How long a film runs​

A film is as long as its distinct shots can carry. It's never padded.

The target is where the length starts, not a promise. A film never runs longer than the distinct shots its days hold: a video counts once its window clears every one already kept, a photo or Live Photo counts once it's five real minutes from every frame already kept in its moment, and a pile of near-identical frames counts as one shot, not many. A dense day can supply well past the old flat 30 s cap; a thin day still supplies much less. The preset target and the available material both limit the cut. It goes short rather than padding. The run record says what set the length:

What set itWhen
--durationyou passed a number (or typed a length under Length and pictures in the web UI)
--short-formyou picked a short-form preset and passed no --duration
the materialneither flag, and the period holds pictures
the preset floorneither flag, and the period holds nothing to measure

A trip and an album count active days: 30 s plus 10 s a day, held between 60 s and 5 min. A special day counts active hours: 30 s plus 6 s an hour, held between 60 s and 3 min, and never fewer than 30 s of pictures on top of its title and ending, however thin the day. Twelve one-minute months do not make a twelve-minute year: the year has its own ten-minute target. How the editor spends those seconds is in Length, quiet weeks and filler.

Filtering by people​

Repeating --person means pictures holding every name. --person-match or makes it a union; the web UI's Pictures with select (all of them together or any of them) is the same switch. For anything else, --people-expression takes the condition directly:

immich-memories generate --memory-type multi_person --year 2025 \
--people-expression '"Riley" AND ("Casey" OR "Bob")'

AND binds tighter than OR, and AND means the same picture, not just the same afternoon: every named person must be recognised on that exact picture, strict per picture. The expression replaces --person and --person-match. The web UI has it under Grouped condition. Trips, albums, person spotlights and any --birthday run refuse it.

Year in review​

A whole calendar year, in capture order, with a title card wherever the month changes.

immich-memories generate --memory-type year_in_review --year 2025

The editor groups the year into stories (a trip, a birthday, a run of ordinary weeks), weighs them against each other and gives each the shots its weight earns. From library to film has the rules. A thin year will not reach 10 minutes and the cut says how far short it landed.

Each month is checked afterwards: a month with worthy material that ends up silent makes the run's verdict coverage_incomplete. Nothing reserves a slot per month up front. If everything you have is one summer trip, a season or trip memory fits the material better.

Month dividers appear only when the range stays within one calendar year and spans four months or more. --no-photos takes stills out of the pool; they are in it by default.

Monthly, season, person, multi-person​

Same shape, different scope: pick a range, optionally filter by person, cut.

immich-memories generate --memory-type monthly_highlights --month 7 --year 2025
immich-memories generate --memory-type season --season summer --year 2025
immich-memories generate --memory-type person_spotlight --person "Riley" --year 2025
immich-memories generate --memory-type multi_person --person "Riley" --person "Bob" --year 2025

Season fits a curve through the date range: about 3 min 15 s for three months, the same from the web UI and the CLI. --duration overrides it. --hemisphere south maps summer onto December to February.

Person spotlight needs the person named in Immich's face recognition. What makes it a spotlight is the filter: the editor is the same one. Multi-person defaults to AND, so two people never in the same frame give an empty memory rather than two solo reels. Each window is read once for videos and once for photos, however many people are named. Titles and default filenames say AND or OR, so two runs never overwrite each other.

A people memory with no dates​

Leave the dates off a person or multi-person memory and it covers everything up to today, starting on the first day one of its pictures could exist:

immich-memories generate --memory-type multi_person \
--people-expression '("Riley" OR "Bob") AND "Sam"'

The start comes from the birth dates Immich holds, and from birth_date in the people registry where Immich has none. An AND waits for the youngest person it needs; an OR opens with the oldest it accepts, and bounds nothing when one of them has no birth date. Two grandparents AND a child born in 2024 covers 2024 onward, because no older picture can hold the child. runs why on an earlier picture says where the window came from. Dates you do give are never moved.

A spotlight over more than about 18 months is told as the person, one era per calendar year. Every year that holds a usable picture of them gets one moment before any story gets a second, so the dense recent years cannot take the whole film. Years with no picture of them take no part.

Birthday compilations​

--birthday turns a person spotlight into the year of someone's life that ends on the birthday, plus that birthday in earlier years. For a 21 July birthday and --year 2025 it runs 22 July 2024 to 21 July 2025, so this year's party is in this year's film. Target: 10 minutes.

immich-memories generate --person "Emma" --year 2025 --birthday

The birth date lives in Immich (People, pick the person, edit). Without one a birthday memory refuses rather than guessing. --birthday 07-21 overrides it for one run, month first; slashed forms are rejected.

The film reaches back to five earlier birthdays, each ±1 day, for the "look how small you were" cutaways. Most of those days hold nothing and the run prints one line (history: 2 of 5 earlier windows hold material) rather than a warning per year. 29 February is celebrated on the 28th in other years.

In the web UI: Person Spotlight, then tick Birthday to birthday, with earlier birthdays. The Birthday (MM-DD) field under it overrides Immich's birth date, and Years back sets how many earlier birthdays it reaches for (five when left empty). For the rolling year without the cutaways, use Custom date range from the day after last year's birthday to this year's. Cut it the night before: a year of one person is a cold run the first time.

On this day​

Up to 30 earlier years by default, ±1 day around today, in one 45-second cut. --years-back changes that reach. It wants three or more years of library, and it is the obvious one to schedule.

immich-memories generate --memory-type on_this_day --years-back 3
immich-memories generate --memory-type on_this_day --day 2026-08-31 --years-back 20

--day names the anniversary to look back from, so a run can be repeated or compared.

Holiday​

A recurrence, not a period: one window per year, the holiday ±2 days, so five Christmases ask Immich for five windows and never for the years between.

immich-memories generate --memory-type holiday --holiday christmas --years-back 5

--holiday is required, --years-back defaults to 5. These names are recognised; availability depends on the country where the table says so:

NameFalls on
new_year1 January
valentines14 February
easterWestern Easter Sunday, computed
mothers_daysecond Sunday of May, or where your home country keeps it
fathers_daythird Sunday of June, or where your home country keeps it
halloween31 October
thanksgivingwhere the country's public calendar has it (the US: fourth Thursday of November)
christmas_eve24 December
christmas25 December
new_years_eve31 December

--holiday also takes any public holiday of your country by name (see below), and anything else is read as MM-DD, for a household's own occasion (--holiday 09-14, the day you moved in). Without --year, the starting year steps back when this year's occasion has not happened yet. The title is the occasion's name, subtitled "Through the Years" in the film's language, on both the CLI and the web UI.

The holidays follow the country your home base is in (trips.homebase_latitude and trips.homebase_longitude); Immich's own geodata says which country that is, so nothing leaves your server. Each country's public holidays come from the holidays library, and --holiday accepts their names too (--holiday "ascension day" in Belgium). Without a home base the US calendar applies. These defaults do not describe what every household celebrates.

Additional observances are added on top: Valentine's Day, Halloween, Christmas Eve, New Year's Eve, and Mother's and Father's Day, which move by country:

CountryMother's DayFather's Day
US, and any country not listedsecond Sunday of Maythird Sunday of June
BE, ATsecond Sunday of Maysecond Sunday of June
DEsecond Sunday of MayAscension Day
ITsecond Sunday of May19 March
ES, PTfirst Sunday of May19 March
FRlast Sunday of May, a week later on Pentecostthird Sunday of June
GB, IEthree weeks before Easterthird Sunday of June
AU, NZsecond Sunday of Mayfirst Sunday of September
MX10 Maythird Sunday of June

Only national holidays are read; regional calendars are not included. For an observance missing from the calendar, use its date as MM-DD with --year for a single year. A recurring MM-DD repeats the Gregorian date; it does not calculate lunar or other moving observances.

Something missing? A public holiday belongs in the holidays library upstream. A family day, or a country whose Mother's or Father's Day differs: open a pull request against memory_types/date_builders.py, one rule per line.

Trip​

Nothing declares a trip. The GPS on your pictures decides where one starts and ends, and each trip gets its own film.

That film is the real renderer over the CC0 fixture library (tests/e2e/fixtures/library, credits in its CREDITS.md): a week by a lake 590 km from the test home. The satellite fly-over needs network.map_tiles: true, which is off by default because the tiles come from ArcGIS. With it off, the title sits on a flat panel. What that switch sends is on Privacy.

Detection is three steps:

  1. Away from home: a picture counts if its GPS is at least min_distance_km (50) from home. No GPS, no trip.
  2. Split on gaps: a new trip starts wherever more than max_gap_days (2) calendar days pass between two pictures, so a rest day does not split a trip. Saturday morning to Monday afternoon is a two-day gap, regardless of the capture times. A trip over New Year is one trip, not two.
  3. Drop the short ones: a trip must span min_duration_days (2) nights. 1 catches a weekend.
trips:
homebase_latitude: 48.8566 # required
homebase_longitude: 2.3522 # required
min_distance_km: 50
min_duration_days: 2
max_gap_days: 2

Home base is required. Get it wrong and your own neighbourhood becomes a trip, or real trips disappear. Drop min_distance_km to about 20 if weekend drives should count.

immich-memories generate --memory-type trip --year 2025 # list what it found
immich-memories generate --memory-type trip --year 2025 --trip-index 2
immich-memories generate --memory-type trip --year 2025 --all-trips
immich-memories generate --memory-type trip --year 2025 --near-date 2025-07-15

Both surfaces read photos and videos, and look a month either side of the year so a trip across New Year stays whole. --person narrows detection (whose pictures are scanned for GPS, useful when one phone carries it). Videos enter by date; photos also need GPS at least min_distance_km (50 km by default) from home. Photos without GPS or nearer home stay out even if their dates fit. Some cameras strip GPS, so a library shot on one can look full of holidays and find none.

--trip-index counts from 1 in the printed table. --month 7 selects the trip whose midpoint is closest to the 15th of that month; it does not crop a trip to July. Without --output, a trip starts with the filename trip_<place>_<start-date>.mp4, using a safe place slug and the selected container extension. The run adds its hash and directory as described under Output.

The name is the smallest place holding at least 85 % of the trip's located pictures, walking up from city to island, region, two regions, country. One step comes before the region: a town holding more than half of the pictures names the trip, so a seaside weekend with a walk to the next town is named after the town, not the province. It comes from the place Immich already stored on each picture, offline:

The tripIts name
A long weekend, nearly every picture in Las VegasLas Vegas, United States
Two weeks across Heraklion, Rethymno and ChaniaCrete, Greece (French film: Crète, Grèce)
Palma and PollençaMallorca, Spain
A road trip, mostly Utah and NevadaUtah and Nevada, United States
Four states, none of them most of itUnited States

network.geocoding: true lets Nominatim name a one-city or one-region trip in the film's language, and a trip to a village inside a merged municipality after the village. It is off by default: it sends coordinates to a third party.

Album​

One Immich album instead of a date range. The album is the selection: nothing outside it is considered, nothing inside it is dropped for its date. A shared album counts as your own.

immich-memories generate --from-album "Trip 2025"
immich-memories generate --from-album 59080965-22f0-46a4-be67-135692a9f584

--from-album makes it an album memory, and cannot be combined with --year, --start/--end, --period, --birthday, --season, --month, --person or another --memory-type. Albums and trips also reject --accounts; they read the primary account only. The film is titled after the album and named album_<slug>.mp4 unless --output names the file. Two albums with one name stop the CLI with the candidates and their IDs; the web UI lists albums largest first and stores the choice by ID.

Smart albums like Recents can hold tens of thousands of assets. Album mode reads at most advanced.analysis.max_album_assets per media type (10,000), newest first, and says so. Past that you probably want a date range.

An album made for one subject​

An album you built around one thing (every loaf you baked, every car you drove) can say what that thing is:

immich-memories generate --from-album "Bread" --subject "bread making along the years"

With --subject, every picture in the album stands on that subject. An ordinary film drops a loaf on a counter with nobody in frame; this one keeps it. Every year the album holds gets at least one shot. Sharing, the family-viewing holds, duplicates and the length still apply, and the run record lists each shot that got in on the subject alone (Picking each shot). --subject needs --from-album and a model reader: the Basic reader refuses a written subject.

Special day​

The nine types above cover something you named. A special day is one you did not: a day from your own library that a scan flagged, wrote down, and offers back when its anniversary comes round. --day is required. When the catalogue holds several events on that day, also pass --event-id with the event's ID from days-export. An ID that does not match an event on the chosen day is refused.

immich-memories discover-days # build the catalogue once; it resumes
immich-memories days-due # what falls within three days of today
immich-memories generate --memory-type special_day --day 2016-06-12

discover-days walks the library a month at a time. On Basic, a day is kept when one recorded fact stands out: it was spent away from home, it holds three or more favourites, it is mostly video, or it ran long (20 pictures over 6 hours or more) with close family in it. Each year keeps its strongest advanced.automation.special_days_per_year (6), away days first. The title comes from the day's own place.

The catalogue lives in the store; days-export writes it to a JSON file you can edit and days-import reads it back. A film covers the day's run, the stretch of pictures the occasion left, split at five hours of silence rather than at midnight, so a long night out is not cut at 00:00. It never reaches past its own first and last picture, and a run longer than 48 hours is not one occasion. window_origin in the run record says what bounded the film.

Three routes bring a day back: auto run offers anniversaries within 3 days (round ones first, a decade before a seventh), the Special day type on the Memory page offers the whole catalogue, and generate --day takes any day, catalogued or not. An uncatalogued day is scoped to itself and named by --title, else by its date.

Catalogue titles name real people and places, so they never reach the command line: automation passes --day alone and generate re-reads the title. What automation prints is the evidence:

10 years ago today · 289 photos over 18 hours
via special-days catalogue

With a model​

A text model adds three things here, and changes nothing else about the types:

  • discover-days first reads each month's days together, then checks each proposed occasion against that day's own picture descriptions. Both readings must agree it was an occasion; a title alone does not qualify it. No picture is sent. Confirmed occasions need enough varied material for a film, with no six-per-year cap. Unread days remain marked for retry. Use discover-days --rescan to recheck catalogue entries.
  • An uncatalogued special day, and people and occasion films, get a title written from their facts. The reader invents no event name the facts do not carry.
  • A month or year gets a light polish on top of the Basic draft. What that polish does and costs is on What a model adds and Make it better.