2012-04-23 8 views
11

EDIT: La cosa più strana: sembra che quando si esegue questo codice da un'app completa tutto funzioni, ma sono sempre stato in esecuzione la creazione del film dal mio unit test, e solo lì non ha funzionato. Cercando di capire perché ...CATextLayer non appare in una AVMutableComposition quando si esegue da un'unità test

Sto cercando di combinare video + audio + testo utilizzando AVMutableComposition ed esportarlo in un nuovo video.

Il mio codice è basato sul AVEditDemo dal WWDC '10

ho aggiunto uno sfondo viola alla CATextLayer così posso sapere per certo che viene esportato nel film, ma nessun testo viene mostrato ... I ho provato a giocare con vari tipi di carattere, posizione, definizioni dei colori, ma non ho aiutato nulla, quindi ho deciso di postare il codice qui e vedere se qualcuno si è imbattuto in qualcosa di simile e può dirmi cosa mi manca.

Ecco il codice (self.audio e self.video sono AVURLAssets): è necessaria

CMTime exportDuration = self.audio.duration; 

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

AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
AVAssetTrack *videoTrack = [[self.video tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 

// add the video in loop until the audio ends 
CMTime currStartTime = kCMTimeZero; 
while (CMTimeCompare(currStartTime, exportDuration) < 0) { 
    CMTime timeRemaining = CMTimeSubtract(exportDuration, currStartTime); 
    CMTime currLoopDuration = self.video.duration; 

    if (CMTimeCompare(currLoopDuration, timeRemaining) > 0) { 
     currLoopDuration = timeRemaining; 
    } 
    CMTimeRange currLoopTimeRange = CMTimeRangeMake(kCMTimeZero, currLoopDuration); 

    [compositionVideoTrack insertTimeRange:currLoopTimeRange ofTrack:videoTrack 
            atTime:currStartTime error:nil]; 

    currStartTime = CMTimeAdd(currStartTime, currLoopDuration); 
} 

AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 

AVAssetTrack *audioTrack = [self.audio.tracks objectAtIndex:0]; 
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, self.audio.duration) ofTrack:audioTrack atTime:kCMTimeZero error:nil]; 

AVMutableVideoComposition *videoComposition; 

// the text layer part - THIS IS THE PART THAT DOESN'T WORK WELL 
CALayer *animatedTitleLayer = [CALayer layer]; 
CATextLayer *titleLayer = [[CATextLayer alloc] init]; 
titleLayer.string = @"asdfasdf"; 
titleLayer.alignmentMode = kCAAlignmentCenter; 
titleLayer.bounds = CGRectMake(0, 0, self.video.naturalSize.width/2, self.video.naturalSize.height/2); 
titleLayer.opacity = 1.0; 
titleLayer.backgroundColor = [UIColor purpleColor].CGColor; 

[animatedTitleLayer addSublayer:titleLayer]; 
animatedTitleLayer.position = CGPointMake(self.video.naturalSize.width/2.0, self.video.naturalSize.height/2.0); 

// build a Core Animation tree that contains both the animated title and the video. 
CALayer *parentLayer = [CALayer layer]; 
CALayer *videoLayer = [CALayer layer]; 
parentLayer.frame = CGRectMake(0, 0, self.video.naturalSize.width, self.video.naturalSize.height); 
videoLayer.frame = CGRectMake(0, 0, self.video.naturalSize.width, self.video.naturalSize.height); 
[parentLayer addSublayer:videoLayer]; 
[parentLayer addSublayer:animatedTitleLayer]; 

videoComposition = [AVMutableVideoComposition videoComposition]; 
videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; 

AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
passThroughInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, exportDuration); 
AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack]; 

passThroughInstruction.layerInstructions = [NSArray arrayWithObject:passThroughLayer]; 
videoComposition.instructions = [NSArray arrayWithObject:passThroughInstruction]; 

videoComposition.frameDuration = CMTimeMake(1, 30); 
videoComposition.renderSize = self.video.naturalSize; 

AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality]; 

exportSession.videoComposition = videoComposition; 
exportSession.outputURL = [NSURL fileURLWithPath:self.outputFilePath]; 
exportSession.outputFileType = AVFileTypeQuickTimeMovie; 

[exportSession exportAsynchronouslyWithCompletionHandler:^() { 
    // save the video ... 
}]; 
+0

Non sono sicuro .. Potrebbe essere questo potrebbe aiutare..http: //stackoverflow.com/questions/7205820/iphone-watermark-on-recorded-video –

+0

Grazie, sto facendo qualcosa di più o meno come ciò che è menzionato lì. Se qualcuno rileva la differenza fondamentale tra il mio codice e quello nella risposta pertinente, sarei molto grato. – yonix

+0

Hai provato a impostare la dimensione del carattere? –

risposta

0

ulteriori indagini, ma in questo momento AFAICT CATextLayer all'interno di un AVMutableVideoComposition semplicemente non funziona all'interno di un test di unità logica obiettivo, e questa funzione deve essere testata da un bersaglio regolare.

1

Mi sono imbattuto nello stesso problema in un contesto diverso. Nel mio caso, avevo spostato la preparazione di AVMutableComposition in un thread in background. Spostando nuovamente quella parte di preparazione nella sovrapposizione principale/thread sovrapposti di CATextLayer, funzionerà di nuovo correttamente.

Questo probabilmente non si applica esattamente al contesto di test dell'unità, ma suppongo che CATextLayer/AVFoundation dipenda da una parte di UIKit/AppKit in esecuzione/disponibile (un contesto di disegno? Uno schermo corrente?) In tale thread contesto, che potrebbe spiegare il fallimento che stiamo entrambi vedendo.

+0

Ciao Adam sai se è possibile unire immagini e video usando 'AVMutableCompositionTracks' (simile a come unisci i video insieme), o hai bisogno di' CALayers' per incorporare le immagini in un video unito. Domanda qui: http://stackoverflow.com/questions/34937862/merge-videos-images-in-avmutablecomposition-using-avmutablecompositiontrack – Crashalot

1

Ho avuto il problema che quasi tutto ha reso grande, anche le immagini con CALayer e il contenuto impostato su CGImage. Tranne il testo CGTextLayer, se impostassi un colore di sfondo su CGTextLayer, un beginTime e una durata perfettamente renderizzati, solo il testo effettivo non voleva apparire. Questo era tutto sul simulatore, poi l'ho eseguito sul telefono: ed è stato perfetto.

Conclusione: il simulatore rende piacevoli i video ... Finché non si utilizza CATextLayer.

0

Il mio problema era che avevo bisogno di impostare contenutiGravity = kCAGravityBottomLeft - altrimenti il ​​mio testo era fuori dallo schermo.

Problemi correlati