$30 off During Our Annual Pro Sale. View Details »

Building a Playlist with AV Foundation

Building a Playlist with AV Foundation

Slides from my talk at iOSDevCampDC 2013 about building playlists with AV Foundation.

Josh Johnson

August 24, 2013
Tweet

More Decks by Josh Johnson

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

  3. Why just music?
    AV Foundation
    Audio-only
    Classes

    View Slide

  4. View Slide

  5. View Slide

  6. UIKit
    Core Audio Core Media Core Animation
    Media Player
    AV Foundation

    View Slide

  7. MPMusicPlayerController

    View Slide

  8. 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];

    View Slide

  9. View Slide

  10. UIKit
    Core Audio Core Media Core Animation
    Media Player
    AV Foundation

    View Slide

  11. Players

    View Slide

  12. AVPlayer
    AVQueuePlayer

    View Slide

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

    View Slide

  14. 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];

    View Slide

  15. Assets

    View Slide

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

    View Slide

  17. Time

    View Slide

  18. 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#>)

    View Slide

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

    View Slide

  20. Demo

    View Slide

  21. View Slide

  22. Compositions and
    AudioMix

    View Slide

  23. AVComposition

    View Slide

  24. AVCompositionTrack

    View Slide

  25. AVCompositionTrack
    AVCompositionTrack

    View Slide

  26. AVCompositionTrack (Video)
    AVCompositionTrack (Audio)

    View Slide

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

    View Slide

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

    View Slide

  29. 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];

    View Slide

  30. A composition is an
    asset.

    View Slide

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

    View Slide

  32. 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];

    View Slide

  33. Demo

    View Slide

  34. View Slide

  35. Questions?
    You can even ask why so much Hasselhoff?

    View Slide

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

    View Slide