5

I can download the JPGs from my DCIM folder in my Pixel 2 and I know that the video is encoded inside the jpg, but I don't know what image viewer I can use to see the motion. I usually use Irfanview, but I haven't yet been able to find out how to make it show the motion. And I haven't found anyone talking about how to do it. Anyone know?

5

I did some experimenting based on the post by @jameshenstridge and came up with a simple PHP script that successfully split every google motion photo i threw at it.

<?php

  $src_arg = $argv[1];
  $src_dir = realpath(pathinfo($src_arg, PATHINFO_DIRNAME)); 

  echo "Scanning for files...\n";

  foreach (glob($src_arg) as $src) {

    $file = realpath($src);

    if (!is_dir($file) && in_array(strtoupper(pathinfo($file, PATHINFO_EXTENSION)), ["JPEG", "JPG"])) {

      echo "\tProcessing: " . $file . "\n";

      $filesize = filesize($file);
      echo "\t\tFile size: " . $filesize . "\n";

      $handle = fopen($file, "rb");
      $data = fread($handle, $filesize);
      fclose($handle);

      $eoi_pos = strpos($data, "\xFF\xD9\x00\x00\x00\x18");
      echo "\t\tEOI segment position: " . $eoi_pos . "\n";

      if ($eoi_pos !== FALSE) {
        $output_base = $src_dir . DIRECTORY_SEPARATOR . pathinfo($file, PATHINFO_FILENAME);
        echo "\t\tSaving photo...\n";
        file_put_contents($output_base . "_photo.jpg", substr($data, 0, $eoi_pos + 2));
        echo "\t\tSaving video...\n";
        file_put_contents($output_base . "_video.mp4", substr($data, $eoi_pos + 2));
      } else {
        echo "\t\tSKIPPING - File does not appear to be a Google motion photo.\n";
      }

    }

  }

  echo "Done.\n";

?>

It should work on Windows and Linux. You just pass a path as the first argument and it will split any files that it believes are motion photos. You can use wildcards. It's non-destructive - the source file(s) are not deleted.

Some example uses:

php google_motion_photo_splitter.php c:\test\file.jpg
php google_motion_photo_splitter.php c:\test\*.jpg
php google_motion_photo_splitter.php c:\test\*
4

I haven't seen any software to view them other than on the Google Photos website. I was curious about this so started pulling apart one of the photos from my phone, and here's what I found:

  1. The image file appears to be a standard JPEG image, but continues on after the End of Image segment (0xFF 0xD9).

  2. exiftool reports unrecognised MakerNotes. I suspect this custom metadata identifies the file as a motion photo.

  3. If transfer all the data after the EOI segment to a separate file, you'll have a standard MPEG-4 container. I got a GStreamer crash when trying to play it, but ffmpeg seems to be able to handle it and displayed the following metadata:

    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'foo.mp4':
      Metadata:
        major_brand     : mp42
        minor_version   : 0
        compatible_brands: isommp42
        creation_time   : 2018-07-07T20:37:57.000000Z
        com.android.version: 8.1.0
      Duration: 00:00:01.87, start: 0.000000, bitrate: 20283 kb/s
        Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, smpte170m/smpte170m/unknown), 1024x768, 20161 kb/s, SAR 1:1 DAR 4:3, 30.01 fps, 30 tbr, 90k tbn, 180k tbc (default)
        Metadata:
          creation_time   : 2018-07-07T20:37:57.000000Z
          handler_name    : VideoHandle
        Stream #0:1(eng): Data: none (mett / 0x7474656D), 108 kb/s (default)
        Metadata:
          creation_time   : 2018-07-07T20:37:57.000000Z
          handler_name    : MetadHandle
        Stream #0:2(eng): Data: none (mett / 0x7474656D), 0 kb/s (default)
        Metadata:
          creation_time   : 2018-07-07T20:37:57.000000Z
          handler_name    : MetadHandle
    Unsupported codec with id 0 for input stream 1
    Unsupported codec with id 0 for input stream 2
    

    So, that's a 1.87 second H.264 video with resolution 1024x768, which seems to roughly match up with what I see from Google's apps/website (a drop in resolution and change in aspect ratio).

I know it isn't a complete solution, but it might be enough to get started on a tool to extract the videos.

0

Although the question is for Windows, I think it's appropriate to post my script to play it from command line on Linux here:

https://gist.github.com/vi/5de17bb8d4ea91b8c28e79e0bac6c3cb

#!/bin/bash

if [[ -z "$1"  || "$1" == --help || "$1" == "-?" ]]; then
    echo "Usage: mvimg_play MVIMG_20190806_183324.jpg [other files]"
    echo "Plays Google's Motion Photo using mpv. Depends on exiftool, mktemp, bash and mpv."
    exit 0
fi

FOUND=0
ARGS=()

TORM=()
TOKILL=()

function cleanup() {
    for i in "${TORM[@]}"; do
        rm -f "$i"
    done
    for p in ${TOKILL[@]}; do
        wait $p
    done
}

trap "cleanup" EXIT

for i in "$@"; do
    O=$(exiftool -t $i  | grep -F 'Micro Video Offset' | cut -f 2-2)
    if [[ -z "$O" ]]; then
        # wrong file? Just appending to playlist as is
        ARGS+=($i)
    else
        FOUND=1
        S=$(find $i -printf '%s')
        T=`mktemp`

        ARGS+=("$T")
        dd if="$i" skip=$((S-O)) iflag=skip_bytes of="$T" 2> /dev/null &
        TOKILL+=($!)
        TORM+=("$T")
    fi
done

if [[ $FOUND == 0 ]]; then
    echo "EXIF tag wasn't detected in specified files. Maybe exiftool does not work?" >&2
fi

mpv "${ARGS[@]}"

Maybe it can be used on Windows as well, with enough Mingw/Cygwin hackery.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.