★ バンドル内の.mp3ファイルを再生する
import AVFoundation
// インスタンス変数として保持する
var player: AVAudioPlayer!
if let url = Bundle.main.url(forResource: "cat", withExtension: "mp3") {
do {
player = try AVAudioPlayer(contentsOf: url)
player.play()
} catch {
print("エラー")
}
}
★ バンドル内の.mp4ファイルを再生する
import UIKit
import AVFoundation
class ViewController: UIViewController {
var playerItem: AVPlayerItem?
var videoPlayer: AVPlayer?
var playerLayer: AVPlayerLayer?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
play()
}
func play() {
if let path = Bundle.main.path(forResource: "sample", ofType: "mp4") {
let fileURL = NSURL(fileURLWithPath: path)
let avAsset = AVAsset(url: fileURL as URL)
playerItem = AVPlayerItem(asset: avAsset)
videoPlayer = AVPlayer(playerItem: playerItem)
playerLayer = AVPlayerLayer(player: videoPlayer)
playerLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
playerLayer?.frame = view.bounds
view.layer.addSublayer(playerLayer!)
videoPlayer?.play()
videoPlayer?.rate = 2.0
}
}
// Rateを変更
@IBAction func valueChanged(_ sender: UISlider) {
videoPlayer?.rate = sender.value
}
}
★ UIViewの上にガメラ画像を表示する
※ボタン押下でカメラロールに保存
参考URL: iOS10カスタムカメラ - Swift 3
import UIKit
import AVFoundation
class ViewController: UIViewController, AVCapturePhotoCaptureDelegate {
// カメラの映像をここに表示
@IBOutlet weak var cameraView: UIView!
var captureSesssion: AVCaptureSession!
var stillImageOutput: AVCapturePhotoOutput?
var previewLayer: AVCaptureVideoPreviewLayer?
override func viewDidLoad() {
super.viewDidLoad()
cameraView.layer.borderColor = UIColor.gray.cgColor
cameraView.layer.borderWidth = 1.0
cameraView.layer.cornerRadius = 5
cameraView.layer.masksToBounds = true
}
// ボタンを押した時呼ばれる
@IBAction func takeIt(_ sender: AnyObject) {
// フラッシュとかカメラの細かな設定
let settingsForMonitoring = AVCapturePhotoSettings()
settingsForMonitoring.flashMode = .auto
settingsForMonitoring.isAutoStillImageStabilizationEnabled = true
settingsForMonitoring.isHighResolutionPhotoEnabled = false
// シャッターを切る
stillImageOutput?.capturePhoto(with: settingsForMonitoring, delegate: self)
}
override func viewWillAppear(_ animated: Bool) {
captureSesssion = AVCaptureSession()
stillImageOutput = AVCapturePhotoOutput()
captureSesssion.sessionPreset = AVCaptureSessionPreset1920x1080 // 解像度の設定
let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
do {
let input = try AVCaptureDeviceInput(device: device)
// 入力
if captureSesssion.canAddInput(input) {
captureSesssion.addInput(input)
// 出力
if (captureSesssion.canAddOutput(stillImageOutput)) {
captureSesssion.addOutput(stillImageOutput)
captureSesssion.startRunning() // カメラ起動
previewLayer = AVCaptureVideoPreviewLayer(session: captureSesssion)
previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill // AspectFill
previewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.portrait // カメラの向き
cameraView.layer.addSublayer(previewLayer!)
// ビューのサイズの調整
previewLayer?.position = CGPoint(x: self.cameraView.frame.width / 2, y: self.cameraView.frame.height / 2)
previewLayer?.bounds = cameraView.frame
}
}
}
catch {
print(error)
}
}
// デリゲート。カメラで撮影が完了した後呼ばれる。JPEG形式でフォトライブラリに保存。
func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {
if let photoSampleBuffer = photoSampleBuffer {
// JPEG形式で画像データを取得
let photoData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer)
let image = UIImage(data: photoData!)
// フォトライブラリに保存
UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
}
}
}
カメラロール、カメラ許可plistに記述する
<key>NSCameraUsageDescription</key>
<string>Camera許可メッセージ</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo Library許可メッセージ</string>
★ カメラのフラッシュを点灯させる
func toggleFlash() {
if let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) {
if (device.hasTorch) {
do {
try device.lockForConfiguration()
if (device.torchMode == AVCaptureTorchMode.on) {
device.torchMode = AVCaptureTorchMode.off
} else {
do {
try device.setTorchModeOnWithLevel(1.0)
} catch {
print(error)
}
}
device.unlockForConfiguration()
} catch {
print(error)
}
}
}
}
- カメラを起動横向きの対応をする
Swift - iOSでビデオカメラを使用時、端末の向きに対応
import UIKit
import AVFoundation
import Photos
extension UIViewController:AVCapturePhotoCaptureDelegate {
//映像をキャプチャする
public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
//データを取り出す
guard let photoData = photo.fileDataRepresentation() else {
return
}
//Dataから写真イメージを作る
if let stillImage = UIImage(data: photoData) {
//移動先のビューコントローラーを参照する
let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "preview")as! previewViewController
//トランジションの映像効果を指定する
// nextVC?.modalTransitionStyle = .flipHorizontal
nextVC.image = stillImage
//シーンを移動する
present(nextVC, animated: true, completion: nil)
}
}
}
class ViewController: UIViewController {
@IBOutlet weak var previewView: UIView!
@IBOutlet weak var shutterButton: UIButton!
var previewLayer: AVCaptureVideoPreviewLayer!
// インスタンスの作成
var session = AVCaptureSession()
var photoOutputObj = AVCapturePhotoOutput()
// 通知センターを作る
let notification = NotificationCenter.default
// プライバシーと入出力のステータス
var authStatus:AuthorizedStatus = .authorized
var inOutStatus:InputOutputStatus = .ready
// 認証のステータス
enum AuthorizedStatus {
case authorized
case notAuthorized
case failed
}
// 入出力のステータス
enum InputOutputStatus {
case ready
case notReady
case failed
}
// ビューが表示された直後に実行
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// セッション実行中ならば中断する
guard !session.isRunning else {
return
}
// カメラのプライバシー認証確認
cameraAuth()
// 入出力の設定
setupInputOutput()
// カメラの準備ができているかどうか
if (authStatus == .authorized)&&(inOutStatus == .ready){
// プレビューレイヤの設定
setPreviewLayer()
// セッション開始
session.startRunning()
shutterButton.isEnabled = true
} else {
// アラートを出す
showAlert(appName: "カメラ")
}
}
// シャッターボタンで実行する
@IBAction func takePhoto(_ sender: Any) {
if (authStatus == .authorized)&&(inOutStatus == .ready){
let captureSetting = AVCapturePhotoSettings()
captureSetting.flashMode = .auto
captureSetting.isAutoStillImageStabilizationEnabled = true
captureSetting.isHighResolutionPhotoEnabled = false
// キャプチャのイメージ処理はデリゲートに任せる
photoOutputObj.capturePhoto(with: captureSetting, delegate: self)
} else {
// カメラの利用を許可しなかったにも関わらずボタンをタップした(初回起動時のみ)
showAlert(appName: "カメラ")
}
}
// カメラのプライバシー認証確認
func cameraAuth(){
let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
switch status {
case .notDetermined:
// 初回起動時
AVCaptureDevice.requestAccess(for: AVMediaType.video,
completionHandler: { [unowned self] authorized in
print("初回", authorized.description)
if authorized {
self.authStatus = .authorized
} else {
self.authStatus = .notAuthorized
}})
case .restricted, .denied:
authStatus = .notAuthorized
case .authorized:
authStatus = .authorized
}
}
// 入出力の設定
func setupInputOutput(){
//解像度の指定
session.sessionPreset = AVCaptureSession.Preset.photo
// 入力の設定
do {
//デバイスの取得
let device = AVCaptureDevice.default(
AVCaptureDevice.DeviceType.builtInWideAngleCamera,
for: AVMediaType.video, // ビデオ入力
position: AVCaptureDevice.Position.back) // バックカメラ
// 入力元
let input = try AVCaptureDeviceInput(device: device!)
if session.canAddInput(input){
session.addInput(input)
} else {
print("セッションに入力を追加できなかった")
return
}
} catch let error as NSError {
print("カメラがない \(error)")
return
}
// 出力の設定
if session.canAddOutput(photoOutputObj) {
session.addOutput(photoOutputObj)
} else {
print("セッションに出力を追加できなかった")
return
}
}
// UIInterfaceOrientation -> AVCaptureVideoOrientationにConvert
func convertUIOrientation2VideoOrientation(f: () -> UIInterfaceOrientation) -> AVCaptureVideoOrientation? {
let v = f()
switch v {
case UIInterfaceOrientation.unknown: return nil
default:
return ([
.portrait: .portrait,
.portraitUpsideDown: .portraitUpsideDown,
.landscapeLeft: .landscapeLeft,
.landscapeRight: .landscapeRight
])[v]
}
}
func appOrientation() -> UIInterfaceOrientation {
return UIApplication.shared.statusBarOrientation
}
// プレビューレイヤの設定
func setPreviewLayer(){
// プレビューレイヤを作る
previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.frame = view.bounds
previewLayer.masksToBounds = true
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspect
if let orientation = self.convertUIOrientation2VideoOrientation(f: { return self.appOrientation() } ) {
previewLayer.connection?.videoOrientation = orientation
}
// previewViewに追加する
previewView.layer.addSublayer(previewLayer)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let previewLayer = previewLayer {
previewLayer.frame = view.bounds
}
}
// 画面の回転にも対応したい時は viewWillTransitionToSize で同じく向きを教える。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(
alongsideTransition: nil,
completion: {(UIViewControllerTransitionCoordinatorContext) in
//画面の回転後に向きを教える。
if let orientation = self.convertUIOrientation2VideoOrientation(f: {return self.appOrientation()}) {
self.previewLayer.connection?.videoOrientation = orientation
}
}
)
}
// プライバシー認証のアラートを表示する
func showAlert(appName:String){
let aTitle = appName + "のプライバシー認証"
let aMessage = "設定>プライバシー>" + appName + "で利用を許可してください。"
let alert = UIAlertController(title: aTitle, message: aMessage, preferredStyle: .alert)
// OKボタン(何も実行しない)
alert.addAction(
UIAlertAction(title: "OK",style: .default,handler: nil)
)
// 設定を開くボタン
alert.addAction(
UIAlertAction(
title: "設定を開く",style: .default,
handler: { action in
UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!, options: [:], completionHandler: nil)
})
)
// アラートを表示する
self.present(alert, animated: false, completion:nil)
}
}