0

Is it possible to create an AVAsset object with two urls, one for the audio and the other one for the video track?

I have tried it with an AVMutableComposition but it seems to load the entire content first and buffer it somewhere before the video+audio playback can be started. In the documentation of AVComposition, it says that file-based assets can be combined, but I need a way to combine url-based assets.

Or is there an option which can be set for the AVComposition in order to start the playback before loading the whole content?

Edit

This is how I tried it:

NSDictionary *urlAssetOptions = @{AVURLAssetPreferPreciseDurationAndTimingKey: [NSNumber numberWithBool:NO]};

AVMutableComposition *composition = [AVMutableComposition composition];


NSURL *audioUrl = [NSURL URLWithString:@"http://..."];
AVURLAsset *audioAsset = [AVURLAsset URLAssetWithURL:audioUrl options:urlAssetOptions];

AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];


NSURL *videoUrl = [NSURL URLWithString:@"http://..."];
AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:videoUrl options:urlAssetOptions];

AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];


AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition];
Ketan P
  • 4,259
  • 3
  • 30
  • 36
selcuksinan
  • 281
  • 3
  • 9

1 Answers1

1

The solution you use does not require to load whole content to start creation of the mutable composition nor to start playback of the composition you created. However, it requires loading of a part of media files to determine duration and tracks of each of files.

Below is working code which uses urls to mp3 and mp4 files found by google to create mutable composition and pass it to AVPlayerViewController. If you run the code you can notice that it starts playback pretty quickly but if you jump through the video timeline, you will find that it takes a long time to load data for requested time.

NSURL *audioURL = [NSURL URLWithString:@"http://www.mfiles.co.uk/mp3-downloads/Toccata-and-Fugue-Dm.mp3"];
AVAsset *audioAsset = [AVAsset assetWithURL:audioURL];

NSURL *videoURL = [NSURL URLWithString:@"http://thv1.uloz.to/6/c/4/6c4b50308843dd29c9176cc2c4961155.360.mp4?fileId=20389770"];
AVAsset *videoAsset = [AVAsset assetWithURL:videoURL];

CMTime duration;
if (CMTimeGetSeconds(audioAsset.duration) < CMTimeGetSeconds(videoAsset.duration)) {
    duration = audioAsset.duration;
} else {
    duration = videoAsset.duration;
}

NSError *error;

AVMutableComposition* mixAsset = [[AVMutableComposition alloc] init];

AVMutableCompositionTrack* audioTrack = [mixAsset addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, duration) ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error: &error];

AVMutableCompositionTrack* videoTrack = [mixAsset addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error: &error];

AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:mixAsset];

AVPlayerViewController* playerController = [AVPlayerViewController new];
playerController.player = [AVPlayer playerWithPlayerItem:playerItem];

[self presentViewController:playerController animated:YES completion:nil];