Instagram, Vine, SlideStory のような動画アプリで動画を保存する仕込みが気になったので実装しました。
BQQಓ!OBLBKJKBQBOΑ͋͘ΔಈըΞϓϦͷ͋ΕΛ࣮͍ͨ͠
View Slide
!OBLBKJKBQBO4PGUXBSF&OHJOFFS(.01&1"#0JOD
৺ྶࣸਅΞϓϦ͓Θ͔Γ͍͚ͨͩͨͩΖ͏͔
৺ྶಈըΞϓϦ͏Ұ͝ཡ͍ͨͩ͜͏
"7'PVOEBUJPOࠓճʂʂ
͋ͷಈըΛอଘ͢ΔΠϯλʔϑΣʔε͕ؾʹͳͬͨͷͰ࣮ͨ͠ɻ
༷
εΫϦʔϯΛλονͨ͠ΒಈըΛอଘ։࢝ͯ͠εΫϦʔϯ͔ΒΕͨΒอଘऴྃ
"7$BQUVSF4FTTJPO
"7$BQUVSF0VUQVU
"7$BQUVSF0VUQVUɾ"7$BQUVSF.PWJF'JMF0VUQVUɾ"7$BQUVSF4UJMM*NBHF0VUQVUɾ"7$BQUVSF7JEFP%BUB0VUQVUɾ"7$BQUVSF"VEJP%BUB0VUQVU
"7$BQUVSF0VUQVUɾ"7$BQUVSF.PWJF'JMF0VUQVU ɾ'JMFTɾ"7$BQUVSF4UJMM*NBHF0VUQVU ɾ*NBHFɾ"7$BQUVSF7JEFP%BUB0VUQVUɾ"7$BQUVSF"VEJP%BUB0VUQVU ɾ-JWFEBUB
"7$BQUVSF"VEJP%BUB0VUQVUAVCaptureVideoDataOutputSampleBufferDelegateAVCaptureAudioDataOutputSampleBufferDelegate"7$BQUVSF7JEFP%BUB0VUQVU
#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate!- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBufferfromConnection:(AVCaptureConnection *)connection{!if (!CMSampleBufferDataIsReady(sampleBuffer)) {NSLog(@"sampleBuffer data is not ready");}!CMTime currentTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);!if (self.touching) {!// Videoif ([captureOutput isKindOfClass:[AVCaptureVideoDataOutput class]]) {[self addSamplebuffer:sampleBuffer withWriterInput:(AVAssetWriterInput *)self.assetWriterInputVideo];}// Audioelse if ([captureOutput isKindOfClass:[AVCaptureAudioDataOutput class]]) {[self addSamplebuffer:sampleBuffer withWriterInput:(AVAssetWriterInput *)self.assetWriterInputAudio];}!}!self.recordStartTime = currentTime;}AVCaptureVideoDataOutputSampleBufferDelegateAVCaptureAudioDataOutputSampleBufferDelegate
8SJUJOH
εΫϦʔϯΛλονͨ͠ΒಈըΛอଘ։࢝ͯ͠εΫϦʔϯ͔ΒΕͨΒอଘऴྃ- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
"7"TTFU8SJUFS"7"TTFU8SJUFS*OQVU
4UBSU8SJUJOHอଘରͷϑΝΠϧΛࢦఆͯ͠ॳظԽϝσΟΞλΠϓΛࢦఆTFU&YQFDUT.FEJB%BUB*O3FBM5JNFΛ0/ʹ͢Δ"7"TTFU8SJUFSʹ"7"TTFU8SJUFS*OQVUΛΈࠐΉॻ͖ࠐΈ։࢝
4UBSU8SJUJOH// AVAssetWriterself.assetWriter = [AVAssetWriter assetWriterWithURL:self.outputURLfileType:AVFileTypeQuickTimeMovieerror:&error];!!// movieNSDictionary *videoSetting = self.videoSettings;self.assetWriterInputVideo = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideooutputSettings:videoSetting];[self.assetWriterInputVideo setExpectsMediaDataInRealTime:YES];!!// audioNSDictionary *audioSetting = self.audioSettings;self.assetWriterInputAudio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudiooutputSettings:audioSetting];[self.assetWriterInputAudio setExpectsMediaDataInRealTime:YES];!![self.assetWriter addInput:self.assetWriterInputVideo];[self.assetWriter addInput:self.assetWriterInputAudio];!// queueself.movieWritingQueue = dispatch_queue_create("Movie Writing Queue", DISPATCH_QUEUE_SERIAL);!// Record[self.assetWriter startWriting];[self.assetWriter startSessionAtSourceTime:self.recordStartTime];
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);});}
$.4BNQMF#VGGFS3FG
$.4BNQMF#VGGFS3FGɾ͋ΔϝσΟΞλΠϓͷαϯϓϧؚ͕·Εͨ$PSF'PVEBUJPO0CKFDUTɹɾѹॖPSൺѹॖɾαϯϓϧɾશମͷத͔ΒऔΓग़ͨ͠Ұ෦ͷԿ͔
'JOJTI8SJUJOH ऴྃॲཧ ϑΝΠϧʹอଘ
'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);}];
͍͍ײ͡ʹग़དྷ্͕ͬͨͷͰެ։͠·ͨ͠ɻ
/,+.VMUJ.PWJF$BQUVSF7JFXIUUQTHJUIVCDPNOBLBKJKBQBO/,+.VMUJ.PWJF$BQUVSF7JFX
൚༻ੑ͕·ͩΓͳ͍ͷͰʑॗʑͱվળ͍͖ͤͯͨͩ͞·͢ɻɻɻɻɻ
ࠂ͍ͤͯͩ͘͞͞
DPNNJOHTPPO
5IBOLT