Objective-C Download Smooth Streaming Video

I am wondering if there is an Objective-C way to download an mp4 video that is configured to stream in Smooth Streaming format. So far, I've tried using AFNetworking, NSInputStream and MPMoviePlayerController to try to access the raw video data, but they were empty in every attempt.

I would then like to take this video data and save it as mp4 to disk, which will be played offline. The url looks something like this:

     http://myurl.com/videoname.ism/manifest(format=m3u8-aapl)

      

+3


source to share


1 answer


I'm going to assume that you are asking for an HTTP Live Streaming video as shown by your example URL instead of a smooth streaming video. If not, please leave a comment and I'll edit the answer to talk about Smooth Streaming.

HTTP Live Streaming Video Structure

There are several versions of HTTP Live Streaming (HLS), new ones of which have added correct support for multilingual audio and titles, making this scenario much more difficult. I am assuming that you have no interest in such functions and will focus on the simple case.

HLS has a three-layer structure:

  • There is a Master Playlist in the root directory . This is what the webserver provides when you request the video root url. It contains links to one or more media playlists.
  • A Media Player presents all videos for one specific configuration. For example, if the media is encoded using two quality levels (such as 720p and 1080p), there will be two media players, one for each. A media playlist contains a list of links to media segments that actually contain media data.
  • media segments are MPEG transport streams containing a fraction of the data streams, usually about 10 seconds per file.

When multilingual features are out of date, you might want to consider HLS videos, as multiple individual videos are separated by 10 seconds - all videos contain the same content but with a different level of quality.

Each of the above objects - the main playlist, media player, each media segment - is individually loaded by the player using standard HTTP file download mechanisms.

Combining the pieces back

All the information the media player requires is present in the media segments - you can basically ignore the main playlist and media player as their sole purpose is to provide you with URLs for the media segments.

Fortunately, the MPEG Transport Stream format is very simple in nature. All you have to do to merge media segments is merge them together. What is it, really!

pseudocode



I'm going to assume you're not asking how to make HTTP requests using Objective-C, as there are many other stack overflow answers on this topic. Instead, I will focus on the algorithm you need to implement.

First, you just need to download the main playlist.

masterPlaylist = download(rootUrl);

      

The main playlist contains both comment lines and data lines. Each line of data is a link to a media playlist. Note that for the lowest quality level for HLS, there will usually only be an audio stream. Let's say you care what the first quality level is in the file, for simplicity's sake.

masterPlaylistLines = masterPlaylist.split('\n');
masterPlaylistDataLines = filter(masterPlaylistLines, x => !x.startsWith("#"));
firstMasterPlaylistDataLine = masterPlaylistDataLines[0];

      

This data line will contain the relative URL in the media playlist. Download it. Your code for adding URLs should be smart and understand how to create relative URLs, not just string concatenation.

mediaPlaylist = download(rootUrl + firstMasterPlaylistDataLine);

      

The media playlist, in turn, is formatted the same, but contains links to media segments. Download them all and add them together.

mediaPlaylistLines = mediaPlaylist.split('\n');
mediaPlaylistDataLines = filter(mediaPlaylistLines, x => !x.startsWith("#"));

foreach (dataLine : mediaPlaylistDataLines)
{
    // URL concatenation code is assumed to be smart, not just string concatenation.
    mediaSegment = download(rootUrl + firstMasterPlaylistDataLine + dataLine);
    appendToFile("Output.ts", mediaSegment);
}

      

The end result will be one MPEG Transport Stream file, playable on most modern media players. You can use various free tools like FFmpeg if you want to convert them to a different format.

+5


source







All Articles