Slide 1

Slide 1 text

Building a Playlist with AV Foundation Josh Johnson @jnjosh | αjnjosh | jnjosh.com

Slide 2

Slide 2 text

or: A crash course to AV Foundation  with music. Josh Johnson @jnjosh | αjnjosh | jnjosh.com

Slide 3

Slide 3 text

Why just music? AV Foundation Audio-only Classes

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

UIKit Core Audio Core Media Core Animation Media Player AV Foundation

Slide 7

Slide 7 text

MPMusicPlayerController

Slide 8

Slide 8 text

MPMusicPlayerController *player =  [MPMusicPlayerController applicationMusicPlayer]; ! // Access the music through the iPod Library Access API MPMediaQuery *query = [MPMediaQuery artistsQuery]; ! [query addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:@"David Hasselhoff" forProperty:MPMediaItemPropertyArtist comparisonType:MPMediaPredicateComparisonEqualTo]]; [query setGroupingType:MPMediaGroupingArtist]; ! // Let the player have the query [player setQueueWithQuery:query]; ! // Listen to the musical stylings of David Hasselhoff [player play];

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

UIKit Core Audio Core Media Core Animation Media Player AV Foundation

Slide 11

Slide 11 text

Players

Slide 12

Slide 12 text

AVPlayer AVQueuePlayer

Slide 13

Slide 13 text

AVURLAsset *asset =  [AVURLAsset URLAssetWithURL:<# hasselhoff.mp3 #> options:nil]; ! ! AVPlayerItem *playerItem =  [[AVPlayerItem alloc] initWithAsset:asset]; ! ! AVPlayer *audioPlayer =  [[AVPlayer alloc] initWithPlayerItem:playerItem]; ! ! [audioPlayer play];

Slide 14

Slide 14 text

AVURLAsset *asset =  [AVURLAsset URLAssetWithURL:<# hasselhoff.mp3 #> options:nil]; ! AVPlayerItem *item1 =  [[AVPlayerItem alloc] initWithAsset:asset]; ! // setup asset2 and item2 ! AVQueuePlayer *audioPlayer =  [AVQueuePlayer queuePlayerWithItems:@[ item1, item2 ]]; ! ! [audioPlayer play];

Slide 15

Slide 15 text

Assets

Slide 16

Slide 16 text

AVURLAsset *asset =  [AVURLAsset URLAssetWithURL:song.url options:nil]; ! ! [asset loadValuesAsynchronouslyForKeys:@[ @"tracks" ] completionHandler:^{  ! NSArray *assetTracks = [asset tracksWithMediaType:AVMediaTypeAudio]; // ... ! }];

Slide 17

Slide 17 text

Time

Slide 18

Slide 18 text

CMTime fiveSeconds = CMTimeMake(5, 1); CMTime halfSecond = CMTimeMake(1, 2); CMTime thirtyFPS = CMTimeMake(1, 30); CMTimeAdd(<#CMTime addend1#>, <#CMTime addend2#>) ! CMTimeSubtract(<#CMTime minuend#>, <#CMTime subtrahend#>) ! CMTimeShow(<#CMTime time#>)

Slide 19

Slide 19 text

CMTimeRange range = CMTimeRangeMake(CMTimeMake(5, 1), CMTimeMake(5, 1)); ! CMTimeRangeMake(<#CMTime start#>, <#CMTime duration#>) ! CMTimeRangeContainsTime(<#CMTimeRange range#>, <#CMTime time#>) ! CMTimeRangeShow(<#CMTimeRange range#>)

Slide 20

Slide 20 text

Demo

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

Compositions and AudioMix

Slide 23

Slide 23 text

AVComposition

Slide 24

Slide 24 text

AVCompositionTrack

Slide 25

Slide 25 text

AVCompositionTrack AVCompositionTrack

Slide 26

Slide 26 text

AVCompositionTrack (Video) AVCompositionTrack (Audio)

Slide 27

Slide 27 text

AVCompositionTrackSegment seconds 50-60 of “the_hoff.mp3” AVCompositionTrackSegment seconds 0-10 of “the_hoff.mp3”

Slide 28

Slide 28 text

AVURLAsset *asset =  [AVURLAsset URLAssetWithURL:song.url options:nil]; ! ! [asset loadValuesAsynchronouslyForKeys:@[ @"tracks" ] completionHandler:^{  ! NSArray *assetTracks = [asset tracksWithMediaType:AVMediaTypeAudio]; // ... ! }];

Slide 29

Slide 29 text

AVMutableComposition *composition = [AVMutableComposition composition]; AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; AVAssetTrack *audioTrack = [assetTracks lastObject]; [track insertTimeRange:audioTrack.timeRange ofTrack:audioTrack atTime:<# CMTime #> error:&error];

Slide 30

Slide 30 text

A composition is an asset.

Slide 31

Slide 31 text

AVComposition *compositionAsset = [composition copy]; ! ! AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:compositionAsset]; ! ! AVPlayer *audioPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem]; ! ! // Observe `status` for AVPlayerStatusReadyToPlay ! ! [audioPlayer play];

Slide 32

Slide 32 text

AVMutableAudioMixInputParameters *params =  [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track]; ! CMTime crossfadeDuration = ...; CMTimeRange crossfadeEndRange = CMTimeRangeMake(CMTimeSubtract(CMTimeRangeGetEnd(songRange), crossfadeDuration), crossfadeDuration); ! // set the ramp [params setVolumeRampFromStartVolume:1.0 toEndVolume:0.0 timeRange:crossfadeEndRange]; [audioMixParameters addObject:params]; ! AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix]; [audioMix setInputParameters:audioMixParameters]; [playerItem setAudioMix:fadeMix];

Slide 33

Slide 33 text

Demo

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

Questions? You can even ask why so much Hasselhoff?

Slide 36

Slide 36 text

Thank you! Josh Johnson @jnjosh | αjnjosh | jnjosh.com