A Weird Imagination

Playing Android motion photos

The problem#

My Android phone's camera app has an option to take a "motion photo", which, similar to the iOS "live photo" feature, records a short, silent video along with the photo. When viewing the photos on the phone, there's an option to play the video. But image viewer programs on my computer like Eye of GNOME (eog) do not support playing them.

The solution#

ExifTool (in Debian, the package name is libimage-exiftool-perl) can extract the video to a file using this example from a forum post:

exiftool -b -EmbeddedVideoFile photo.jpg > photo_motion.mp4

You can also play it directly without saving it to a file by piping to VLC:

exiftool -b -EmbeddedVideoFile photo.jpg | vlc -

The details#

Exif#

Exif is the standard for storing metadata along with photos. Its commonly used for things like identifying the camera settings, when the photo was taken, and where the photo was taken1.

In this case, it's also be used to store the video recorded along with the photo, as strange as it may sound to refer to a video larger than the photo as "metadata" of the photo.

Many image viewers have some way of viewing the Exif data. In Eye of GNOME, selecting "Properties" from the menu shows the most common metadata along with a "Show Details" button to show the exact values of all of the data. Looking there on a photo with a motion photo, I see an "XMP Other" section with a "GCamera:MotionPhoto" tag and some related tags indicating there's an item with a video/mp4 MIME type.

Extracting with ExifTool#

I happened upon this forum post explaining that the -b -EmbeddedVideoFile options would extract the motion photo. The -EmbeddedVideoFile flag tells it to output the tag named "EmbeddedVideoFile", but if you give just that option it says

Embedded Video File : (Binary data 3994570 bytes, use -b option to extract)

Since it does not contain text, you have to provide the -b option to tell it you actually want it to output binary data.

Note that for files that do not have an "EmbeddedVideoFile", both commands will output nothing at all, which can be used to check whether an image has a motion photo.

Playing the video#

The original example I found output the video to a file, but I thought it should be possible to avoid that step. I tried mplayer for this first as it's usually more flexible than VLC, but to my surprise piping to mplayer - failed with multiple copies of the following error:

Cannot seek backward in linear streams!
Seek failed

even though piping to vlc - as I suggest above works just fine.

This post suggests a workaround: mplayer - -cache 8092 does work by telling mplayer to keep around some cache to be able to seek backwards within. I originally tried a smaller cache size of 2048 which did not work, so you may need to adjust the value.

Extracting without ExifTool#

I also came across this script, which does not use ExifTool, instead using grep to find the offset of a binary string in the file. I did not try it myself, but it also is referencing different motion photo formats, so perhaps it may be necessary to read motion photos generated by different or older Android phones.

User-friendly viewer#

PhotoQt claims "Support for Motion Photos and Apple Live Photos", so if you can get it to run, it should also solve this problem.

But I had trouble getting it to actually run. As this Debian bug points out, it needs more dependencies to run than the package specifies. But even once I figured out what dependencies it needed to run, it segfaulted when actually viewing a motion photo.

I ran it under gdb to see if I could get more information:

$ gdb photoqt
GNU gdb (Debian 15.2-1) 15.2
[...]
(No debugging symbols found in photoqt)
(gdb) start 'photo.jpg'
Temporary breakpoint 1 at 0x920e0
Starting program: /usr/bin/photoqt 'photo.jpg'
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Temporary breakpoint 1, 0x00005555555e60e0 in main ()
(gdb) c

(The parts I actually typed at the (gdb) prompt were start 'photo.jpg' to actually run it and give it the command-line arguments and c to continue from the breakpoint it automatically set at the start of the program.)

After minimal interaction, it crashed and I typed bt to get a backtrace:

Thread 1 "photoqt" received signal SIGSEGV, Segmentation fault.
0x00007fffedd3a074 in XDisplayString () from /lib/x86_64-linux-gnu/libX11.so.6
(gdb) bt
#0  0x00007fffedd3a074 in XDisplayString ()
    at /lib/x86_64-linux-gnu/libX11.so.6
#1  0x00007fff96c05ee5 in __vaDriverInit_1_0 ()
    at /usr/lib/x86_64-linux-gnu/dri/nvidia_drv_video.so
#2  0x00007fffedc5536b in vaInitialize () at /lib/x86_64-linux-gnu/libva.so.2
#3  0x00007fffee64ca98 in ??? () at /lib/x86_64-linux-gnu/libavutil.so.59
#4  0x00007fffee63e82c in av_hwdevice_ctx_create ()
    at /lib/x86_64-linux-gnu/libavutil.so.59
#5  0x00007fffbc59dc9b in ??? ()
    at /usr/lib/x86_64-linux-gnu/qt6/plugins/multimedia/libffmpegmediaplugin.so
#6  0x00007fffbc5a104c in ??? ()
[...]

Once I saw the segfault's backtrace included references to libffmpegmediaplugin.so, I figured the problem was unlikely to be solved by installing more dependencies, so I decided to find some other way to view the motion photos, eventually finding the forum post I linked above.


  1. Phones often store the GPS coordinates of where you took the photo inside every photo you take by default. This can be a surprising privacy violation if you share such photos publicly, which is why most social media networks automatically remove this information

Comments

Have something to add? Post a comment by sending an email to comments@aweirdimagination.net. You may use Markdown for formatting.

There are no comments yet.