2015-03-04 3 views
0

У меня есть 3 видеоролика, которые я выполняю с помощью AVMutableComposition, а затем воспроизвожу видео с помощью AVPlayer и захвата кадров с помощью AVPlayerItemVdeoOutput. Видеоряд выглядит следующим образом:Без рендеринга с AVMutableVideoComposition

[Logo Video - n seconds][Main video - m seconds][Logo Video - l seconds] 

код выглядит следующим образом:

// Build the composition. 
    pComposition   = [AVMutableComposition composition]; 

    // Fill in the assets that make up the composition 
    AVMutableCompositionTrack* pCompositionVideoTrack = [pComposition addMutableTrackWithMediaType: AVMediaTypeVideo preferredTrackID: 1]; 
    AVMutableCompositionTrack* pCompositionAudioTrack = [pComposition addMutableTrackWithMediaType: AVMediaTypeAudio preferredTrackID: 2]; 

    CMTime   time   = kCMTimeZero; 
    CMTimeRange  keyTimeRange = kCMTimeRangeZero; 
    for(AVAsset* pAssetsAsset in pAssets) 
    { 
     AVAssetTrack* pAssetsAssetVideoTrack = [pAssetsAsset tracksWithMediaType: AVMediaTypeVideo].firstObject; 
     AVAssetTrack* pAssetsAssetAudioTrack = [pAssetsAsset tracksWithMediaType: AVMediaTypeAudio].firstObject; 

     CMTimeRange  timeRange    = CMTimeRangeMake(kCMTimeZero, pAssetsAsset.duration); 

     NSError*  pVideoError    = nil; 
     NSError*  pAudioError    = nil; 

     if (pAssetsAssetVideoTrack) 
     { 
      [pCompositionVideoTrack insertTimeRange: timeRange ofTrack: pAssetsAssetVideoTrack atTime: time error: &pVideoError]; 
     } 
     if (pAssetsAssetAudioTrack) 
     { 
      [pCompositionAudioTrack insertTimeRange: timeRange ofTrack: pAssetsAssetAudioTrack atTime: time error: &pAudioError]; 
     } 

     if (pAssetsAsset == pKeyAsset) 
     { 
      keyTimeRange = CMTimeRangeMake(time, timeRange.duration); 
     } 

     NSLog(@"%@", [pVideoError description]); 
     NSLog(@"%@", [pAudioError description]); 

     time  = CMTimeAdd(time, pAssetsAsset.duration); 
    } 

В логотипе видео молчит и просто показать свой логотип. Я вручную создаю эти видеоролики, поэтому здесь все идеально. Однако «Основное видео» может привести к неправильной ориентации. Для борьбы с этим AVMutableVideoComposition выглядит как идеальный путь вперед. Поэтому я настраиваю простую композицию видео, которая делает простой setTransform следующим образом:

pAsset = pComposition; pPlayerItem = [AVPlayerItem playerItemWithAsset: pAsset]; pPlayer = [AVPlayer playerWithPlayerItem: pPlayerItem];

NSArray*  pPlayerTracks = [pAsset tracksWithMediaType: AVMediaTypeVideo]; 
    AVAssetTrack* pPlayerTrack = pPlayerTracks[0]; 

    pVideoCompositionLayerInstruction    = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstruction]; 
    [pVideoCompositionLayerInstruction setTransform: [[pKeyAsset tracksWithMediaType: AVMediaTypeVideo].firstObject preferredTransform] atTime: kCMTimeZero]; 

    pVideoCompositionInstruction     = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
    pVideoCompositionInstruction.backgroundColor = [[UIColor blackColor] CGColor]; 
    pVideoCompositionInstruction.timeRange   = keyTimeRange; 
    pVideoCompositionInstruction.layerInstructions = @[ pVideoCompositionLayerInstruction ]; 

    pVideoComposition        = [AVMutableVideoComposition videoComposition]; 
    pVideoComposition.renderSize     = [[pKeyAsset tracksWithMediaType: AVMediaTypeVideo].firstObject naturalSize]; 
    pVideoComposition.frameDuration     = [[pKeyAsset tracksWithMediaType: AVMediaTypeVideo].firstObject minFrameDuration]; 
    pVideoComposition.instructions     = @[ pVideoCompositionInstruction ]; 

    pPlayerItem.videoComposition = pVideoComposition; 

Однако, когда я пришел, чтобы воспроизвести видеопоследовательность, я не получаю никаких выходных данных. AVPlayerItemVideoOutput hasNewPixelBufferForItemTime всегда возвращает NO. Если я прокомментирую последнюю строку в приведенном выше коде (т. Е. Настройку videoComposition), то все работает по-прежнему (с видео с неправильной ориентацией). Кто-нибудь знает, что я делаю неправильно? Любые мысли очень ценятся!

ответ

2

Проблема в том, что keyTimeRange может не начинаться с нуля, если ваше видео с логотипом имеет ненулевую продолжительность. pVideoCompositionInstruction начнется в keyTimeRange.start, а не kCMTimeZero (когда AVMutableComposition начнет), который нарушает правила AVVideoCompositionInstructions

«Для первой инструкции в массиве, timeRange.start должен быть меньше или равен самому раннему времени которая воспроизведения или другой обработки будет предпринята попытка (как правило, kCMTimeZero)», в соответствии с the docs

чтобы решить эту проблему, установите pVideoComposition.instructions на массив, содержащий три AVMutableVideoCompositionInstruction объекты, каждый со своим собственным AVMutableVideoCompositionLayerInstruction в соответствии с преобразованием каждого AVAsset х. Временной диапазон для каждой из трех команд должен быть временем, в котором эти активы отображаются на композиционном треке. Убедитесь, что они точно совпадают.

+0

Спасибо, что это может помочь! – Goz

+0

К сожалению, это, похоже, не помогает :( – Goz

+0

Возможно, я немного поспешил сказать, что он не работает. Кажется, я получаю очень хорошие результаты (и это позволяет мне хорошо писать письма)! – Goz