MomentStays User Guide

Applies to MomentStays 1.4.0 (macOS 12 or later). 中文版见 USER_GUIDE.zh-CN.md.

High-resolution cover selection and candidate-photo export are included from version 1.2.0. Earlier installers do not include these options.

MomentStays converts Android Motion Photos into Apple Live Photos on your Mac — and back again. Everything follows three rules:

  1. The cover frame stays — the moment you picked remains the cover, aligned to the real frame on the media timeline.
  2. Video and audio are not re-encoded — they are remuxed only and verified sample by sample, so their quality is never lost. Image-format conversion and candidate-frame export can require image encoding.
  3. HDR is preserved honestly — gain maps that can be kept are kept intact; anything unsupported is reported, never faked.

All conversion and verification happen locally on your Mac. Nothing is uploaded.


Contents


1. Quick start

Open the DMG and drag MomentStays into Applications, then launch it from Applications. The installer shows only the application and Applications link, with an arrow indicating the drag direction. Open the guide from the app's help button; license files are inside the app bundle.

  1. Open MomentStays and click Add Photos, drag files into the queue, or pick Scan Photos Library… from the source menu.
  2. Confirm the direction: Android → Apple Live Photo (default) or Apple Live Photo → Android.
  3. Use Save to and More Options… in the top toolbar to check the destination (folder / Photos library / sharing), target format, and HDR options.
  4. Click Start (⌘Return). Settings are snapshotted when a task starts and locked while it runs.
  5. Review per-photo results in the report. Recent Results… lets you retry delivery, reveal files, or open the output folder.

Each photo produces one result folder (see §9 for naming), not loose files.

First launch: the distributed app is ad-hoc signed and not notarized. If macOS blocks the first launch, allow it under System Settings → Privacy & Security, or Control-click the app in Finder and choose Open. Once installed, the app needs no Python, FFmpeg, ExifTool, or Homebrew.

2. Interface and importing

2.1 The queue

A single workspace groups direction, Add Photos, Save to, and More Options at the top. Persistent categories show counts for Pending, Completed, Static, Needs Review, and All; Pending is selected by default. The preview pane starts closed; toggle it with Preview or ⌥⌘P. Narrow windows adapt the layout, and the interface follows system light/dark appearance with the native system orange accent.

Scanning and conversion use limited parallel processing within a memory budget. Confirmed static photos are counted separately and skipped without advancing the motion-photo conversion progress. Changes to the source list require a new scan.

Switch between thumbnails and a file list; narrow queues use the list automatically. Select a photo to inspect its vendor, path, detected cover time, and HDR information.

In the preview pane, a cover marker shows the source cover position below the photo. Hover over the timeline to see the actual video frame and time; move away to restore the still photo. Missing or ambiguous covers are reported, and unreadable video is not replaced with a fabricated preview. Preview reads the original primary motion track and does not change the cover.

Categories filter the display only: conversion still processes all selected sources, skipping confirmed static photos. Open past tasks with Recent Results.

2.2 Four ways in

Source Notes
Choose files Multi-select file picker
Choose folder Read recursively
Drag & drop Drop files onto the queue
Scan Photos Library Enumerates library assets via PhotoKit and identifies formats; can be scoped to one album (see §8)

2.3 Keyboard shortcuts

Shortcut Action
⌘O Choose photos
⌘R Rescan
⌘Return Start conversion
⌘. Stop
⌘, Export settings

2.4 Task rules

3. Directions and format support

Vendor support means "the layouts the parser can validate", not a promise for every device or firmware. Photos that were edited or forwarded through chat apps may already have lost their embedded video — lost video cannot be reconstructed from a still image.

3.1 Android → Apple

Input Notes
Google-compatible Motion Photo (JPEG) Main XMP, Extended XMP, and fully verified cover-metadata recovery
Huawei / Honor (LIVE_ trailer) Including the raw cover-frame-index path (see §4)
Samsung SEF Including the SEF trailer structure
Samsung HEIC Only validated mpvd/SEF layouts; original HEVC image items are kept, never transcoded to JPEG
OPPO / OnePlus OPPO container layout
vivo V2 vivo V2 container layout

Output is a Live Photo pair: a still (JPEG/HEIC) plus a separate MOV, paired by ContentIdentifier. The still output contains only verified still-image payloads and required extensions; motion and audio live only in the MOV.

3.2 Apple → Android

Stills and MOVs are matched by Apple ContentIdentifier, and the still-image-time timed marker is read and aligned to the actual video frame.

Target Vendors
JPEG Google/generic, Xiaomi, Samsung (writes an SEF trailer), Huawei, Honor, OPPO, vivo V2
HEIC Samsung only; existing image, thumbnail, and gain-map encodings and properties are retained. JPEG is never re-encoded into HEIC for this. Google and Xiaomi Motion Photos do not use HEIC — choose JPEG for those targets

4. How the cover frame is located

The cover timestamp is the instant in the motion video chosen as the cover. It is not the capture date — the two are separate metadata.

MomentStays reads the cover time recorded in the source, maps it along the real media timeline to the actual frame, and writes the Live Photo still-image-time marker. Converting back reads the marker and restores the Android cover position.

Rules that protect your cover:

5. Remuxing and sample-by-sample verification

Publishing and source protection:

When an output already exists:

Batch item states: converted, resumed, skipped, failed.

6. How HDR is handled

Input Handling
Existing Ultra HDR (JPEG gain map) Gain map and parameters preserved as-is; main image keeps its original encoding
Legacy Apple gain map Converted to an Ultra HDR gain map using Apple's published Rec.709 brightness model. Only the gain map is re-encoded — the SDR base image never is. Valid headroom (stops) range: (0, 16]
ISO gain data (ISO/TS 21496-1) When parameters are complete and interpretable, the encoded image is kept and only metadata is added; output can be promoted to Ultra HDR + ISO
HEIC passthrough Encoded image items, auxiliary data, and supported properties retained. tmap-style variants stay inside HEIC and are never guessed into a legacy gain model
Honor private EHDR Still extensions preserved as opaque data with byte-level verification. Preservation does not mean Apple devices can render the private model
SDR Stays SDR; no gain map is invented
Unknown/private HDR (unknown tmap, PQ/HLG, complex HEIF…) Never silently converted to SDR and never faked; reported clearly. Keeping the original HEIC encoding is an option

More detail:

7. The auxiliary track: the second video track most people never see

7.1 What it is

Some Motion Photos carry two video tracks in their embedded video: the primary motion track — the continuous clip that matches the cover — and a secondary (auxiliary) track. In measured samples the auxiliary track can be a single frame at higher resolution (e.g. 2048px wide): more like a high-resolution key frame than a video. The engine's rule: at most one auxiliary track per photo.

Do not confuse it with two other things: the MPF auxiliary images inside a JPEG (gain maps etc. — that's what the manifest field auxiliary_sha256 refers to) and HEIC auxiliary data. "Auxiliary track" here always means the video track.

7.2 Export modes

Under Export Settings → Output content (Android → Apple only):

Mode Behavior
Live Photo only (default) Build the Live Photo from the selected track
Live Photo + auxiliary track Additionally saves the auxiliary track as a separate file, <name>.auxiliary.mov. Keep it apart from the Live Photo pair
Auxiliary track only Exports just the auxiliary track as a standalone MOV (result folder suffix .auxiliary-export). No Live Photo, no audio; destination is forced to folder
Live Photo + high-resolution candidate photos Exports the selected Live Photo cover and the remaining covers as separate photos, with an all-Live-Photo or mixed delivery option

Without an auxiliary track, standalone auxiliary-video operations report an error. Candidate-photo mode still exports the original Live Photo and reports that there are no additional candidates.

7.3 Using the auxiliary track as the motion video — strict conditions

The Video track setting can switch between the primary and auxiliary tracks, but:

The UI says it plainly: "The auxiliary track may contain only one frame and cannot replace continuous motion video."

7.4 Standalone export specification

7.5 Advanced: repairing zero-duration auxiliary tracks

Some auxiliary tracks declare a duration of 0 for their only frame, so the system cannot read a valid sample and export fails. The Advanced switch "Allow repair of zero-duration auxiliary tracks" (off by default) handles this:

7.6 Selecting a high-resolution cover

Use the cover menu in the preview pane to switch between the original still and auxiliary high-resolution candidates. In list view, right-click and choose the cover-selection command. Each photo keeps its own selection; selections cannot change during conversion.

Selecting a candidate replaces the still and moves the Live Photo marker to that candidate's time. Continuous motion always comes from the primary video track. Google high-resolution frame metadata takes precedence over the auxiliary sample PTS. A candidate whose time cannot map onto the primary video cannot become a Live Photo cover.

Candidates are decoded to JPEG with the video transform applied. The original cover's HDR gain map is not reused. Zero-duration samples are repaired only in a private decode copy; originals and exported primary-video timing stay intact. This is a decoded image export, not a lossless copy of a photo bitstream.

7.7 Two candidate-photo delivery options

After selecting the candidate-photo export mode, choose either:

Candidate files use names such as .candidate-001.jpg; an additional original cover uses .original. All-live mode creates matching MOVs. Photos-library delivery creates separate assets rather than hiding candidates in alternatePhoto. Library writes occur only when a library destination is selected.

Candidate JPEGs carry their relative video time and candidate index. Optional JSON manifests also record selection, decoding and pairing details. HDR preservation for arbitrary auxiliary-video formats has not been verified.

8. Photos library: recognition, import, and monitoring

MomentStays talks to the Photos library only through the public PhotoKit API — it never reads or writes the library database directly. Library permission is requested the first time you enter a library feature, not at app launch.

8.1 Scanning and recognition

8.2 Originals vs edited versions

The Library version setting defaults to Unmodified original (keeps original HDR):

8.3 Direct import

8.4 iCloud and incremental monitoring

9. Batches, delivery, and sharing

9.1 Destinations

Destination Android → Apple Apple → Android
Save to folder ✓ ✓
Import into Photos library ✓ —
Folder + import ✓ —
Share directly — ✓
Folder + share — ✓

Auxiliary-only mode is folder-only. The main button label follows the destination ("Convert and Import", "Export Auxiliary Track", …).

9.2 Output naming

One result folder per source (stills/MOV default to photo.jpg / photo.mov inside; the original filename is recorded in the manifest's original_filename, and output modification times inherit the source's):

Case Folder
Android → Apple <relative path>.livephoto (still + MOV, plus manifest when enabled)
Auxiliary only <relative path>.auxiliary-export
Apple → Android <relative path>.motionphoto

9.3 System sharing (Apple → Android)

9.4 Reports and recent results

10. Settings reference

Open the settings sheet with More Options… in the top toolbar. Items marked * are Advanced and collapsed by default.

Group Setting Options / default
Direction Conversion direction Android → Apple Live Photo (default) / Apple Live Photo → Android
Output Destination See §9.1; enabled options depend on direction and mode
Output Target album name Default "留刻转换结果"; empty falls back to default
Output Library version Unmodified original (default) / Current edited version
Content (→Apple) Export mode Live Photo only (default) / + auxiliary track / auxiliary only
Content (→Apple) Video track Primary motion track (default) / Auxiliary track
HDR (→Apple) Try compatible conversion for non-Ultra HDR On by default
Target (→Android) Target vendor Google/generic (default), Xiaomi, Samsung, Huawei, Honor, OPPO, vivo V2
Target (→Android) Photo format JPEG · Ultra HDR / HEIC · keep original encoding (HEIC for Samsung only; all other vendors force JPEG)
Image quality (→Android) Keep original JPEG encoding On by default (no recompression)
Image quality (→Android) Main image quality / gain map quality Sliders 1%–100%, both default 95%
Verification Export manifest & JSON report Off by default (see §11)
Advanced * When cover time is not recorded Report an error (default, recommended) / Use video midpoint
Advanced * Cover time meaning (time domain) Auto-check (default, recommended) / media / presentation
Advanced * Allow repair of zero-duration auxiliary tracks Off by default (see §7.5)

As the Advanced section warns: auto mode checks the cover position and reports ambiguity as an error — change these only if you understand the source's timeline.

11. Manifests and reports

Each result folder includes a manifest.json when Export manifest & JSON report is enabled. The switch is off by default: with it off, only media is exported, but internal verification still runs, the in-app report is still available, and library import does not depend on the files. Key fields:

Field Meaning
source / source_sha256 Source path and fingerprint
identifier The pairing ContentIdentifier UUID
source_format Detected source format (e.g. samsung-sef, vivo-v2)
source_timestamp_us / source_timestamp_tag Source cover time and where it came from
timing Timeline report: time domain, cover seconds, snap_error_seconds, timing policy (source XMP / video metadata / Huawei frame / midpoint), selected track and role, frame count, dimensions
hdr Input/output HDR status and reason
primary_coding_sha256 Coding hash of the main still
auxiliary_sha256 Per-image hashes of MPF auxiliary images inside the still (gain maps etc.) — image data, not the §7 video track
auxiliary_video Auxiliary-track export info: track id, frames, dimensions, duration, hash, audio flag, duration-repair record
output_sha256 / warnings Output file hashes and all warnings

Batch reports are named report-<date>-<time>-<random>.json, with counts and per-file results. History reports are not deleted automatically.

Privacy: reports and manifests can contain source paths, EXIF, dates, and hashes. Keep them local; MomentStays itself uploads nothing.

12. Command-line tool (CLI)

The repository ships a separate Python CLI that shares parts of the native engine. Scope: the CLI covers the Google Motion Photo (JPEG) workflow only — no HEIC, vendor containers, auxiliary tracks, or library features.

Requirements: Python 3.9+, macOS 12+, Xcode Command Line Tools. The first run compiles the native helper automatically (with a notice).

# from the repository root
./motion-live --help
./motion-live --version        # 0.1.0

# 1) Read-only scan: cover time, HDR, format problems (file or folder, recursive)
./motion-live scan ~/Photos/incoming

# 2) Batch convert (output dir is required and must be outside the input dir)
./motion-live convert ~/Photos/incoming -o ~/Photos/converted

# 3) Verify an existing result against its recorded checksums
./motion-live verify ~/Photos/converted/sample.jpg.livephoto

convert options:

Option Default Meaning
--missing-time {error,midpoint} error Error when cover time is missing; midpoint uses the video midpoint and must be chosen explicitly
--legacy-hdr {auto,preserve} auto auto tries converting an existing legacy Apple gain map; plain SDR never gains HDR. preserve keeps it untouched
--time-domain {auto,media,presentation} auto Checks sample and presentation timelines and errors on ambiguity; can be pinned explicitly

Behavior: inputs are .jpg/.jpeg only (symlinks skipped). Plain still JPEGs are skipped; corrupt motion photos are failed and make the exit code 1. Each result is a <name>.livephoto/ folder (photo.jpg + photo.mov + manifest.json) plus a batch report in the output root. Existing results with matching fingerprint and options are resumed; mismatches error out and ask for a different output directory. Publishing is atomic and non-overwriting, and output timestamps inherit the source's access/modification times.

Parsing is strict by design: Motion Photo detection relies on GCamera XMP and container structure, the video must sit at the file tail and pass full box-structure validation — never signature sniffing — and an Ultra HDR claim without an MPF auxiliary image is an error.

13. Troubleshooting

Symptom / message Cause and what to do
Converted photo doesn't move on iPhone Usually the file was copied without conversion, or pairing/cover markers are incomplete. Convert with MomentStays and deliver via library import or as a pair; long-press in Photos to play
"Cover time missing" The source has no verifiable cover time. Use an unedited original; if you must proceed, choose "Use video midpoint" under Advanced (the strategy is recorded)
"Ambiguous cover time (media vs presentation)" The two timelines disagree. Pin a time domain under Advanced, or use the unedited original
"Auxiliary track has only 1 frame" Expected. Use the primary track, or export the auxiliary track on its own as an ordinary video
"Source has no auxiliary video track" That photo has a single video track; auxiliary modes don't apply
"Output exists with different content or settings" The app refuses to overwrite a mismatched result. Choose a new output folder or explicitly Overwrite in the dialog
"Library de-duplication record unreadable; writing stopped" The dedup record is corrupt; writing stops to prevent duplicate imports. Inspect the records under ~/Library/Application Support/Motion-Live/ or contact the developer
HEIC → JPEG says HDR cannot be extracted safely That HEIC's HDR structure is unsupported. Choose "HEIC · keep original encoding" instead
HDR missing after conversion You may have used the library's edited version (edits can drop the gain map) — switch to the unmodified original. SDR or unknown private HDR sources are reported as such
macOS blocks first launch The app is ad-hoc signed. Allow it in System Settings → Privacy & Security, or Control-click → Open in Finder
Library scan shows "download needed" The original is only in iCloud. Enable downloads in the library picker and retry

14. Known limitations


This guide follows the current MomentStays source, product documentation and validation scope. If the guide and an in-app message disagree, the in-app message and the result report win.