I am using ffmpeg to generate a segmented list of files in order to stream them to an iOS app. The list of files is generated fine but when it comes time to play them, the video needs to be downloaded in its entirety before playback starts. This behaviour seems to be the case on iOS, Safari and VLC.

Does anybody know why this is happening and how I can improve the performance of playback? I have complete control over how the files are recorded in iOS, as well as how they are processed. Here is a sample stream:


Here are my ffmpeg commands to generate the segments from the file:

ffmpeg -i joined.ts -flags -global_header -vcodec copy -acodec copy -map 0 -f segment -segment_time 2 -segment_list hls.m3u8 -segment_list_size 999999 -segment_format mpegts out%03d.ts

Here is the output of ffprobe on the file:

  libavutil      54.  7.100 / 54.  7.100
  libavcodec     56.  1.100 / 56.  1.100
  libavformat    56.  4.101 / 56.  4.101
  libavdevice    56.  0.100 / 56.  0.100
  libavfilter     5.  1.100 /  5.  1.100
  libavresample   2.  1.  0 /  2.  1.  0
  libswscale      3.  0.100 /  3.  0.100
  libswresample   1.  1.100 /  1.  1.100
  libpostproc    53.  0.100 / 53.  0.100
Input #0, mpegts, from 'joined.ts':
  Duration: 00:00:07.96, start: 1.441667, bitrate: 3899 kb/s
  Program 1 
      service_name    : Service01
      service_provider: FFmpeg
    Stream #0:0[0x100]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p, 1280x720, 24 fps, 24 tbr, 90k tbn, 180k tbc
    Stream #0:1[0x101](und): Audio: aac ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp, 222 kb/s

In order to have high performance video streaming, there needs to be a set of multiple variant video streams. In other words, videos encoded at various bitrates and resolutions, which are all referenced from a playlist file (.m3u8)

Video players that support adaptive-bitrate streams will then choose a stream that matches your network connection and are able to switch streams seamlessly as network conditions change. The reason the video I was trying to stream was taking so long to start playing was because I only had one stream at 720p resolution, so the player took really long to buffer before it would start playing.

I used the Http Live Streaming (HLS) standard created by Apple to generate an adaptive bitrate stream with 5 streams (which I generated using ffmpeg) and my video starts playing almost immediately.

Shameless plug: To make this simpler for developers and others out there, I've packaged the infrastructure we put together to generate HLS streams, with an iOS SDK which you can check out here: https://github.com/Storie/StorieCloudSDK

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.