#ios #objective-c #avplayeritem #avurlasset #avcomposition
#iOS #objective-c #avplayeritem #avurlasset #avcomposition
Вопрос:
Возможно ли создать AVAsset
объект с двумя URL-адресами, один для аудио, а другой для видеодорожки?
Я пробовал это с помощью an AVMutableComposition
, но, похоже, сначала загружается весь контент и где-то его буферизует, прежде чем можно будет начать воспроизведение видео аудио. В документации AVComposition
говорится, что ресурсы на основе файлов могут быть объединены, но мне нужен способ объединения ресурсов на основе url.
Или есть опция, которую можно установить для AVComposition
того, чтобы начать воспроизведение перед загрузкой всего содержимого?
Редактировать
Вот как я это пробовал:
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];
Комментарии:
1. Самый простой способ .. создать два AVAssets.
2. @Gagan_iOS Как мне тогда создать объект AVPlayerItem с этими двумя AVAssets?
Ответ №1:
Используемое вами решение не требует загрузки всего содержимого для начала создания изменяемой композиции или для начала воспроизведения созданной вами композиции. Однако для определения длительности и дорожек каждого из файлов требуется загрузка части медиафайлов.
Ниже приведен рабочий код, который использует URL-адреса для файлов mp3 и mp4, найденных Google, для создания изменяемой композиции и передачи ее в AVPlayerViewController. Если вы запустите код, вы заметите, что он начинает воспроизведение довольно быстро, но если вы перейдете по временной шкале видео, вы обнаружите, что загрузка данных за запрошенное время занимает много времени.
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: amp;error];
AVMutableCompositionTrack* videoTrack = [mixAsset addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error: amp;error];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:mixAsset];
AVPlayerViewController* playerController = [AVPlayerViewController new];
playerController.player = [AVPlayer playerWithPlayerItem:playerItem];
[self presentViewController:playerController animated:YES completion:nil];
Комментарии:
1. Все еще работает сегодня в Swift 4: gist.github.com/gonzo-oin/b300dc7391f83bddd9bcd60aae4614b7