From b7ec3ba2f78dd65bbac9f517981fcb9476e40240 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 20 Feb 2026 08:34:28 +0000 Subject: [PATCH 1/4] Remove broken HEIC extractor, add honest Live Photo guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ISOBMFF parser was based on a wrong assumption — iOS Live Photos store the still image (.HEIC) and video (.MOV) as separate paired files. The HEIC doesn't contain an embedded video track that can be extracted in the browser. Replaced with: - Clear tabbed guide (iPhone / Mac / Quickest Way) showing how to get the .MOV companion video from a Live Photo - Smart HEIC detection on drop: shows a specific warning explaining why the HEIC won't work and points to the instructions - Multi-file drop: if both HEIC + MOV are dropped, auto-picks the MOV - Accepts .MOV/.MP4 video files directly https://claude.ai/code/session_01YLrWud6tskxirgrvVBAsGE --- live-photo-to-gif.html | 564 +++++++++++++---------------------------- 1 file changed, 171 insertions(+), 393 deletions(-) diff --git a/live-photo-to-gif.html b/live-photo-to-gif.html index 90c58fa..4d330e3 100644 --- a/live-photo-to-gif.html +++ b/live-photo-to-gif.html @@ -34,7 +34,7 @@ } h1 { font-size: 1.6rem; font-weight: 700; margin-bottom: 4px; text-align: center; } - .subtitle { color: var(--text-dim); font-size: 0.9rem; margin-bottom: 28px; text-align: center; max-width: 520px; line-height: 1.5; } + .subtitle { color: var(--text-dim); font-size: 0.9rem; margin-bottom: 28px; text-align: center; max-width: 540px; line-height: 1.5; } .app { width: 100%; max-width: 720px; display: flex; flex-direction: column; gap: 20px; } @@ -42,7 +42,7 @@ .drop-zone { border: 2px dashed var(--border); border-radius: var(--radius); - padding: 40px 24px; + padding: 36px 24px; text-align: center; cursor: pointer; transition: border-color 0.2s, background 0.2s; @@ -58,31 +58,66 @@ } .drop-zone .browse:hover { background: var(--accent-hover); } - .how-to { - margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border); - text-align: left; max-width: 420px; margin-left: auto; margin-right: auto; + /* How-to guide */ + .guide { + background: var(--surface); border: 1px solid var(--border); + border-radius: var(--radius); overflow: hidden; } - .how-to summary { - font-size: 0.82rem; color: var(--text-dim); cursor: pointer; - text-align: center; list-style: none; + .guide-header { + padding: 16px 20px; cursor: pointer; display: flex; + justify-content: space-between; align-items: center; + user-select: none; } - .how-to summary::-webkit-details-marker { display: none; } - .how-to .steps { - margin-top: 10px; padding: 0; list-style: none; - font-size: 0.82rem; color: var(--text-dim); line-height: 1.7; + .guide-header h2 { font-size: 0.95rem; font-weight: 600; } + .guide-header .arrow { transition: transform 0.2s; color: var(--text-dim); font-size: 0.8rem; } + .guide.open .guide-header .arrow { transform: rotate(180deg); } + .guide-body { display: none; padding: 0 20px 20px; } + .guide.open .guide-body { display: block; } + + .method-tabs { + display: flex; gap: 0; margin-bottom: 16px; + border-bottom: 2px solid var(--border); } - .how-to .steps li { padding-left: 20px; position: relative; } - .how-to .steps li::before { - content: attr(data-n); position: absolute; left: 0; color: var(--accent); font-weight: 600; + .method-tab { + padding: 10px 18px; font-size: 0.85rem; font-weight: 600; + color: var(--text-dim); background: none; border: none; + cursor: pointer; border-bottom: 2px solid transparent; + margin-bottom: -2px; transition: color 0.2s, border-color 0.2s; + } + .method-tab:hover { color: var(--text); } + .method-tab.active { color: var(--accent); border-bottom-color: var(--accent); } + + .method-content { display: none; } + .method-content.active { display: block; } + + .step-list { list-style: none; padding: 0; counter-reset: step; } + .step-list li { + counter-increment: step; position: relative; + padding: 10px 0 10px 36px; font-size: 0.85rem; + line-height: 1.6; color: var(--text-dim); + border-left: 2px solid var(--border); margin-left: 12px; + } + .step-list li:last-child { border-left-color: transparent; } + .step-list li::before { + content: counter(step); position: absolute; left: -11px; top: 8px; + width: 22px; height: 22px; border-radius: 50%; + background: var(--accent); color: #fff; font-size: 0.72rem; + font-weight: 700; display: flex; align-items: center; justify-content: center; + } + .step-list li strong { color: var(--text); } + + .tip-box { + margin-top: 14px; padding: 10px 14px; border-radius: 8px; + background: rgba(78,205,196,0.08); border: 1px solid rgba(78,205,196,0.2); + font-size: 0.82rem; line-height: 1.6; color: var(--success); } /* Status banner */ .status-banner { - padding: 10px 16px; border-radius: 8px; font-size: 0.85rem; line-height: 1.5; - display: none; align-items: flex-start; gap: 8px; + padding: 12px 16px; border-radius: 8px; font-size: 0.85rem; line-height: 1.5; + display: none; } - .status-banner.active { display: flex; } - .status-banner.info { background: rgba(108,99,255,0.12); border: 1px solid rgba(108,99,255,0.3); } + .status-banner.active { display: block; } .status-banner.warn { background: rgba(240,192,64,0.1); border: 1px solid rgba(240,192,64,0.3); color: var(--warn); } .status-banner.error { background: rgba(255,107,107,0.1); border: 1px solid rgba(255,107,107,0.3); color: var(--danger); } @@ -183,41 +218,82 @@ h1 { font-size: 1.3rem; } .drop-zone { padding: 28px 16px; } .card { padding: 14px; } + .method-tab { padding: 8px 12px; font-size: 0.8rem; } }

Live Photo → GIF

-

Drop an iOS Live Photo and convert it to an animated GIF with optional trimming — entirely in your browser, no upload.

+

Convert the video from an iOS Live Photo into an animated GIF — entirely in your browser, nothing uploaded.

-
Drop your Live Photo here
-

- Accepts .HEIC Live Photos directly,
- or the .MOV video companion,
- or both files together. -

- - - -
- How do I get my Live Photo file? -
    -
  1. Open Photos on iPhone or Mac
  2. -
  3. Select the Live Photo
  4. -
  5. iPhone: Tap Share → Save to Files → pick this page via Safari
  6. -
  7. Mac: File → Export → Export Unmodified Original — then drag the .HEIC (or both files) here
  8. -
  9. AirDrop to Mac also gives you the paired files
  10. -
-
+
Drop the video from your Live Photo here
+

Accepts .MOV or .MP4 files

+ + +
+ + +
+
+

How to get the video from a Live Photo

+ +
+
+

+ iOS stores a Live Photo as two separate files: a still image (.HEIC) and a short video (.MOV). + Browsers can't read the .HEIC directly — you need the .MOV video companion. Here's how to get it: +

+
+ + + +
+ +
+
    +
  1. Open the Photos app and find your Live Photo
  2. +
  3. Tap the ··· menu (top right) or long-press the photo
  4. +
  5. Tap Save as Video
  6. +
  7. The video now appears in your Recents — share or save it to Files
  8. +
  9. Open this page in Safari and Choose Video File above
  10. +
+
+ Don't see "Save as Video"? Make sure Live is turned on for that photo (not set to Long Exposure or Loop). +
+
+ +
+
    +
  1. Open Photos on your Mac and select the Live Photo
  2. +
  3. Go to File → Export → Export Unmodified Original
  4. +
  5. This saves two files: a .HEIC (still image) and a .MOV (video)
  6. +
  7. Drag the .MOV file onto the drop zone above
  8. +
+
+ You can also drag the Live Photo directly from Photos into Finder first, then drag the .MOV file here. +
+
+ +
+
    +
  1. AirDrop the Live Photo from iPhone to your Mac
  2. +
  3. It arrives as two files: .HEIC + .MOV
  4. +
  5. Drag the .MOV here
  6. +
+
+ This is the fastest way if you have a Mac nearby. The .MOV file is the exact original video from the Live Photo. +
+
+
- +
@@ -303,233 +379,6 @@

Your GIF