2012-05-18 6 views
12

Zrobiłem R & D i odniosłem sukces, w jaki sposób uzyskać ramki pod względem obrazów z pliku wideo odtwarzanego w MPMoviePlayerController.Tworzenie wideo z ramek iPhone

Otrzymuje wszystkie ramki z tego kodu i zapisuje wszystkie obrazy w jednym szyku.

for(int i= 1; i <= moviePlayerController.duration; i++) 
{ 
    UIImage *img = [moviePlayerController thumbnailImageAtTime:i timeOption:MPMovieTimeOptionNearestKeyFrame]; 
    [arrImages addObject:img]; 
} 

Teraz pytanie brzmi: Po zmianie pliku obrazu, np. Dodaniu emocji do zdjęć, a także dodaniu filtrów, takich jak; film prawdziwy, czarno-biały, Jak możemy ponownie stworzyć wideo i zapisać ten sam film w katalogu dokumentów z tą samą liczbą klatek na sekundę i bez utraty jakości wideo.

Po zmianie niektórych zdjęć wykonałem poniższy kod, aby ponownie zapisać ten film.

- (void) writeImagesAsMovie:(NSString*)path 
{ 
    NSError *error = nil; 
    UIImage *first = [arrImages objectAtIndex:0]; 
    CGSize frameSize = first.size; 
    AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL: 
            [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie 
                   error:&error]; 
    NSParameterAssert(videoWriter); 

    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
            AVVideoCodecH264, AVVideoCodecKey, 
            [NSNumber numberWithInt:640], AVVideoWidthKey, 
            [NSNumber numberWithInt:480], AVVideoHeightKey, 
            nil]; 
    AVAssetWriterInput* writerInput = [[AVAssetWriterInput 
             assetWriterInputWithMediaType:AVMediaTypeVideo 
             outputSettings:videoSettings] retain]; 

    AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor 
                assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput 
                sourcePixelBufferAttributes:nil]; 

    NSParameterAssert(writerInput); 
    NSParameterAssert([videoWriter canAddInput:writerInput]); 
    [videoWriter addInput:writerInput]; 

    [videoWriter startWriting]; 
    [videoWriter startSessionAtSourceTime:kCMTimeZero]; 

    int frameCount = 0; 
    CVPixelBufferRef buffer = NULL; 
    for(UIImage *img in arrImages) 
    { 
     buffer = [self newPixelBufferFromCGImage:[img CGImage] andFrameSize:frameSize]; 

      if (adaptor.assetWriterInput.readyForMoreMediaData) 
      { 
       CMTime frameTime = CMTimeMake(frameCount,(int32_t) kRecordingFPS); 
       [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime]; 

       if(buffer) 
        CVBufferRelease(buffer); 
      } 
     frameCount++; 
    } 

    [writerInput markAsFinished]; 
    [videoWriter finishWriting]; 
} 


- (CVPixelBufferRef) newPixelBufferFromCGImage: (CGImageRef) image andFrameSize:(CGSize)frameSize 
{ 
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, 
          nil]; 
    CVPixelBufferRef pxbuffer = NULL; 
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width, 
              frameSize.height, kCVPixelFormatType_32ARGB, (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, 
               kCGImageAlphaNoneSkipFirst); 
    NSParameterAssert(context); 
    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); 
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
              CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 

    return pxbuffer; 
} 

Jestem nowy w tym temacie, więc proszę pomóż mi rozwiązać to pytanie.

+0

Można użyć http://stackoverflow.com/ pytania/7873423/iphone-sdk-create-a-video-from-uiimage – Jasmit

+0

Czy otrzymałeś na to rozwiązanie? Czy możesz przesłać rozwiązanie, jeśli to możliwe? –

+0

dlaczego chcesz ponownie konwertować jako wideo? używaj tylko zdjęć ... –

Odpowiedz

7
+0

Witam, czy jest coś zaktualizowanego dla Swifta? Wszystkie te linki wydają się stare. Staramy się połączyć obrazy i filmy w jeden główny film, w którym obrazy muszą być widoczne jako oddzielne "wideo" w głównym filmie wideo. Załóżmy na przykład 1 obraz i 1 jeden film. W głównym filmie obraz pojawia się przez 3 sekundy, a następnie wideo jest odtwarzane. Jakieś rady na ten temat? Dzięki! – Crashalot

1

Musisz uzyskać obrazy dla każdej klatki, którą renderuje ekran. Użyłem prywatnego interfejsu API , aby zrobić to samo. i zapisz te obrazy jako Film używając AVAssetWriter.

pisałem owijkę do zrobienia co konieczne z zaledwie kilku linii kodu, spróbuj tego komponentu open source dla odniesienia:

https://www.cocoacontrols.com/controls/iqprojectvideo

+0

Prywatne API? Nie, po prostu nie. – Raptor

+0

Na pewno nie prześlesz swojego projektu do AppStore z tą biblioteką. Jest przeznaczony tylko do nagrywania wideo z zrzutów ekranu. Po prostu użyj i rzuć. Dlaczego więc prywatny interfejs API nie powinien być używany? –