Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
よくある動画アプリのあれを実装したい。
Search
nakajijapan
May 28, 2014
Technology
0
2.7k
よくある動画アプリのあれを実装したい。
Instagram, Vine, SlideStory のような動画アプリで動画を保存する仕込みが気になったので実装しました。
nakajijapan
May 28, 2014
Tweet
Share
More Decks by nakajijapan
See All by nakajijapan
サービスにおけるDesign Systemの構築
nakajijapan
11
3.7k
Markdownをリアルタイムに解析する
nakajijapan
5
4.4k
Firebase Authorization
nakajijapan
0
270
Intoducing Izumo
nakajijapan
1
1.9k
Practical CloudKit
nakajijapan
1
1.8k
Introducing to Ajimi - プロダクトを味見していこう
nakajijapan
0
2.2k
Shari
nakajijapan
1
2.8k
Japan Apple Pay Development
nakajijapan
0
280
業務で絶対必要にならない技術
nakajijapan
0
840
Other Decks in Technology
See All in Technology
複数サービスを支えるマルチテナント型Batch MLプラットフォーム
lycorptech_jp
PRO
1
980
20250905_MeetUp_Ito-san_s_presentation.pdf
magicpod
1
100
Django's GeneratedField by example - DjangoCon US 2025
pauloxnet
0
160
Unlocking the Power of AI Agents with LINE Bot MCP Server
linedevth
0
120
共有と分離 - Compose Multiplatform "本番導入" の設計指針
error96num
2
1.2k
なぜテストマネージャの視点が 必要なのか? 〜 一歩先へ進むために 〜
moritamasami
0
240
Snowflake Intelligenceにはこうやって立ち向かう!クラシルが考えるAI Readyなデータ基盤と活用のためのDataOps
gappy50
0
280
これでもう迷わない!Jetpack Composeの書き方実践ガイド
zozotech
PRO
0
1.1k
職種の壁を溶かして開発サイクルを高速に回す~情報透明性と職種越境から考えるAIフレンドリーな職種間連携~
daitasu
0
190
RSCの時代にReactとフレームワークの境界を探る
uhyo
11
3.5k
AI時代を生き抜くエンジニアキャリアの築き方 (AI-Native 時代、エンジニアという道は 「最大の挑戦の場」となる) / Building an Engineering Career to Thrive in the Age of AI (In the AI-Native Era, the Path of Engineering Becomes the Ultimate Arena of Challenge)
jeongjaesoon
0
260
Snowflake×dbtを用いたテレシーのデータ基盤のこれまでとこれから
sagara
0
130
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
6k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Being A Developer After 40
akosma
90
590k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.5k
Visualization
eitanlees
148
16k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
GraphQLとの向き合い方2022年版
quramy
49
14k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
61k
BBQ
matthewcrist
89
9.8k
Done Done
chrislema
185
16k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.6k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Transcript
BQQಓ !OBLBKJKBQBO Α͋͘Δಈը ΞϓϦͷ͋Ε Λ࣮͍ͨ͠
!OBLBKJKBQBO 4PGUXBSF&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$BQUVSF0VUQVU ɾ"7$BQUVSF.PWJF'JMF0VUQVU ɾ'JMFT ɾ"7$BQUVSF4UJMM*NBHF0VUQVU ɾ*NBHF ɾ"7$BQUVSF7JEFP%BUB0VUQVU ɾ"7$BQUVSF"VEJP%BUB0VUQVU
ɾ-JWFEBUB
"7$BQUVSF"VEJP%BUB0VUQVU AVCaptureVideoDataOutputSampleBufferDelegate AVCaptureAudioDataOutputSampleBufferDelegate "7$BQUVSF7JEFP%BUB0VUQVU
#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
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 // 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];
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];
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];
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];
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];
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); }];
'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$BQUVSF7JFX IUUQTHJUIVCDPNOBLBKJKBQBO/,+.VMUJ.PWJF$BQUVSF7JFX
൚༻ੑ͕·ͩΓͳ͍ͷ Ͱʑॗʑͱվળͤͯ͞ ͍͖ͨͩ·͢ɻɻɻɻɻ
ࠂ͍ͤͯͩ͘͞͞
DPNNJOHTPPO
5IBOLT