Photos.app doesn't play audio from videos recorded by Olympus camera
(Answering my own question.)

The problem is that the Olympus SZ-31MR encodes its audio as signed 16-bit PCM. This audio format is not supported by Photos. So the audio needs to be transcoded in order to play from Photos.

The command-line program ffmpeg can transcode audio streams while leaving the video streams unchanged. For example, here's how to transcode the audio to Apple Lossless (ALAC) and copy the video:

$ ffmpeg -i input.mov -vcodec copy -acodec alac output.mov


Experimentally, it seems that Photos doesn't mind if I edit the videos in its library, so here's a shell script that automates transcoding the Olympus's 16-bit PCM to Photos-compatible ALAC:

#!/bin/sh
# Convert movies in Photos library from 16-bit little-endian PCM to
# Apple Lossless.

set -e

# Location of Photos library
PHOTOS=~/"Pictures/Photos Library.photoslibrary/Masters"

# Directory for movie backups
BACKUPDIR=~/movie-backups
mkdir -p "$BACKUPDIR"

find "$PHOTOS" -name '*.MOV' | while read MOV; do
  if ffprobe -v fatal -show_streams -select_streams a -of flat -i "$MOV" |
    grep -q 'codec_name="pcm_s16le"'
  then
    echo "Transcoding $MOV..."
    BACKUP=$BACKUPDIR/$(echo "$MOV" | sed 's+_+__+g;s+/+_+g')
    TMP=$BACKUPDIR/tmp.mov
    ffmpeg -v fatal -y -nostdin -i "$MOV" -vcodec copy -acodec alac "$TMP"
    mv -- "$MOV" "$BACKUP"
    mv -- "$TMP" "$MOV"
  fi
done


This script is careful to keep the original movies in a backup directory in case something goes wrong, and it uses set -e and ffmpeg -v fatal to avoid continuing after an error, but it does overwrite the movies in the Photos library, so use it at your own risk.