心霊動画アプリ「もう一度ご覧いただこう」を作成してみて
Conference With Developers 2014
"7'PVOEBUJPO৺ྶಈըΞϓϦʮ͏Ұ͝ཡ͍ͨͩ͜͏ʯΛ࡞ͯ͠Έͯ!OBLBKJKBQBO
View Slide
ࠓ͢͜ͱw ࣗݾհw ΞϓϦհw "7'PVOEBUJPOΛ࣮ͬͨ͋Ε͜Εw ॴײ
ࣗݾհ!OBLBKJKBQBOQBQFSCPZDP
!JTPEJOF
!JTPEJOFςϨϏͰΔΑ͏ͳ৺ྶ൪Έ͍ͨͳಈը࡞Γ͍ͨΜʙ
͍
IUUQPXLSJOGPNPWJF͏Ұ͝ཡ͍ͨͩ͜͏৺ྶಈըΞϓϦ
ओͳػೳw ಈըըw ಈըʹ৺ྶΛೖΕΔw ಈըʹςϩοϓͱϫΠϓw ಈըͷγνϡΤʔγϣϯʹ߹ΘͤͯφϨʔγϣϯΛೖΕΔw ιʔγϟϧڞ༗
w .FEJB1MBZFS'SBNFXPSLw 6*,JU্ҐͷϑϨʔϜϫʔΫ
"7'PVOEBUJPO
ௐࠪ
ௐࠪw "7'PVOEBUJPO1SPHSBNNJOH(VJEFw .PWJOHUP"7,JUBOE"7'PVOEBUJPOrw $PSF*NBHF&GGFDUTBOE5FDIOJRVFTrw "EWBODFE&EJUJOHXJUI"7'PVOEBUJPOr
ߏ
εϩʔϞʔγϣϯಈըTFD TFD TFDφϨʔγϣϯԻϫΠϓը૾߹ಈը݁߹ ಈը݁߹
࣮
ಈը݁߹
// AssetੜAVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:movieURL options:nil];!// CompositionTrackੜAVMutableCompositionTrack* compositionVideoTrack;compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideopreferredTrackID:kCMPersistentTrackID_Invalid];!// Ξηοτ͔ΒτϥοΫΛऔಘAVAssetTrack *videoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];!// ઃఆ[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)ofTrack:videoTrackatTime:self.currentTimeDurationerror:nil];[compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo]objectAtIndex:0] preferredTransform]];AVMutableCompositionTrack *compositionAudioTrack = [mixCompositionaddMutableTrackWithMediaType:AVMediaTypeAudiopreferredTrackID:kCMPersistentTrackID_Invalid];// Assetੜ[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]atTime:self.currentTimeDuration error:nil];self.currentTimeDuration = [mixComposition duration];!// Layer InstructionͷՃAVMutableVideoCompositionLayerInstruction *layerInstruction;layerInstruction = [AVMutableVideoCompositionLayerInstructionvideoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];![self.layerInstructions addObject:layerInstruction];ϝσΟΞใΛอ࣋͠ɺͦͷใΛऔಘͰ͖Δ
// AssetੜAVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:movieURL options:nil];!// CompositionTrackੜAVMutableCompositionTrack* compositionVideoTrack;compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideopreferredTrackID:kCMPersistentTrackID_Invalid];!// Ξηοτ͔ΒτϥοΫΛऔಘAVAssetTrack *videoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];!// ઃఆ[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)ofTrack:videoTrackatTime:self.currentTimeDurationerror:nil];[compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo]objectAtIndex:0] preferredTransform]];AVMutableCompositionTrack *compositionAudioTrack = [mixCompositionaddMutableTrackWithMediaType:AVMediaTypeAudiopreferredTrackID:kCMPersistentTrackID_Invalid];// Assetੜ[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]atTime:self.currentTimeDuration error:nil];self.currentTimeDuration = [mixComposition duration];!// Layer InstructionͷՃAVMutableVideoCompositionLayerInstruction *layerInstruction;layerInstruction = [AVMutableVideoCompositionLayerInstructionvideoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];![self.layerInstructions addObject:layerInstruction];ө૾ΛऔΓग़͢ԻΛऔΓग़͢
// AssetੜAVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:movieURL options:nil];!// CompositionTrackੜAVMutableCompositionTrack* compositionVideoTrack;compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideopreferredTrackID:kCMPersistentTrackID_Invalid];!// Ξηοτ͔ΒτϥοΫΛऔಘAVAssetTrack *videoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];!// ઃఆ[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)ofTrack:videoTrackatTime:self.currentTimeDurationerror:nil];[compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo]objectAtIndex:0] preferredTransform]];AVMutableCompositionTrack *compositionAudioTrack = [mixCompositionaddMutableTrackWithMediaType:AVMediaTypeAudiopreferredTrackID:kCMPersistentTrackID_Invalid];// Assetੜ[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]atTime:self.currentTimeDuration error:nil];self.currentTimeDuration = [mixComposition duration];!// Layer InstructionͷՃAVMutableVideoCompositionLayerInstruction *layerInstruction;layerInstruction = [AVMutableVideoCompositionLayerInstructionvideoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];![self.layerInstructions addObject:layerInstruction];ίϯϙδγϣϯΛΈཱͯΔ
ը૾ͷ߹ͱΞχϝʔγϣϯ
// generate parent layerCALayer* layerRoot = [CALayer layer];CALayer* layerVideo = [CALayer layer];....videoComp = [AVMutableVideoComposition videoComposition];videoComp.animationTool = [AVVideoCompositionCoreAnimationToolvideoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:layerVideoinLayer:layerRoot];$"-BZFSʹ$"#BTJD"OJNBUJPOͰઃఆͨ͠ΞχϝʔγϣϯΛՃ͢Δ
ϫΠϓಈը
// AssetੜAVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:movieURL options:nil];// CompositionTrackੜAVMutableCompositionTrack* compositionVideoTrack = [mixCompositionaddMutableTrackWithMediaType:AVMediaTypeVideopreferredTrackID:kCMPersistentTrackID_Invalid];// TrackऔಘAVAssetTrack* videoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];!// ઃఆCMTime timeDuration;timeDuration = videoAsset.duration;![compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, timeDuration)ofTrack:videoTrackatTime:kCMTimeZeroerror:nil];[compositionVideoTrack setPreferredTransform:[videoTrack preferredTransform]];AVMutableVideoCompositionLayerInstruction* layerInstruction;layerInstruction = [AVMutableVideoCompositionLayerInstructionvideoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];[layerInstruction setTransform:CGAffineTransformConcat(scale, trnsration) atTime:kCMTimeZero];![self.layerInstructions addObject:layerInstruction];ΞϑΟϯม
εϩʔϞʔγϣϯ
// શମʹରͯ͠εϩʔϞʔγϣϯॲཧΛ͔͚ΔCMTime durationSlow = CMTimeSubtract(videoAsset.duration, CMTimeMake(9, 1));[mixComposition scaleTimeRange:CMTimeRangeMake(CMTimeMake(19, 1), durationSlow)toDuration:CMTimeMake(durationSlow.value * 2.0, durationSlow.timescale)];࣮ࡍͷө૾Λ̎ഒͷ࣌ؒͰग़ྗͤ͞Δ
εϩʔϞʔγϣϯϫΠϓಈըը૾ͷ߹ͱΞχϝʔγϣϯಈը݁߹࣮
ॴײw Ϋϥε໊͔ͬͨΓ࣮ྔ͕ଟͯ͘େมʂw ͱ͍͑ઃܭ͢Β͍͠w ใ͕গͳ͍w ϋϚΔͱ໎ঢ়ଶw ࣄͰશ͘׆͔ͤͳ͍ʂʂʂ
4BNQMF.PWJFIUUQTXXXZPVUVCFDPNXBUDI WLKPXF43%*%FNP.PWJFIUUQTXXXZPVUVCFDPNXBUDI WSKUNK:6
5IBOLT