SlideShare a Scribd company logo
iOSで動画から
スクショを撮る方法
@gawawa124
Who am I ?
• Tomoya Itagawa (@gawawa124)
• フリーランスのiPhoneアプリエンジニア
• Objective-Cを3年くらい
• Swiftは2になってからちょっと触ってた
Swiftのお仕事募集中です
iOSアプリ上で動画から
スクショが撮りたい
AVPlayerで
視聴している動画を
UIImageに変換したい
普通のUIViewの場合は?
func imageFromView() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
if let context = UIGraphicsGetCurrentContext() {
layer.renderInContext(context)
let image =
UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image;
}
return nil
}
問題ない
しかし
AVPlayerだと真っ白になる
How? - 0.動画再生準備
• AVPlayer(動画を再生するためのもの)
• AVPlayerItem(AVPlayerに渡す動画ファイ
ル)
• AVPlayerLayer(実際に見える画面)
How? - 1.CADisplayLinkと
AVPlayerItemVideoOutput
• CADisplayLink(画面更新のたびに呼び出され
るメソッドを提供するタイマーオブジェクト)
• AVPlayerItemVideoOutput(動画から出力さ
れる情報を司っている)
• AVPlayerItemにaddVideoOutputで紐付ける
How? - 2.コールバックから
UIImageに変換していく
1. AVPlayerItemVideoOutput
2. CVPixelBuffer
3. CIImage
4. CGImage
5. UIImage
どうしてこんなに面倒な感じなのかは後述
CADisplayLinkのコールバックから
UIImageに変換
func displayLinkCallback(sender: CADisplayLink) {
var outputItemTime: CMTime = kCMTimeInvalid
let nextVsync: CFTimeInterval = sender.timestamp + sender.duration
outputItemTime = videoOutput.itemTimeForHostTime(nextVsync)
if videoOutput.hasNewPixelBufferForItemTime(outputItemTime) {
if let pixelBuffer =
videoOutput.copyPixelBufferForItemTime(outputItemTime, itemTimeForDisplay: nil) {
let ciImage = CIImage(CVPixelBuffer: pixelBuffer)
let temporaryContext = CIContext(options: nil)
let videoImage = temporaryContext.createCGImage(
ciImage,
fromRect: CGRectMake(
0,
0,
CGFloat(CVPixelBufferGetWidth(pixelBuffer)),
CGFloat(CVPixelBufferGetHeight(pixelBuffer))))
backgroundImageView.image = UIImage(CGImage: videoImage)
}
}
}
CADisplayLinkのコールバックから
UIImageに変換
func displayLinkCallback(sender: CADisplayLink) {
var outputItemTime: CMTime = kCMTimeInvalid
let nextVsync: CFTimeInterval = sender.timestamp + sender.duration
outputItemTime = videoOutput.itemTimeForHostTime(nextVsync)
if videoOutput.hasNewPixelBufferForItemTime(outputItemTime) {
if let pixelBuffer =
videoOutput.copyPixelBufferForItemTime(outputItemTime, itemTimeForDisplay: nil) {
let ciImage = CIImage(CVPixelBuffer: pixelBuffer)
let temporaryContext = CIContext(options: nil)
let videoImage = temporaryContext.createCGImage(
ciImage,
fromRect: CGRectMake(
0,
0,
CGFloat(CVPixelBufferGetWidth(pixelBuffer)),
CGFloat(CVPixelBufferGetHeight(pixelBuffer))))
backgroundImageView.image = UIImage(CGImage: videoImage)
}
}
}
指定するための時間
時間を指定して
pixelBufferを取得
CADisplayLinkのコールバックから
UIImageに変換
func displayLinkCallback(sender: CADisplayLink) {
var outputItemTime: CMTime = kCMTimeInvalid
let nextVsync: CFTimeInterval = sender.timestamp + sender.duration
outputItemTime = videoOutput.itemTimeForHostTime(nextVsync)
if videoOutput.hasNewPixelBufferForItemTime(outputItemTime) {
if let pixelBuffer =
videoOutput.copyPixelBufferForItemTime(outputItemTime, itemTimeForDisplay: nil) {
let ciImage = CIImage(CVPixelBuffer: pixelBuffer)
let temporaryContext = CIContext(options: nil)
let videoImage = temporaryContext.createCGImage(
ciImage,
fromRect: CGRectMake(
0,
0,
CGFloat(CVPixelBufferGetWidth(pixelBuffer)),
CGFloat(CVPixelBufferGetHeight(pixelBuffer))))
backgroundImageView.image = UIImage(CGImage: videoImage)
}
}
}
CIImageをそのままUIImageに
するとうまく描画されない!
最適解とは
言いづらいですけど
実装できました
Demo
参考資料
• Swift Docs(006 動画の再生) https://sites.google.com/a/gclue.jp/
swift-docs/ni-yinki100-ios/3-avfoundation/006-dong-huano-zai-
sheng
• iOS Developer Library(Real-time Video Processing Using
AVPlayerItemVideoOutput) https://developer.apple.com/
library/prerelease/ios/samplecode/AVBasicVideoOutput/
Introduction/Intro.html
• stack over flow(How to turn a CVPixelBuffer into a UIImage?)
http://stackoverflow.com/questions/8072208/how-to-turn-a-
cvpixelbuffer-into-a-uiimage
Thank you!

More Related Content

What's hot

ディープラーニングとAppiumでモバイルテスト自動化
ディープラーニングとAppiumでモバイルテスト自動化ディープラーニングとAppiumでモバイルテスト自動化
ディープラーニングとAppiumでモバイルテスト自動化
Nozomi Ito
 
猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について
エピック・ゲームズ・ジャパン Epic Games Japan
 
【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~
【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~
【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~
UnityTechnologiesJapan002
 
Unity5.3をさわってみた
Unity5.3をさわってみたUnity5.3をさわってみた
Unity5.3をさわってみた
Keizo Nagamine
 
猫でも分かる Control Rig UE4.25 版
猫でも分かる Control Rig UE4.25 版猫でも分かる Control Rig UE4.25 版
猫でも分かる Control Rig UE4.25 版
エピック・ゲームズ・ジャパン Epic Games Japan
 
Archer
ArcherArcher
Lt 20150711
Lt 20150711Lt 20150711
Lt 20150711
Tomoyuki Obi
 
プログラムで映像をつくるとは?? ~超入門編~
プログラムで映像をつくるとは?? ~超入門編~プログラムで映像をつくるとは?? ~超入門編~
プログラムで映像をつくるとは?? ~超入門編~
Ryo Kanda
 

What's hot (8)

ディープラーニングとAppiumでモバイルテスト自動化
ディープラーニングとAppiumでモバイルテスト自動化ディープラーニングとAppiumでモバイルテスト自動化
ディープラーニングとAppiumでモバイルテスト自動化
 
猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について
 
【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~
【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~
【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~
 
Unity5.3をさわってみた
Unity5.3をさわってみたUnity5.3をさわってみた
Unity5.3をさわってみた
 
猫でも分かる Control Rig UE4.25 版
猫でも分かる Control Rig UE4.25 版猫でも分かる Control Rig UE4.25 版
猫でも分かる Control Rig UE4.25 版
 
Archer
ArcherArcher
Archer
 
Lt 20150711
Lt 20150711Lt 20150711
Lt 20150711
 
プログラムで映像をつくるとは?? ~超入門編~
プログラムで映像をつくるとは?? ~超入門編~プログラムで映像をつくるとは?? ~超入門編~
プログラムで映像をつくるとは?? ~超入門編~
 

Similar to iOSで動画からスクショを撮る方法

Swift Study Vol.4
Swift Study Vol.4Swift Study Vol.4
Swift Study Vol.4
Nagamine Hiromasa
 
I phonedevws20121028ci filter
I phonedevws20121028ci filterI phonedevws20121028ci filter
I phonedevws20121028ci filterZuQ9Nn
 
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 EastiOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
irgaly
 
iPhoneアプリ開発の歩き方〜Swift編〜
iPhoneアプリ開発の歩き方〜Swift編〜iPhoneアプリ開発の歩き方〜Swift編〜
iPhoneアプリ開発の歩き方〜Swift編〜
Yusuke SAITO
 
iTamabi 13  第3回:iPhoneアプリ実践開発講座 1 画像ファイルの読み込み 画像でアニメーションを作成する
iTamabi 13  第3回:iPhoneアプリ実践開発講座 1 画像ファイルの読み込み 画像でアニメーションを作成するiTamabi 13  第3回:iPhoneアプリ実践開発講座 1 画像ファイルの読み込み 画像でアニメーションを作成する
iTamabi 13  第3回:iPhoneアプリ実践開発講座 1 画像ファイルの読み込み 画像でアニメーションを作成するAtsushi Tadokoro
 
iOSにおけるUIテスト@potetotips
iOSにおけるUIテスト@potetotipsiOSにおけるUIテスト@potetotips
iOSにおけるUIテスト@potetotips
Yusuke Kita
 
Core Animation 使って見た
Core Animation 使って見たCore Animation 使って見た
Core Animation 使って見た
OCHI Shuji
 
iOS 10 new Camera
iOS 10 new CameraiOS 10 new Camera
iOS 10 new Camera
Gaprot
 
OpenCV 3.0 on iOS
OpenCV 3.0 on iOSOpenCV 3.0 on iOS
OpenCV 3.0 on iOS
Shuichi Tsutsumi
 
JavaScriptでいいじゃなイカ
JavaScriptでいいじゃなイカJavaScriptでいいじゃなイカ
JavaScriptでいいじゃなイカ
Yuuichi Akagawa
 
20121201yidev hirobe iPad miniでRetina
20121201yidev hirobe iPad miniでRetina20121201yidev hirobe iPad miniでRetina
20121201yidev hirobe iPad miniでRetinaKazuya Hirobe
 
勉強会資料Out ofmemory
勉強会資料Out ofmemory勉強会資料Out ofmemory
勉強会資料Out ofmemory
Nao Fujita
 
HTML5のCanvas入門 - Img画像を編集してみよう -
HTML5のCanvas入門 - Img画像を編集してみよう -HTML5のCanvas入門 - Img画像を編集してみよう -
HTML5のCanvas入門 - Img画像を編集してみよう -
Toshio Ehara
 
Titanium もくもく会第6回 Kii Cloud と TiGPUImageView
Titanium もくもく会第6回 Kii Cloud と TiGPUImageViewTitanium もくもく会第6回 Kii Cloud と TiGPUImageView
Titanium もくもく会第6回 Kii Cloud と TiGPUImageView
濱田 章吾
 
UIImagePickerController よもやま話
UIImagePickerController よもやま話UIImagePickerController よもやま話
UIImagePickerController よもやま話
Kei Kusakari
 
あの言語で画像処理する ライブラリを作った件
あの言語で画像処理する ライブラリを作った件あの言語で画像処理する ライブラリを作った件
あの言語で画像処理する ライブラリを作った件
Sakiyama Kei
 
About SnapKit - Open source lab -
About SnapKit - Open source lab -About SnapKit - Open source lab -
About SnapKit - Open source lab -
Daisuke Yamashita
 
WatchKitを実際にさわってみてわかったこと
WatchKitを実際にさわってみてわかったことWatchKitを実際にさわってみてわかったこと
WatchKitを実際にさわってみてわかったこと
Shuichi Tsutsumi
 
Swiftではじめる動画再生
Swiftではじめる動画再生Swiftではじめる動画再生
Swiftではじめる動画再生
Yusuke Ariyoshi
 

Similar to iOSで動画からスクショを撮る方法 (20)

Swift Study Vol.4
Swift Study Vol.4Swift Study Vol.4
Swift Study Vol.4
 
I phonedevws20121028ci filter
I phonedevws20121028ci filterI phonedevws20121028ci filter
I phonedevws20121028ci filter
 
魅せるUIの作り方 | iOS 7エンジニア勉強会
魅せるUIの作り方 | iOS 7エンジニア勉強会魅せるUIの作り方 | iOS 7エンジニア勉強会
魅せるUIの作り方 | iOS 7エンジニア勉強会
 
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 EastiOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
 
iPhoneアプリ開発の歩き方〜Swift編〜
iPhoneアプリ開発の歩き方〜Swift編〜iPhoneアプリ開発の歩き方〜Swift編〜
iPhoneアプリ開発の歩き方〜Swift編〜
 
iTamabi 13  第3回:iPhoneアプリ実践開発講座 1 画像ファイルの読み込み 画像でアニメーションを作成する
iTamabi 13  第3回:iPhoneアプリ実践開発講座 1 画像ファイルの読み込み 画像でアニメーションを作成するiTamabi 13  第3回:iPhoneアプリ実践開発講座 1 画像ファイルの読み込み 画像でアニメーションを作成する
iTamabi 13  第3回:iPhoneアプリ実践開発講座 1 画像ファイルの読み込み 画像でアニメーションを作成する
 
iOSにおけるUIテスト@potetotips
iOSにおけるUIテスト@potetotipsiOSにおけるUIテスト@potetotips
iOSにおけるUIテスト@potetotips
 
Core Animation 使って見た
Core Animation 使って見たCore Animation 使って見た
Core Animation 使って見た
 
iOS 10 new Camera
iOS 10 new CameraiOS 10 new Camera
iOS 10 new Camera
 
OpenCV 3.0 on iOS
OpenCV 3.0 on iOSOpenCV 3.0 on iOS
OpenCV 3.0 on iOS
 
JavaScriptでいいじゃなイカ
JavaScriptでいいじゃなイカJavaScriptでいいじゃなイカ
JavaScriptでいいじゃなイカ
 
20121201yidev hirobe iPad miniでRetina
20121201yidev hirobe iPad miniでRetina20121201yidev hirobe iPad miniでRetina
20121201yidev hirobe iPad miniでRetina
 
勉強会資料Out ofmemory
勉強会資料Out ofmemory勉強会資料Out ofmemory
勉強会資料Out ofmemory
 
HTML5のCanvas入門 - Img画像を編集してみよう -
HTML5のCanvas入門 - Img画像を編集してみよう -HTML5のCanvas入門 - Img画像を編集してみよう -
HTML5のCanvas入門 - Img画像を編集してみよう -
 
Titanium もくもく会第6回 Kii Cloud と TiGPUImageView
Titanium もくもく会第6回 Kii Cloud と TiGPUImageViewTitanium もくもく会第6回 Kii Cloud と TiGPUImageView
Titanium もくもく会第6回 Kii Cloud と TiGPUImageView
 
UIImagePickerController よもやま話
UIImagePickerController よもやま話UIImagePickerController よもやま話
UIImagePickerController よもやま話
 
あの言語で画像処理する ライブラリを作った件
あの言語で画像処理する ライブラリを作った件あの言語で画像処理する ライブラリを作った件
あの言語で画像処理する ライブラリを作った件
 
About SnapKit - Open source lab -
About SnapKit - Open source lab -About SnapKit - Open source lab -
About SnapKit - Open source lab -
 
WatchKitを実際にさわってみてわかったこと
WatchKitを実際にさわってみてわかったことWatchKitを実際にさわってみてわかったこと
WatchKitを実際にさわってみてわかったこと
 
Swiftではじめる動画再生
Swiftではじめる動画再生Swiftではじめる動画再生
Swiftではじめる動画再生
 

iOSで動画からスクショを撮る方法

  • 2. Who am I ? • Tomoya Itagawa (@gawawa124) • フリーランスのiPhoneアプリエンジニア • Objective-Cを3年くらい • Swiftは2になってからちょっと触ってた
  • 6. 普通のUIViewの場合は? func imageFromView() -> UIImage? { UIGraphicsBeginImageContextWithOptions(size, false, 0) if let context = UIGraphicsGetCurrentContext() { layer.renderInContext(context) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image; } return nil } 問題ない
  • 8. How? - 0.動画再生準備 • AVPlayer(動画を再生するためのもの) • AVPlayerItem(AVPlayerに渡す動画ファイ ル) • AVPlayerLayer(実際に見える画面)
  • 9. How? - 1.CADisplayLinkと AVPlayerItemVideoOutput • CADisplayLink(画面更新のたびに呼び出され るメソッドを提供するタイマーオブジェクト) • AVPlayerItemVideoOutput(動画から出力さ れる情報を司っている) • AVPlayerItemにaddVideoOutputで紐付ける
  • 10. How? - 2.コールバックから UIImageに変換していく 1. AVPlayerItemVideoOutput 2. CVPixelBuffer 3. CIImage 4. CGImage 5. UIImage どうしてこんなに面倒な感じなのかは後述
  • 11. CADisplayLinkのコールバックから UIImageに変換 func displayLinkCallback(sender: CADisplayLink) { var outputItemTime: CMTime = kCMTimeInvalid let nextVsync: CFTimeInterval = sender.timestamp + sender.duration outputItemTime = videoOutput.itemTimeForHostTime(nextVsync) if videoOutput.hasNewPixelBufferForItemTime(outputItemTime) { if let pixelBuffer = videoOutput.copyPixelBufferForItemTime(outputItemTime, itemTimeForDisplay: nil) { let ciImage = CIImage(CVPixelBuffer: pixelBuffer) let temporaryContext = CIContext(options: nil) let videoImage = temporaryContext.createCGImage( ciImage, fromRect: CGRectMake( 0, 0, CGFloat(CVPixelBufferGetWidth(pixelBuffer)), CGFloat(CVPixelBufferGetHeight(pixelBuffer)))) backgroundImageView.image = UIImage(CGImage: videoImage) } } }
  • 12. CADisplayLinkのコールバックから UIImageに変換 func displayLinkCallback(sender: CADisplayLink) { var outputItemTime: CMTime = kCMTimeInvalid let nextVsync: CFTimeInterval = sender.timestamp + sender.duration outputItemTime = videoOutput.itemTimeForHostTime(nextVsync) if videoOutput.hasNewPixelBufferForItemTime(outputItemTime) { if let pixelBuffer = videoOutput.copyPixelBufferForItemTime(outputItemTime, itemTimeForDisplay: nil) { let ciImage = CIImage(CVPixelBuffer: pixelBuffer) let temporaryContext = CIContext(options: nil) let videoImage = temporaryContext.createCGImage( ciImage, fromRect: CGRectMake( 0, 0, CGFloat(CVPixelBufferGetWidth(pixelBuffer)), CGFloat(CVPixelBufferGetHeight(pixelBuffer)))) backgroundImageView.image = UIImage(CGImage: videoImage) } } } 指定するための時間 時間を指定して pixelBufferを取得
  • 13. CADisplayLinkのコールバックから UIImageに変換 func displayLinkCallback(sender: CADisplayLink) { var outputItemTime: CMTime = kCMTimeInvalid let nextVsync: CFTimeInterval = sender.timestamp + sender.duration outputItemTime = videoOutput.itemTimeForHostTime(nextVsync) if videoOutput.hasNewPixelBufferForItemTime(outputItemTime) { if let pixelBuffer = videoOutput.copyPixelBufferForItemTime(outputItemTime, itemTimeForDisplay: nil) { let ciImage = CIImage(CVPixelBuffer: pixelBuffer) let temporaryContext = CIContext(options: nil) let videoImage = temporaryContext.createCGImage( ciImage, fromRect: CGRectMake( 0, 0, CGFloat(CVPixelBufferGetWidth(pixelBuffer)), CGFloat(CVPixelBufferGetHeight(pixelBuffer)))) backgroundImageView.image = UIImage(CGImage: videoImage) } } } CIImageをそのままUIImageに するとうまく描画されない!
  • 15. Demo
  • 16. 参考資料 • Swift Docs(006 動画の再生) https://sites.google.com/a/gclue.jp/ swift-docs/ni-yinki100-ios/3-avfoundation/006-dong-huano-zai- sheng • iOS Developer Library(Real-time Video Processing Using AVPlayerItemVideoOutput) https://developer.apple.com/ library/prerelease/ios/samplecode/AVBasicVideoOutput/ Introduction/Intro.html • stack over flow(How to turn a CVPixelBuffer into a UIImage?) http://stackoverflow.com/questions/8072208/how-to-turn-a- cvpixelbuffer-into-a-uiimage