J'essaie d'obtenir une image à partir d'une vidéo, utilisez cette image pour générer un film fixe La première étape fonctionne bien, mais la deuxième étape a généré une vidéo mal formée après que je définis AppleSpreferredtrackTransform = TRUE
Image normale extraite de la vidéo
Vidéo malformée générée à partir de l'image
p>
Comment est-ce arrivé? Une image normale a généré une vidéo mal formée? En outre, si je mettez le blocageMoviefiefromimage.GeneratemoviewImageHImagehImage dans # 2 L'application s'écrasera sur cgcontextDrawimage (contexte, cgrecture (0, 0, cadresize.Width, imagesze.Height), image); p>
J'ai fait comme ci-dessous (à Swift): P>
+ (void)generateMovieWithImage:(CGImageRef)image completionBlock:(GenerateMovieWithImageCompletionBlock)handler { NSLog(@"%@", image); NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent: [@"tmpgen" stringByAppendingPathExtension:@"mov" ] ]; NSURL *videoUrl = [NSURL fileURLWithPath:path]; if ([[NSFileManager defaultManager] fileExistsAtPath:path] ) { NSError *error; if ([[NSFileManager defaultManager] removeItemAtPath:path error:&error] == NO) { NSLog(@"removeitematpath %@ error :%@", path, error); } } // TODO: image need to rotate programly, not in hand int width = (int)CGImageGetWidth(image); int height = (int)CGImageGetHeight(image); NSError *error = nil; AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:videoUrl fileType:AVFileTypeQuickTimeMovie error:&error]; NSParameterAssert(videoWriter); NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:width], AVVideoWidthKey, [NSNumber numberWithInt:height], AVVideoHeightKey, nil]; AVAssetWriterInput* writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] ; //retain should be removed if ARC NSParameterAssert(writerInput); NSParameterAssert([videoWriter canAddInput:writerInput]); [videoWriter addInput:writerInput]; AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:nil ]; // 2) Start a session: NSLog(@"start session"); [videoWriter startWriting]; [videoWriter startSessionAtSourceTime:kCMTimeZero]; //use kCMTimeZero if unsure dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL); [writerInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^{ if ([writerInput isReadyForMoreMediaData]) { // 3) Write some samples: // Or you can use AVAssetWriterInputPixelBufferAdaptor. // That lets you feed the writer input data from a CVPixelBuffer // thatâs quite easy to create from a CGImage. CVPixelBufferRef sampleBuffer = [self newPixelBufferFromCGImage:image]; if (sampleBuffer) { CMTime frameTime = CMTimeMake(150,30); [adaptor appendPixelBuffer:sampleBuffer withPresentationTime:kCMTimeZero]; [adaptor appendPixelBuffer:sampleBuffer withPresentationTime:frameTime]; CFRelease(sampleBuffer); } } // 4) Finish the session: [writerInput markAsFinished]; [videoWriter endSessionAtSourceTime:CMTimeMakeWithSeconds(5, 30.0) ] ; //optional can call finishWriting without specifiying endTime // [videoWriter finishWriting]; //deprecated in ios6 NSLog(@"to finnish writing"); [videoWriter finishWritingWithCompletionHandler:^{ NSLog(@"%@",videoWriter); NSLog(@"finishWriting.."); handler(videoUrl); ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init]; [library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:path] completionBlock: ^(NSURL *assetURL, NSError *error){ if( error != nil) { NSLog(@"writeVideoAtPathToSavedPhotosAlbum error: %@" , error); } }]; }]; //ios 6.0+ }]; } + (CVPixelBufferRef) newPixelBufferFromCGImage: (CGImageRef)image { NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; CVPixelBufferRef pxbuffer = NULL; CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image) ); NSLog(@"width:%f", frameSize.width); NSLog(@"height:%f", frameSize.height); CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width, frameSize.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)options, &pxbuffer); NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); CVPixelBufferLockBaseAddress(pxbuffer, 0); void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); NSParameterAssert(pxdata != NULL); CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(pxdata, frameSize.width, frameSize.height, 8, 4*frameSize.width, rgbColorSpace, (CGBitmapInfo)kCGImageAlphaNoneSkipFirst ); NSParameterAssert(context); CGContextConcatCTM(context, CGAffineTransformIdentity); CGContextDrawImage(context, CGRectMake(0, 0, frameSize.width, frameSize.height), image); CGColorSpaceRelease(rgbColorSpace); CGContextRelease(context); CVPixelBufferUnlockBaseAddress(pxbuffer, 0); return pxbuffer; }
3 Réponses :
Essayez ceci:
(requestTime, image, actualTime, result, error) -> Void in if result == AVAssetImageGeneratorResult.Succeeded { let img : UIImage = UIImage(CGImage: image)! // retain UIImageWriteToSavedPhotosAlbum(img,nil,nil,nil) // synchron GenerateMovieFromImage.generateMovieWithImage(image, completionBlock:{ (genMovieURL) in handler(genMovieURL) })
Cela ne fonctionne pas aussi, j'essaie d'utiliser mon iPad pour tester si c'est le problème de mon iPhone. Mais je pense que le problème est peut-être la matrice de transformation de l'avexte ou de la graphique.
Ajoutez ce chèque: Si (! [Vidéofriter commence]) et vérifiez le résultat de l'annexePixBuffer. Vous pouvez voir une erreur comme cette vidéoriter.Error.
Tout retour Oui, pas d'erreur enregistrée. Et j'ai essayé mais je ne peux pas faire fonctionner le programme sur mon iPad (il ne peut pas jailbreak)
Il semble que j'ai eu une certaine amélioration.
en fonction (CVPixElbufferref) Newpixelbufferfromcgimage: (cgimageref) Image P>
Modification: P>
AVAssetWriterInput* writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] ; //retain should be removed if ARC
Résolu par une hauteur multiple avec 2, mais je ne sais pas pourquoi: CGContextref context = cgbitmapcontextexcreate (pxdata, cadresize.width, cadresize.Height * 2, 8, 4 * cadresize.Width, rgbcolorspace (CGBITMAPInfo) KCGIMAGELPHANONESKIPFIRAT); CgcontextDrawimage (contexte, cgrectument (0, 0, cadresize.width, encadrement.Height * 2), image);
Les codeurs vidéo que vous utilisez peuvent avoir des restrictions de largeur, par ex. la largeur doit être divisible deux ou quatre. Avez-vous essayé de changer votre largeur?
J'ai aussi eu cette erreur lorsque j'ai essayé de créer une vidéo avec un tableau d'images et de fichiers de musique. C'est dû au rapport vidéo. Alors vérifiez le cadre pour la composition vidéo. Pour votre référence: http://size43.com/jQueryvideotool.html P>