2015-04-08 14 views
5

Ciao a tutti Sto ritagliando un video preso dalla fotocamera su iPhone e poi ritagliandolo e riproducendolo in questo modo. Quando lo faccio, tuttavia, ottengo una strana linea verde intorno al lato inferiore e destro del video? Non sono sicuro del motivo per cui ciò sta accadendo o come risolverlo. Ecco come sto tagliando.Ritaglia il video in iOS, vedi una strana linea verde intorno al video

- (UIImageOrientation)getVideoOrientationFromAsset:(AVAsset *)asset 
{ 
    AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    CGSize size = [videoTrack naturalSize]; 
    CGAffineTransform txf = [videoTrack preferredTransform]; 

    if (size.width == txf.tx && size.height == txf.ty) 
     return UIImageOrientationLeft; //return UIInterfaceOrientationLandscapeLeft; 
    else if (txf.tx == 0 && txf.ty == 0) 
     return UIImageOrientationRight; //return UIInterfaceOrientationLandscapeRight; 
    else if (txf.tx == 0 && txf.ty == size.width) 
     return UIImageOrientationDown; //return UIInterfaceOrientationPortraitUpsideDown; 
    else 
     return UIImageOrientationUp; //return UIInterfaceOrientationPortrait; 
} 


- (AVAssetExportSession*)applyCropToVideoWithAsset:(AVAsset*)asset AtRect:(CGRect)cropRect OnTimeRange:(CMTimeRange)cropTimeRange ExportToUrl:(NSURL*)outputUrl ExistingExportSession:(AVAssetExportSession*)exporter WithCompletion:(void(^)(BOOL success, NSError* error, NSURL* videoUrl))completion 
{ 

// NSLog(@"CALLED"); 
    //create an avassetrack with our asset 
    AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 

//create a video composition and preset some settings 
AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoComposition]; 
videoComposition.frameDuration = CMTimeMake(1, 30); 

CGFloat cropOffX = cropRect.origin.x; 
CGFloat cropOffY = cropRect.origin.y; 
CGFloat cropWidth = cropRect.size.width; 
CGFloat cropHeight = cropRect.size.height; 
// NSLog(@"width: %f - height: %f - x: %f - y: %f", cropWidth, cropHeight, cropOffX, cropOffY); 

videoComposition.renderSize = CGSizeMake(cropWidth, cropHeight); 

//create a video instruction 
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
instruction.timeRange = cropTimeRange; 

AVMutableVideoCompositionLayerInstruction* transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack]; 

UIImageOrientation videoOrientation = [self getVideoOrientationFromAsset:asset]; 

CGAffineTransform t1 = CGAffineTransformIdentity; 
CGAffineTransform t2 = CGAffineTransformIdentity; 

switch (videoOrientation) { 
    case UIImageOrientationUp: 
     t1 = CGAffineTransformMakeTranslation(clipVideoTrack.naturalSize.height - cropOffX, 0 - cropOffY); 
     t2 = CGAffineTransformRotate(t1, M_PI_2); 
     break; 
    case UIImageOrientationDown: 
     t1 = CGAffineTransformMakeTranslation(0 - cropOffX, clipVideoTrack.naturalSize.width - cropOffY); // not fixed width is the real height in upside down 
     t2 = CGAffineTransformRotate(t1, - M_PI_2); 
     break; 
    case UIImageOrientationRight: 
     t1 = CGAffineTransformMakeTranslation(0 - cropOffX, 0 - cropOffY); 
     t2 = CGAffineTransformRotate(t1, 0); 
     break; 
    case UIImageOrientationLeft: 
     t1 = CGAffineTransformMakeTranslation(clipVideoTrack.naturalSize.width - cropOffX, clipVideoTrack.naturalSize.height - cropOffY); 
     t2 = CGAffineTransformRotate(t1, M_PI ); 
     break; 
    default: 
     NSLog(@"no supported orientation has been found in this video"); 
     break; 
} 

CGAffineTransform finalTransform = t2; 
[transformer setTransform:finalTransform atTime:kCMTimeZero]; 

//add the transformer layer instructions, then add to video composition 
instruction.layerInstructions = [NSArray arrayWithObject:transformer]; 
videoComposition.instructions = [NSArray arrayWithObject: instruction]; 

//Remove any prevouis videos at that path 
[[NSFileManager defaultManager] removeItemAtURL:outputUrl error:nil]; 

if (!exporter){ 
    exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality] ; 
} 
// assign all instruction for the video processing (in this case the transformation for cropping the video 
exporter.videoComposition = videoComposition; 
exporter.outputFileType = AVFileTypeQuickTimeMovie; 
if (outputUrl){ 
    exporter.outputURL = outputUrl; 
    [exporter exportAsynchronouslyWithCompletionHandler:^{ 
     switch ([exporter status]) { 
      case AVAssetExportSessionStatusFailed: 
       NSLog(@"crop Export failed: %@", [[exporter error] localizedDescription]); 
       if (completion){ 
        dispatch_async(dispatch_get_main_queue(), ^{ 
         completion(NO,[exporter error],nil); 
        }); 
        return; 
       } 
       break; 
      case AVAssetExportSessionStatusCancelled: 
       NSLog(@"crop Export canceled"); 
       if (completion){ 
        dispatch_async(dispatch_get_main_queue(), ^{ 
         completion(NO,nil,nil); 
        }); 
        return; 
       } 
       break; 
      default: 
       break; 
     } 
     if (completion){ 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       completion(YES,nil,outputUrl); 
      }); 
     } 

    }]; 
} 

return exporter; 
} 

E poi gioco e chiamo il raccolto in questo modo.

AVAsset *assest = [AVAsset assetWithURL:self.videoURL]; 


NSString * documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
NSString *exportPath = [documentsPath stringByAppendingFormat:@"/croppedvideo.mp4"]; 
NSURL *exportUrl = [NSURL fileURLWithPath:exportPath]; 


AVAssetExportSession *exporter = [AVAssetExportSession exportSessionWithAsset:assest presetName:AVAssetExportPresetLowQuality]; 


[self applyCropToVideoWithAsset:assest AtRect:CGRectMake(self.view.frame.size.width/2 - 57.5 - 5, self.view.frame.size.height/2 - 140, 115, 85) OnTimeRange:CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(assest.duration.value, 1)) 
        ExportToUrl:exportUrl ExistingExportSession:exporter WithCompletion:^(BOOL success, NSError *error, NSURL *videoUrl) { 
AVPlayer *player = [AVPlayer playerWithURL:videoUrl]; 

AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:player]; 
layer.frame = CGRectMake(125, 365, 115, 115); 
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]; 
[view.layer addSublayer:layer]; 
[self.view addSubview:view]; 
[player play]; 

Se volete testare questo, il codice solo bisogno di essere copiato e incollato e quindi impostare un video, e vedrete che cosa sto parlando.

Grazie per il tempo di aiutarmi, so che è un bel po 'di codice.

risposta

8

Ci sono requisiti di larghezza per gli encoder iOS o il formato video stesso. Prova a rendere la tua larghezza pari o divisibile per 4.

Non ero a conoscenza dell'esistenza di un requisito simile per l'altezza, ma potrebbe valere anche la pena di provarlo.

Non l'ho mai trovato documentato, ma richiedere l'uniformità ha un certo senso di h.264 utilizza uno spazio colore 4: 2: 0 yuv, dove la componente UV è metà della dimensione (in entrambe le dimensioni) di il canale Y, che ha le dimensioni generali del video. Se quelle dimensioni non fossero pari, le dimensioni UV non sarebbero integrali.

p.s. il suggerimento in questi casi è il misterioso colore verde. Penso che corrisponda a 0, 0, 0 in YUV.

+0

che doveva essere fatto sia per la larghezza e l'altezza, ma wow questo è così strano – iqueqiorio

+0

Cool. Era un multiplo di 2 o 4? –

+0

divisibile per 2. – iqueqiorio

2

La risposta di @Rhythmic mi ha salvato la giornata.

Nella mia app, ho bisogno di video quadrati come dimensioni dello schermo. Quindi per iPhone 5 questo arriva a 320 pixel e per iPhone 6 questo diventa 375 pixel.

Quindi mi sono imbattuto nello stesso problema di linea verde per la risoluzione di iPhone 6. Poiché la larghezza della sua dimensione dello schermo è 375 pixel. E non è divisibile per 2 o 4.

di uscire da questo abbiamo fatto questi cambiamenti

AVMutableVideoComposition *MainCompositionInst = [AVMutableVideoComposition videoComposition]; 
    MainCompositionInst.instructions = [NSArray arrayWithObject:MainInstruction]; 
    MainInstruction.timeRange = range; 

    MainCompositionInst.frameDuration = VideoFrameDuration; //Constants 
    MainCompositionInst.renderScale = VideoRenderScale; //Constants 

    if ((int)SCREEN_WIDTH % 2 == 0) 
     MainCompositionInst.renderSize = CGSizeMake(SCREEN_WIDTH, SCREEN_WIDTH); 
    else // This does the trick 
     MainCompositionInst.renderSize = CGSizeMake(SCREEN_WIDTH+1, SCREEN_WIDTH+1); 

Spero che questo aiuti. Basta aggiungere un altro pixel ad esso in modo che diventi divisibile per 2 o 4.

Grazie

+1

spiegazione intelligente, ho visto la risposta @Ritmica, in realtà è una bella risposta. ma quando è questione di poco tempo. hai vinto il sorteggio. ;) quindi +1 per te. – Vats