Why doesn't this video play on iOS?-Collection of common programming errors


  • Dominic P

    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 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

    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.