I’ve been a Transmit user since version 3 and have always liked it (and Panic, the company behind Transmit). When Transmit 5 was released with support for Amazon Drive, I was eager to try it.

Amazon lets Prime members store an unlimited number of photos, including RAW files — which is unique among cloud storage providers, to my knowledge — on Amazon Drive for free. It seemed like a good addition to my backup plan, and it would give me access to all of my photos on my phone or iPad (assuming I knew which ones I needed, since the Amazon Drive app doesn’t show previews of RAW files).

But because my photos are on an external hard drive, and Amazon doesn’t allow the sync folder to be on an external drive, there were a couple of things I didn’t like. First, I had to upload photos by dragging them to the Amazon Drive app, so I couldn’t do anything close to an automatic upload. Second, there was no good way to see my files in a traditional files-and-folders interface. I was hoping Transmit 5 could solve these problems.

Setting up the connection

Setting up the connection was simple. Just add a new server by clicking Servers > Add New Server or by clicking the + button at the bottom of the servers pane.

Select “Amazon Drive,” click Next, and you’ll be presented with an Amazon login screen.

  New server setup screen
Set up a new server

After you log in, Transmit will set up the new connection, and you’ll see a screen like the one below where you can change various attributes like the name of the connection.

  Amazon Drive setup screen
Amazon Drive configuration

Click Save, and you’re done.

On the front end, it works like any other connection in Transmit. You can browse the files in a Finder-like view, and you can preview them with Quick Look. (The files are still on a remote server, though, so Quick Look isn’t as fast as it is when previewing a local file.) One problem solved.

  Files and folders on Amazon Drive
There are my photos

Synchronization

One of Transmit’s great features is its ability to synchronize a local folder and a remote folder. If I could use Transmit to synchronize my Pictures folder on my external hard drive with my Pictures folder on Amazon Drive, that would solve the other problem.

Unlike in Transmit 4, where the Sync screen was behind a button that had both an intuitive icon and a “Sync” label, the Sync screen in Transmit 5 is hidden behind this unlabeled button that doesn’t really scream “synchronize” to me: Transmit Sync button

But once I found it, the screen looked (interface updates aside) and worked exactly like it did in Transmit 4.

  Transmit Sync screen
Same basic screen with an updated design

I simulated the sync first, and it took about one and a half minutes to determine that the local folder contained 378 files that weren’t on Amazon Drive. I proceeded to synchronize the folders, and everything went fine for about an hour. (I think Transmit is probably slower to upload that Amazon’s own app, but the extra features offered by Transmit are worth the trade-off to me.)

After about an hour (and all except 15 files successfully uploaded), uploads started failing. According to the message in Transmit, the Amazon token had expired; I suspect this was due to rate limiting. I simply closed the connection, reopened it, and synchronized again to fix the problem.

Purchase

This is just a nice touch, but the Panic website has Apple Pay enabled, and it was super easy to use. My MacBook is too old to support it, but it worked perfectly on my iPad. I just tapped the “Buy With  Pay” link and authorized it via Touch ID. My serial number was displayed in the browser and sent via email almost immediately.

In the end, Transmit 5 solved my problems with Amazon Drive well enough that I thought it was worth the $35 price tag. (It’s currently discounted; the regular price will be $45.)

Here’s Ben Gibbard covering a great ’90s song, Teenage Fanclub’s “The Concept.” I have to admit I didn’t like it at first, but it hooked me on the second listen. Can’t wait to hear the rest of the album.

 Ben Gibbard's New Album Is Teenage Fanclub's "Bandwagonesque," Covered Song For Song

Publishing Live Photos with Jekyll and LivePhotosKit JS

I recently posted three Live Photos using LivePhotosKit JS. My blog is built with Jekyll, and I wanted the Live Photos to display correctly on large and small screens. Since getting it to work took some trial and error, and there aren’t a lot of helpful resources other than Apple’s documentation, I wrote this post to explain how I got it to work.

The Apple way

First I tried Apple’s recommended method, adding the appropriate data- attributes to a <div> element:

<div
    data-live-photo
    data-photo-src="{{ site.url }}/images/live-photos/IMG_7280.JPG"
    data-video-src="{{ site.url }}/images/live-photos/IMG_7280.MOV"
    style="width: 640px; height: 852px">         
</div>

But I ran into a problem. It looked fine on a big screen, but the picture overflowed the <div>’s parent container on the iPhone screen in portrait orientation.

  Screen shot of the webpage on macOS
It looked the way I expected on macOS.
  Screen shot of the broken webpage on iOS
On iOS... not so great.

If you want it to be viewable on different screen sizes, Apple’s method doesn’t really work.

Media queries

My first thought was to use media queries to control the size of the <div>, but LivePhotosKit complained about the <div> having a width and height of zero. After a little more experimentation, I concluded that CSS wouldn’t work. It seems that LivePhotosKit expects the <div> to have a style attribute with a non-zero width and height.

Solution

To appropriately set expectations, I’ll introduce this next part by saying that my front-end development skills are pretty amateur, and my solution isn’t elegant. This is how I finally got the Live Photos to render correctly on large and small screens.

In the post’s front matter, I listed the photo, the video and a caption for each Live Photo I wanted to display on the page:

live_photos:
    -
        photo: IMG_7280.JPG
        video: IMG_7280.MOV
        caption: Taxiing in the rain in Atlanta
    -
        photo: IMG_7337.JPG
        video: IMG_7337.MOV
        caption: Sunset at <a href="https://maps.google.com/?q=37.0046,-122.188">Shark Fin Cove</a>

    -
        photo: IMG_7341.JPG
        video: IMG_7341.MOV
        caption: There were lots of rabbits on the cliffs above the cove.

In the body of the post, I put an empty <div> to serve as the container for the Live Photos:

<div id="live-photo-container"></div>

Finally, I have an include called scripts.html that’s included in my post template. I added this to the end of scripts.html:

{% if page.live_photos %}
<script>
    $(document).ready(function() {
        var divWidth;
        var divHeight;
        if (screen.width < 640) {
            divWidth = "320px";
            divHeight = "426px";
        }
        else {
            divWidth = "640px";
            divHeight = "852px";
        }
        {% for p in page.live_photos %}
        $("#live-photo-container").append('<div data-live-photo data-photo-src="{{ site.url }}/images/live-photos/{{ p.photo }}" data-video-src="{{ site.url }}/images/live-photos/{{ p.video }}" style="width: ' + divWidth + '; height: ' + divHeight + '">');
        $("#live-photo-container").append('<p class="live-photo-caption">{{ p.caption }}</p>');
        {% endfor %}
    });
</script>
<script src="https://cdn.apple-livephotoskit.com/lpk/1/livephotoskit.js"></script>
{% endif %}

{% if page.live_photos %} ensures that the JavaScript is executed, and LivePhotosKit JS is loaded, only if the post contains Live Photos.

The script is wrapped in jQuery’s $(document).ready() function to make sure the <div> with ID live-photo-container is present before the Live Photo <div> elements are added to the page. If the screen is less than 640 pixels wide, the width is set to 320px, and the height is set to 426px. Otherwise, the width and height are set to 640px and 852px.

Then for each Live Photo defined in the post’s front matter, jQuery is used to append a <div> with the proper attributes to the <div> with ID live-photo-container. Finally, LivePhotosKit JS is loaded to do the heavy lifting.

It’s not an elegant solution. It only handles two broad screen sizes, and the Live Photo isn’t centered on iOS. But it works well enough for now.

Screen shot of the webpage rendered correctly on iOS
You can actually see the whole image on iOS now.

A few oddities

In case you want to try this for yourself, here are a few issues I encountered.

When I was testing locally on my MacBook (using bundle exec jekyll serve), Firefox was the only browser that would actually render both the photo and the video elements on macOS. Safari and Chrome just rendered the static photo and showed in place of the normal control. Neither Safari nor Chrome would play the video on iOS. They behaved in the same way as Safari and Chrome on macOS.

The Live Photos rendered correctly in all browsers (sort of; see below) only after I moved everything to my web server.

In my experience, browser compatibility wasn’t consistent with the list of supported browsers in Apple’s documentation. On macOS, Live Photos on the web are best viewed in Chrome. Safari and Firefox work, but the performance is a little worse when transitioning from photo to video.

On iOS, Safari was the only browser that worked for me, but it crashed frequently, usually after playing one of the videos for the first time. Chrome on iOS didn’t work at all for me. It crashed almost immediately on both my iPhone 6S and my iPad Pro.

A few Live Photos I took on a recent trip to California, posted using LivePhotosKit JS. To see the video, hover your mouse pointer over the “LIVE” button in the top right corner of the photo. On a phone or tablet, tap and hold the picture.

For best results, use Safari if you’re on iOS. Chrome seems to work best on macOS. It works fine on macOS but seems to be a little buggy on iOS. (Apple says Chrome may work on Android, and any of the major browsers should work on Windows, but I haven’t tried those.)

(I'm still working on getting the Live Photos to display on the front page. Click here to view them.)

Interesting fact: Newark Liberty International Airport is EWR because in the U.S., “N” can only be used by the Navy.

 Why the 'O' in San Francisco's Airport Code, SFO?