Upgrade to Pro — share decks privately, control downloads, hide ads and more …

よくある動画アプリのあれを実装したい。

 よくある動画アプリのあれを実装したい。

Instagram, Vine, SlideStory のような動画アプリで動画を保存する仕込みが気になったので実装しました。

nakajijapan

May 28, 2014
Tweet

More Decks by nakajijapan

Other Decks in Technology

Transcript

  1. BQQಓ৔
    !OBLBKJKBQBO
    Α͋͘Δಈը
    ΞϓϦͷ͋Ε
    Λ࣮૷͍ͨ͠

    View Slide

  2. !OBLBKJKBQBO
    4PGUXBSF&OHJOFFS
    (.01&1"#0JOD

    View Slide

  3. ৺ྶࣸਅΞϓϦ͓Θ͔Γ͍͚ͨͩͨͩΖ͏͔

    View Slide

  4. ৺ྶಈըΞϓϦ΋͏Ұ౓͝ཡ͍ͨͩ͜͏

    View Slide

  5. "7'PVOEBUJPO
    ࠓճ΋ʂʂ

    View Slide

  6. ͋ͷಈըΛอଘ͢ΔΠ
    ϯλʔϑΣʔε͕ؾʹ
    ͳͬͨͷͰ࣮૷ͨ͠ɻ

    View Slide

  7. ࢓༷

    View Slide

  8. εΫϦʔϯΛλον
    ͨ͠ΒಈըΛอଘ։
    ࢝ͯ͠εΫϦʔϯ͔
    Β཭ΕͨΒอଘऴྃ

    View Slide

  9. "7$BQUVSF4FTTJPO

    View Slide

  10. "7$BQUVSF0VUQVU

    View Slide

  11. "7$BQUVSF0VUQVU
    ɾ"7$BQUVSF.PWJF'JMF0VUQVU
    ɾ"7$BQUVSF4UJMM*NBHF0VUQVU
    ɾ"7$BQUVSF7JEFP%BUB0VUQVU
    ɾ"7$BQUVSF"VEJP%BUB0VUQVU

    View Slide

  12. "7$BQUVSF0VUQVU
    ɾ"7$BQUVSF.PWJF'JMF0VUQVU
    ɾ'JMFT
    ɾ"7$BQUVSF4UJMM*NBHF0VUQVU
    ɾ*NBHF
    ɾ"7$BQUVSF7JEFP%BUB0VUQVU
    ɾ"7$BQUVSF"VEJP%BUB0VUQVU
    ɾ-JWFEBUB

    View Slide

  13. "7$BQUVSF0VUQVU
    ɾ"7$BQUVSF.PWJF'JMF0VUQVU
    ɾ'JMFT
    ɾ"7$BQUVSF4UJMM*NBHF0VUQVU
    ɾ*NBHF
    ɾ"7$BQUVSF7JEFP%BUB0VUQVU
    ɾ"7$BQUVSF"VEJP%BUB0VUQVU
    ɾ-JWFEBUB

    View Slide

  14. "7$BQUVSF"VEJP%BUB0VUQVU
    AVCaptureVideoDataOutputSampleBufferDelegate
    AVCaptureAudioDataOutputSampleBufferDelegate
    "7$BQUVSF7JEFP%BUB0VUQVU

    View Slide

  15. #pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate
    !
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
    fromConnection:(AVCaptureConnection *)connection
    {
    !
    if (!CMSampleBufferDataIsReady(sampleBuffer)) {
    NSLog(@"sampleBuffer data is not ready");
    }
    !
    CMTime currentTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    !
    if (self.touching) {
    !
    // Video
    if ([captureOutput isKindOfClass:[AVCaptureVideoDataOutput class]]) {
    [self addSamplebuffer:sampleBuffer withWriterInput:(AVAssetWriterInput *)self.assetWriterInputVideo];
    }
    // Audio
    else if ([captureOutput isKindOfClass:[AVCaptureAudioDataOutput class]]) {
    [self addSamplebuffer:sampleBuffer withWriterInput:(AVAssetWriterInput *)self.assetWriterInputAudio];
    }
    !
    }
    !
    self.recordStartTime = currentTime;
    }
    AVCaptureVideoDataOutputSampleBufferDelegate
    AVCaptureAudioDataOutputSampleBufferDelegate

    View Slide

  16. 8SJUJOH

    View Slide

  17. εΫϦʔϯΛλον
    ͨ͠ΒಈըΛอଘ։
    ࢝ͯ͠εΫϦʔϯ͔
    Β཭ΕͨΒอଘऴྃ

    View Slide

  18. εΫϦʔϯΛλον
    ͨ͠ΒಈըΛอଘ։
    ࢝ͯ͠εΫϦʔϯ͔
    Β཭ΕͨΒอଘऴྃ
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

    View Slide

  19. "7"TTFU8SJUFS
    "7"TTFU8SJUFS*OQVU

    View Slide

  20. 4UBSU8SJUJOH
    อଘର৅ͷϑΝΠϧΛࢦఆͯ͠ॳظԽ
    ϝσΟΞλΠϓΛࢦఆ
    TFU&YQFDUT.FEJB%BUB*O3FBM5JNFΛ0/ʹ͢Δ
    "7"TTFU8SJUFSʹ"7"TTFU8SJUFS*OQVUΛ૊ΈࠐΉ
    ॻ͖ࠐΈ։࢝

    View Slide

  21. 4UBSU8SJUJOH
    // AVAssetWriter
    self.assetWriter = [AVAssetWriter assetWriterWithURL:self.outputURL
    fileType:AVFileTypeQuickTimeMovie
    error:&error];
    !
    !
    // movie
    NSDictionary *videoSetting = self.videoSettings;
    self.assetWriterInputVideo = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
    outputSettings:videoSetting];
    [self.assetWriterInputVideo setExpectsMediaDataInRealTime:YES];
    !
    !
    // audio
    NSDictionary *audioSetting = self.audioSettings;
    self.assetWriterInputAudio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
    outputSettings:audioSetting];
    [self.assetWriterInputAudio setExpectsMediaDataInRealTime:YES];
    !
    !
    [self.assetWriter addInput:self.assetWriterInputVideo];
    [self.assetWriter addInput:self.assetWriterInputAudio];
    !
    // queue
    self.movieWritingQueue = dispatch_queue_create("Movie Writing Queue", DISPATCH_QUEUE_SERIAL);
    !
    // Record
    [self.assetWriter startWriting];
    [self.assetWriter startSessionAtSourceTime:self.recordStartTime];

    View Slide

  22. 4UBSU8SJUJOH
    // AVAssetWriter
    self.assetWriter = [AVAssetWriter assetWriterWithURL:self.outputURL
    fileType:AVFileTypeQuickTimeMovie
    error:&error];
    !
    !
    // movie
    NSDictionary *videoSetting = self.videoSettings;
    self.assetWriterInputVideo = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
    outputSettings:videoSetting];
    [self.assetWriterInputVideo setExpectsMediaDataInRealTime:YES];
    !
    !
    // audio
    NSDictionary *audioSetting = self.audioSettings;
    self.assetWriterInputAudio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
    outputSettings:audioSetting];
    [self.assetWriterInputAudio setExpectsMediaDataInRealTime:YES];
    !
    !
    [self.assetWriter addInput:self.assetWriterInputVideo];
    [self.assetWriter addInput:self.assetWriterInputAudio];
    !
    // queue
    self.movieWritingQueue = dispatch_queue_create("Movie Writing Queue", DISPATCH_QUEUE_SERIAL);
    !
    // Record
    [self.assetWriter startWriting];
    [self.assetWriter startSessionAtSourceTime:self.recordStartTime];

    View Slide

  23. 4UBSU8SJUJOH
    // AVAssetWriter
    self.assetWriter = [AVAssetWriter assetWriterWithURL:self.outputURL
    fileType:AVFileTypeQuickTimeMovie
    error:&error];
    !
    !
    // movie
    NSDictionary *videoSetting = self.videoSettings;
    self.assetWriterInputVideo = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
    outputSettings:videoSetting];
    [self.assetWriterInputVideo setExpectsMediaDataInRealTime:YES];
    !
    !
    // audio
    NSDictionary *audioSetting = self.audioSettings;
    self.assetWriterInputAudio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
    outputSettings:audioSetting];
    [self.assetWriterInputAudio setExpectsMediaDataInRealTime:YES];
    !
    !
    [self.assetWriter addInput:self.assetWriterInputVideo];
    [self.assetWriter addInput:self.assetWriterInputAudio];
    !
    // queue
    self.movieWritingQueue = dispatch_queue_create("Movie Writing Queue", DISPATCH_QUEUE_SERIAL);
    !
    // Record
    [self.assetWriter startWriting];
    [self.assetWriter startSessionAtSourceTime:self.recordStartTime];

    View Slide

  24. 4UBSU8SJUJOH
    // AVAssetWriter
    self.assetWriter = [AVAssetWriter assetWriterWithURL:self.outputURL
    fileType:AVFileTypeQuickTimeMovie
    error:&error];
    !
    !
    // movie
    NSDictionary *videoSetting = self.videoSettings;
    self.assetWriterInputVideo = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
    outputSettings:videoSetting];
    [self.assetWriterInputVideo setExpectsMediaDataInRealTime:YES];
    !
    !
    // audio
    NSDictionary *audioSetting = self.audioSettings;
    self.assetWriterInputAudio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
    outputSettings:audioSetting];
    [self.assetWriterInputAudio setExpectsMediaDataInRealTime:YES];
    !
    !
    [self.assetWriter addInput:self.assetWriterInputVideo];
    [self.assetWriter addInput:self.assetWriterInputAudio];
    !
    // queue
    self.movieWritingQueue = dispatch_queue_create("Movie Writing Queue", DISPATCH_QUEUE_SERIAL);
    !
    // Record
    [self.assetWriter startWriting];
    [self.assetWriter startSessionAtSourceTime:self.recordStartTime];

    View Slide

  25. 4UBSU8SJUJOH
    // AVAssetWriter
    self.assetWriter = [AVAssetWriter assetWriterWithURL:self.outputURL
    fileType:AVFileTypeQuickTimeMovie
    error:&error];
    !
    !
    // movie
    NSDictionary *videoSetting = self.videoSettings;
    self.assetWriterInputVideo = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
    outputSettings:videoSetting];
    [self.assetWriterInputVideo setExpectsMediaDataInRealTime:YES];
    !
    !
    // audio
    NSDictionary *audioSetting = self.audioSettings;
    self.assetWriterInputAudio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
    outputSettings:audioSetting];
    [self.assetWriterInputAudio setExpectsMediaDataInRealTime:YES];
    !
    !
    [self.assetWriter addInput:self.assetWriterInputVideo];
    [self.assetWriter addInput:self.assetWriterInputAudio];
    !
    // queue
    self.movieWritingQueue = dispatch_queue_create("Movie Writing Queue", DISPATCH_QUEUE_SERIAL);
    !
    // Record
    [self.assetWriter startWriting];
    [self.assetWriter startSessionAtSourceTime:self.recordStartTime];

    View Slide

  26. 4UBSU8SJUJOH
    - (void)addSamplebuffer:(CMSampleBufferRef)sampleBuffer withWriterInput:(AVAssetWriterInput
    *)assetWriterInput
    {
    CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
    !
    CFRetain(sampleBuffer);
    CFRetain(formatDescription);
    dispatch_async(self.movieWritingQueue, ^{
    !
    if (_assetWriter.status == AVAssetWriterStatusWriting) {
    !
    if (assetWriterInput.readyForMoreMediaData) {
    !
    [assetWriterInput appendSampleBuffer:sampleBuffer];
    !
    }
    }
    !
    CFRelease(sampleBuffer);
    CFRelease(formatDescription);
    });
    }

    View Slide

  27. $.4BNQMF#VGGFS3FG

    View Slide

  28. $.4BNQMF#VGGFS3FG
    ɾ͋ΔϝσΟΞλΠϓͷαϯϓϧؚ͕·Εͨ$PSF'PVEBUJPO0CKFDUT
    ɹɾѹॖPSൺѹॖ
    ɾαϯϓϧ
    ɾશମͷத͔ΒऔΓग़ͨ͠Ұ෦෼ͷԿ͔

    View Slide

  29. 'JOJTI8SJUJOH
    ऴྃॲཧ
    ϑΝΠϧʹอଘ

    View Slide

  30. 'JOJTI8SJUJOH
    [self.assetWriterInputVideo markAsFinished];
    [self.assetWriterInputAudio markAsFinished];
    [self.assetWriter endSessionAtSourceTime:self.recordStartTime];
    [self.assetWriter finishWritingWithCompletionHandler:^{
    NSLog(@"self.assetWriter finishWritingWithCompletionHandler");
    [self.movieURLs addObject:self.outputURL];
    NSLog(@"%@", self.movieURLs);
    }];

    View Slide

  31. 'JOJTI8SJUJOH
    [self.assetWriterInputVideo markAsFinished];
    [self.assetWriterInputAudio markAsFinished];
    [self.assetWriter endSessionAtSourceTime:self.recordStartTime];
    [self.assetWriter finishWritingWithCompletionHandler:^{
    NSLog(@"self.assetWriter finishWritingWithCompletionHandler");
    [self.movieURLs addObject:self.outputURL];
    NSLog(@"%@", self.movieURLs);
    }];

    View Slide

  32. ͍͍ײ͡ʹग़དྷ্͕ͬͨ
    ͷͰެ։͠·ͨ͠ɻ

    View Slide

  33. /,+.VMUJ.PWJF$BQUVSF7JFX
    IUUQTHJUIVCDPNOBLBKJKBQBO/,+.VMUJ.PWJF$BQUVSF7JFX

    View Slide

  34. ൚༻ੑ͕·ͩ଍Γͳ͍ͷ
    Ͱ೔ʑॗʑͱվળͤͯ͞
    ͍͖ͨͩ·͢ɻɻɻɻɻ

    View Slide

  35. ࠂ஌͍ͤͯͩ͘͞͞

    View Slide

  36. DPNNJOHTPPO

    View Slide

  37. 5IBOLT

    View Slide