media_organizer 1.20260802.1152033 copy "media_organizer: ^1.20260802.1152033" to clipboard
media_organizer: ^1.20260802.1152033 copied to clipboard

Normalize photos and videos into self-describing, sortable, dedup-friendly filenames (datetime · place · size · checksum). CLI + library, cross-platform.

1.20260802.1152033 #

The filename rule becomes the package's shared contract, importable without dart:io.

  • New package:media_organizer/media_naming.dart — the naming contract on its own, with zero imports. Flutter apps (and anything sandboxed or web-bound) can now depend on the rule without pulling in the IO layer.

  • New MediaUploadNameCodec / MediaUploadNameComponents — encode, parse and contentKeyOf for <YYYYMMDDTHHmmss>[_<place>]_<sizeBytes>_<md5-8>.<ext>, pinned by test/fixtures/media_filename_contract.json. That fixture is now the single source of truth for every consumer, including a Kotlin parser in another repo that cannot share Dart code. Change the fixtures first when changing the rules.

  • MediaFilename.parse now delegates to that codec, which fixes three ways it disagreed with the contract:

    • 20261307T143022_123_abcdef01.jpg (month 13) used to parse, because DateTime() silently rolls an out-of-range month into the next year. Hours ≥ 24, minutes and seconds ≥ 60 had the same problem. All are rejected now.
    • a size token longer than 15 digits, or a negative one, used to be accepted.
    • the parse is otherwise unchanged, so normal names behave exactly as before.

    Stricter parsing means a malformed name that used to yield a (wrong) MediaName now yields null, and the organizer treats it as not-yet-normalized.

  • MediaFilename.build is unchanged and keeps its filesystem-friendlier place policy (New YorkNew-York). MediaUploadNameCodec.encode keeps spaces and underscores instead, for pipelines that must match a corpus already in the wild. Both emit names the shared parser accepts, and dedup keys on <size>_<md5-8> alone, never on the place — so the two policies can coexist in one folder without breaking dedup.

1.20260615.1205955 #

Initial release. Versions follow 1.YYYYMMDD.1HHmmss; mediaOrganizerVersion (printed by media_organizer --version) and pubspec.yaml are kept in sync by tool/set_version.dart.

  • MediaFilename — build/parse <datetime>[_<place>]_<size>_<md5-8>.<ext>.
  • MediaOrganizer — scan a folder, probe capture time + GPS, checksum, dedup by content key, rename into the scheme, copy/move to an output folder (dry-run + idempotent re-runs).
  • Injectable MediaProbe (default CompositeMediaProbe: image EXIF + Mp4MediaProbe for video moov time/GPS + mtime fallback), LocationResolver (default none), MediaTranscoder (default passthrough), and MediaFileSystem (default LocalFileSystem, optionally RandomAccessReader) — keeps the core pure, IO-agnostic, and cross-platform.
  • OfflineGeocoder + GeoPlace — a LocationResolver that maps GPS to the nearest place name fully offline (haversine, no API key). Data-free: you supply the place list (e.g. from GeoNames / immich-geodata). Examples: example/offline_geocoder_example.dart (GeoNames) and example/immich_geodata_example.dart (zh-TW localized immich-geodata CSVs).
  • Mp4MediaProbe — pure-Dart MP4/MOV capture time + GPS from the moov box (Apple creationdate, mvhd 1904 time, ISO-6709 location); seeks past mdat via RandomAccessReader instead of reading the whole file.
  • Verified copies: verify (forced on with move) re-hashes each written file and aborts that item on mismatch, so a corrupt copy never deletes an original.
  • Progress + cancellation: onProgress per-file callback and a cancelled predicate on run(); the CLI shows a live [i/total] line and stops cleanly on Ctrl-C.
  • FfmpegTranscoder — opt-in video re-encode to 1080p H.264 + faststart, with isAvailable() detection and a per-OS installHint() when ffmpeg is missing.
  • UploadTarget + MediaUploader — push an organize run to a cloud sink (Google Drive / S3 / SFTP), idempotent via the same content key (NAS needs no target — organize straight into the mount). Core stays SDK-free; targets are injectable and faked in tests.
  • CLI: media_organizer organize -i <input> -o <output> [--move] [--verify] [--dry-run] [-r] [--progress] [--transcode] [--ffmpeg <path>], plus media_organizer stats <folder> and media_organizer --version.
0
likes
160
points
90
downloads

Documentation

API reference

Publisher

verified publisherchangyy.app

Weekly Downloads

Normalize photos and videos into self-describing, sortable, dedup-friendly filenames (datetime · place · size · checksum). CLI + library, cross-platform.

Repository (GitHub)
View/report issues

Topics

#media #photos #rename #exif #organize

License

MIT (license)

Dependencies

args, crypto, exif, path

More

Packages that depend on media_organizer