Why doesn't this video play on iOS?

3

I'm having trouble getting my mp4 video to play on any iOS device. I'm testing on an iPhone with iOS 6 and an iPad running iOS 7. When I upload the video to my server and enter the URL directly on the device I get a black screen and an alert that says "The operation could not be completed." The same problem happens when I try to play the video on a web page using a <video> tag.

The video plays fine on Android and Windows. You can find an example video here. Here are my ffmpeg settings.

ffmpeg -i uncompressed.avi -s 854x480 -c:v libx264 -pix_fmt yuv420p
    -preset:v veryslow -profile:v baseline -crf 23
    -c:a libfdk_aac -flags +qscale -global_quality 3 -afterburner 1
    -ar 48000 -cutoff 19000
    output.mp4

And here is the output from ffmpeg when encoding a video.

ffmpeg version N-55064-g3cd8aaa Copyright (c) 2000-2013 the FFmpeg developers
  built on Jul 29 2013 12:59:12 with gcc 4.8.0 (GCC)
  configuration: --arch=x86_64 --target-os=mingw32 --cross-prefix=/home/dominic/
GitHub/ffmpeg-windows-build-helpers/sandbox/mingw-w64-x86_64/bin/x86_64-w64-ming
w32- --pkg-config=pkg-config --enable-gpl --enable-libsoxr --enable-libx264 --en
able-avisynth --enable-libxvid --enable-libmp3lame --enable-version3 --enable-zl
ib --enable-librtmp --enable-libvorbis --enable-libtheora --enable-libspeex --en
able-libopenjpeg --enable-gnutls --enable-libgsm --enable-libfreetype --enable-f
ontconfig --enable-libass --enable-libutvideo --enable-libopus --disable-w32thre
ads --enable-frei0r --enable-filter=frei0r --enable-libvo-aacenc --enable-bzlib
--enable-libxavs --extra-cflags=-DPTW32_STATIC_LIB --enable-libopencore-amrnb --
enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-libschroedinger --enab
le-libbluray --enable-libvpx --enable-libilbc --enable-static --disable-shared -
-enable-nonfree --enable-libfdk-aac --enable-runtime-cpudetect
  libavutil      52. 40.100 / 52. 40.100
  libavcodec     55. 19.100 / 55. 19.100
  libavformat    55. 12.102 / 55. 12.102
  libavdevice    55.  3.100 / 55.  3.100
  libavfilter     3. 81.103 /  3. 81.103
  libswscale      2.  4.100 /  2.  4.100
  libswresample   0. 17.103 /  0. 17.103
  libpostproc    52.  3.100 / 52.  3.100
Input #0, avi, from 'cure.avi':
  Metadata:
    date            : 2013-10-12T21:16:56.00708-07:00
  Duration: 00:00:30.07, start: 0.000000, bitrate: 88517 kb/s
    Stream #0:0: Video: lagarith (LAGS / 0x5347414C), rgb24, 854x480, 23.98 tbr,
 23.98 tbn, 23.98 tbc
    Stream #0:1: Audio: pcm_s32le ([1][0][0][0] / 0x0001), 96000 Hz, stereo, s32
, 6144 kb/s

[libx264 @ 000000000209f620] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2
[libx264 @ 000000000209f620] profile Constrained Baseline, level 4.0
[libx264 @ 000000000209f620] 264 - core 133 r2339 585324f - H.264/MPEG-4 AVC cod
ec - Copyleft 2003-2013 - http://www.videolan.org/x264.html - options: cabac=0 r
ef=16 deblock=1:0:0 analyse=0x1:0x131 me=umh subme=10 psy=1 psy_rd=1.00:0.00 mix
ed_ref=1 me_range=24 chroma_me=1 trellis=2 8x8dct=0 cqm=0 deadzone=21,11 fast_ps
kip=1 chroma_qp_offset=-2 threads=12 lookahead_threads=1 sliced_threads=0 nr=0 d
ecimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 k
eyint=250 keyint_min=23 scenecut=40 intra_refresh=0 rc_lookahead=60 rc=crf mbtre
e=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00

[libfdk_aac @ 00000000020d8f80] Note, the VBR setting is unsupported and only wo
rks with some parameter combinations
Output #0, mp4, to 'cure-baseline.mp4':
  Metadata:
    date            : 2013-10-12T21:16:56.00708-07:00
    encoder         : Lavf55.12.102
    Stream #0:0: Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 854x48
0, q=-1--1, 24k tbn, 23.98 tbc
    Stream #0:1: Audio: aac (libfdk_aac) ([64][0][0][0] / 0x0040), 48000 Hz, ste
reo, s16
Stream mapping:
  Stream #0:0 -> #0:0 (lagarith -> libx264)
  Stream #0:1 -> #0:1 (pcm_s32le -> libfdk_aac)

video:4373kB audio:442kB subtitle:0 global headers:0kB muxing overhead 0.333461%

[libx264 @ 000000000209f620] frame I:16    Avg QP:22.72  size: 46151
[libx264 @ 000000000209f620] frame P:705   Avg QP:27.08  size:  5303
[libx264 @ 000000000209f620] mb I  I16..4: 42.7%  0.0% 57.3%
[libx264 @ 000000000209f620] mb P  I16..4:  1.9%  0.0%  1.6%  P16..4: 32.1%  9.7
%  4.8%  0.6%  0.2%    skip:48.9%
[libx264 @ 000000000209f620] coded y,uvDC,uvAC intra: 47.7% 59.1% 19.9% inter: 1
2.9% 9.2% 0.9%
[libx264 @ 000000000209f620] i16 v,h,dc,p: 31% 21%  7% 41%
[libx264 @ 000000000209f620] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 11% 13%  6% 11% 15%
13% 14% 10%  9%
[libx264 @ 000000000209f620] i8c dc,h,v,p: 48% 21% 18% 13%
[libx264 @ 000000000209f620] ref P L0: 74.5% 10.1%  6.1%  2.0%  1.6%  1.4%  1.2%
  0.5%  0.4%  0.4%  0.4%  0.4%  0.3%  0.3%  0.3%  0.2%
[libx264 @ 000000000209f620] kb/s:1191.01

Dominic P

Posted 2013-10-13T05:53:07.973

Reputation: 391

Answers

3

Ok, after banging my head against the wall on this one for some time, it seems the answer was the H.264 level. It looks like ffmpeg defaulted to level 4.0 and that does not seem to be supported by iOS.

When I set the level down to 3.1, I got an error about the DPB size from ffmpeg. So, I added a -refs 11 flag and now the video plays. I was even able to get the main profile to work as long as the level was still set at 3.1 and I didn't exceed the DPB size specified for that level.

Dominic P

Posted 2013-10-13T05:53:07.973

Reputation: 391

It should be noted though that it isn't recommended to use more than 5 reference frames for live action footage (http://www.avidemux.org/admWiki/doku.php?id=tutorial:h.264), so this could maybe use some tweaking. Also ffmpeg have updated their compatibility docs: https://trac.ffmpeg.org/wiki/Encode/H.264#Compatibility

– Dominic P – 2015-02-19T02:10:00.823