AVFoundation to persist playlist , downloads two different video tracks.

Hi,

I'm trying to download hls playlist video track by parsing specific bitrate / resolution.

Downloads work perfectly fine. But we need to download specific video track variant from the manifest. So I parse bitrate & resolution via AVAssetDownloadTaskMinimumRequiredMediaBitrateKey & AVAssetDownloadTaskMinimumRequiredPresentationSizeKey.

But AVAggregateAssetDownloadTask always downloads the specific ( parsed ) bitrate variant of the video track segments along with the lower resolution video track segments. This makes the download size to go higher than expected.

Is this the expected behaviour or am I doing something wrong ?

I tried the sample source from https://developer.apple.com/documentation/avfoundation/offline_playback_and_storage/using_avfoundation_to_play_and_persist_http_live_streams & it has the same behaviour.

This is how my manifest file looks like.

#EXT-X-VERSION:7
## Created with Unified Streaming Platform  (version=1.11.3-24483)
#EXT-X-SESSION-KEY:METHOD=SAMPLE-AES,URI="skd://xxxxxxx",KEYFORMAT="com.apple.streamingkeydelivery",KEYFORMATVERSIONS="1"

# AUDIO groups
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aacl-96",LANGUAGE="en",NAME="eng",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2",URI="vod-idx-audio_eng=96000.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aacl-160",LANGUAGE="en",NAME="eng",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2",URI="vod-idx-audio_eng=160000.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-ec-3-192",LANGUAGE="en",NAME="eng",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="6",URI="vod-idx-audio_eng_1=192000.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aacl-320",LANGUAGE="en",NAME="eng",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="6",URI="vod-idx-audio_eng_2=320000.m3u8"

# SUBTITLES groups
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="textstream",LANGUAGE="da",NAME="Dansk",DEFAULT=YES,AUTOSELECT=YES,URI="vod-idx-textstream_dan=1000.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="textstream",LANGUAGE="fi",NAME="Suomi",AUTOSELECT=YES,URI="vod-idx-textstream_fin=1000.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="textstream",LANGUAGE="no",NAME="Norsk",AUTOSELECT=YES,URI="vod-idx-textstream_nor=1000.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="textstream",LANGUAGE="sv",NAME="Svenska",AUTOSELECT=YES,URI="vod-idx-textstream_swe=1000.m3u8"

# variants
#EXT-X-STREAM-INF:BANDWIDTH=416000,CODECS="mp4a.40.2,avc1.4D4015",RESOLUTION=480x270,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-aacl-96",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=300000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=799000,CODECS="mp4a.40.2,avc1.4D401E",RESOLUTION=640x360,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-aacl-160",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=600000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1385000,CODECS="mp4a.40.2,avc1.4D401E",RESOLUTION=768x432,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-aacl-320",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=1000000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2021000,CODECS="mp4a.40.2,avc1.4D401F",RESOLUTION=960x540,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-aacl-320",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=1600000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3505000,CODECS="mp4a.40.2,avc1.64001F",RESOLUTION=1280x720,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-aacl-320",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=3000000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=5837000,CODECS="mp4a.40.2,avc1.640032",RESOLUTION=1920x1080,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-aacl-320",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=5200000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=513000,CODECS="ec-3,avc1.4D4015",RESOLUTION=480x270,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-ec-3-192",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=300000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=831000,CODECS="ec-3,avc1.4D401E",RESOLUTION=640x360,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-ec-3-192",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=600000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1255000,CODECS="ec-3,avc1.4D401E",RESOLUTION=768x432,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-ec-3-192",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=1000000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1891000,CODECS="ec-3,avc1.4D401F",RESOLUTION=960x540,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-ec-3-192",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=1600000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3375000,CODECS="ec-3,avc1.64001F",RESOLUTION=1280x720,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-ec-3-192",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=3000000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=5707000,CODECS="ec-3,avc1.640032",RESOLUTION=1920x1080,FRAME-RATE=25,VIDEO-RANGE=SDR,AUDIO="audio-ec-3-192",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
vod-idx-video=5200000.m3u8

# variants
#EXT-X-STREAM-INF:BANDWIDTH=98000,CODECS="mp4a.40.2",AUDIO="audio-aacl-96",SUBTITLES="textstream"
vod-idx-audio_eng=96000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=163000,CODECS="mp4a.40.2",AUDIO="audio-aacl-160",SUBTITLES="textstream"
vod-idx-audio_eng=160000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=325000,CODECS="mp4a.40.2",AUDIO="audio-aacl-320",SUBTITLES="textstream"
vod-idx-audio_eng_2=320000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=195000,CODECS="ec-3",AUDIO="audio-ec-3-192",SUBTITLES="textstream"
vod-idx-audio_eng_1=192000.m3u8

# keyframes
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=40000,CODECS="avc1.4D4015",RESOLUTION=480x270,VIDEO-RANGE=SDR,URI="keyframes/vod-idx-video=300000.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=80000,CODECS="avc1.4D401E",RESOLUTION=640x360,VIDEO-RANGE=SDR,URI="keyframes/vod-idx-video=600000.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=133000,CODECS="avc1.4D401E",RESOLUTION=768x432,VIDEO-RANGE=SDR,URI="keyframes/vod-idx-video=1000000.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=212000,CODECS="avc1.4D401F",RESOLUTION=960x540,VIDEO-RANGE=SDR,URI="keyframes/vod-idx-video=1600000.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=398000,CODECS="avc1.64001F",RESOLUTION=1280x720,VIDEO-RANGE=SDR,URI="keyframes/vod-idx-video=3000000.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=689000,CODECS="avc1.640032",RESOLUTION=1920x1080,VIDEO-RANGE=SDR,URI="keyframes/vod-idx-video=5200000.m3u8"

And this is how I create the download task

let preferredMediaSelection = asset.urlAsset.preferredMediaSelection
if #available(iOS 14.0, *) {
      guard let task =
          assetDownloadURLSession.aggregateAssetDownloadTask(with: asset.urlAsset,
                                    mediaSelections: [preferredMediaSelection],
                                    assetTitle: asset.stream.name,
                                    assetArtworkData: nil,
                                    options:
                                    [AVAssetDownloadTaskMinimumRequiredMediaBitrateKey:5200000, AVAssetDownloadTaskMinimumRequiredPresentationSizeKey: CGSize(width: 1920, height: 1080)])
      else { return }

      task.taskDescription = asset.stream.name
      task.resume()
    }

Any help will be appreciated. thanks

Replies

I found the reason for this behaviour. It seems like when you have 2 different audio channel variants in the master playlist ( in my case it was 2 & 6 channels ) , AVFoundation downloads the video variants for both those audio versions. Removing / filtering out 5.1 audio ( 6 channel ) from the master playlist solve the issue & downloaded only one video variant.