AVFoundationでアルバムから写真を選択して保存 Swift3
環境
- swift
- Swift3
- Xcode
- Xcode9
- AVFoundation
- video
ソース
実行
説明
iOSのアルバムから動画を選択してavfoundationでmacのドキュメントフォルダにアルバムから選択した動画を生成して保存します
実装
//
// ViewController.swift
// video-edit
//
// Created by ryosuke-hujisawa on 2017/10/04.
// Copyright © 2017年 ryosuke-hujisawa. All rights reserved.
//
import UIKit
import AVFoundation
import AVKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let imagePickerController = UIImagePickerController()
var videoURL: URL?
@IBAction func ChoiceCamera(_ sender: Any) {
print("UIBarButtonItem。カメラロールから動画を選択")
imagePickerController.sourceType = .photoLibrary
imagePickerController.delegate = self
imagePickerController.mediaTypes = ["public.image", "public.movie"]
present(imagePickerController, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//アルバムから選択した動画を変数に代入
let documentsPath = info[UIImagePickerControllerMediaURL] as! URL!
videoURL = documentsPath
//viewを戻す
picker.dismiss(animated: true, completion: nil)
}
@IBAction func SaveMovies(_ sender: Any) {
// 動画のurlを定義する
// Define the url of the video
let url = videoURL
//URL(string: "https://160.16.120.119/kkk.m4v")
// 動画URLからアセットを生成
// Generate assets from video URL
let videoAsset: AVURLAsset = AVURLAsset(url: url!)
// アセットからトラックを取得
// Get a track from an asset
let videoTrack: AVAssetTrack = videoAsset.tracks(withMediaType: AVMediaType.video)[0]
let audioTrack: AVAssetTrack = videoAsset.tracks(withMediaType: AVMediaType.audio)[0]
// ベースとなる動画のコンポジション作成
// Composition creation of the base video
let mainComposition : AVMutableComposition = AVMutableComposition()
// コンポジションのトラック作成
// Creating composition tracks
let compositionVideoTrack: AVMutableCompositionTrack = mainComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)!
let compositionAudioTrack: AVMutableCompositionTrack = mainComposition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)!
// コンポジションの設定
// Composition setting
try! compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoTrack, at: kCMTimeZero)
try! compositionAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: audioTrack, at: kCMTimeZero)
// ロゴのCALayerの作成
// Create logo CALayer
//let logoImage : UIImage = UIImage(named: "logo")!
// UIImage インスタンスの生成
// 画像はAssetsに入れてないのとjpgなので拡張子を入れます
let image1:UIImage = UIImage(named:"logo.png")!
// UIImageView 初期化
let logoImage = UIImageView(image:image1)
let logoLayer: CALayer = CALayer()
logoLayer.contents = logoImage
logoLayer.frame = CGRect(x: 5, y: 25, width: 57, height: 57)
logoLayer.opacity = 0.9
// 動画のサイズを取得
// Get video size
let videoSize: CGSize = videoTrack.naturalSize
// 親レイヤーを作成
// Create parent layer
let parentLayer: CALayer = CALayer()
let videoLayer: CALayer = CALayer()
parentLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
parentLayer.addSublayer(videoLayer)
parentLayer.addSublayer(logoLayer)
// 合成用コンポジション作成
// Composition composition creation
let videoComp = AVMutableVideoComposition()
videoComp.renderSize = videoSize
videoComp.frameDuration = CMTimeMake(1, 30)
videoComp.animationTool = AVVideoCompositionCoreAnimationTool.init(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
// インストラクション作成
// Instruction creation
let instruction: AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, mainComposition.duration)
let layerInstruction: AVMutableVideoCompositionLayerInstruction = AVMutableVideoCompositionLayerInstruction.init(assetTrack: videoTrack)
instruction.layerInstructions = [layerInstruction]
// インストラクションを合成用コンポジションに設定
// Set Instruction to Composition for Composition
videoComp.instructions = [instruction]
// 動画のコンポジションをベースにAVAssetExportを生成
// Generate AVAssetExport based on composition of video
let assetExport = AVAssetExportSession.init(asset: mainComposition, presetName: AVAssetExportPresetMediumQuality)
/*
下記が画像を動画に合成する処理。下記を記述する動画が生成されなくなる。
下記の処理を消すと、正常にmacのドキュメントフォルダに動画が生成される
Process below to combine images into moving images. A moving image describing the following will not be generated.
When the following processing is deleted, a movie is normally generated in the mac document folder
*/
// 合成用コンポジションを設定
// Set composition for composition
assetExport!.videoComposition = videoComp
// 生成された動画を保存する場所のurlとファイルの名前を設定(今回はmacの中のDocumentsディレクトリに保存)
// Set the url and file name where the generated video will be saved (this time saved in the Documents directory in mac)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
//生成する動画の名前
// Name of video to generate
let filePath = documentsDirectory.appendingPathComponent("rendered-audio.m4v")
// エクスポートファイルのビデオタイプの設定
// Setting the video type of the export file
assetExport?.outputFileType = AVFileType.mov
// 出力されるurlの設定
// Setting output url
assetExport?.outputURL = filePath
// これは必要?
// Is this necessary?
//assetExport?.shouldOptimizeForNetworkUse = true
assetExport?.exportAsynchronously {
//出力されたファイルのパスをprint表示
//Print the path of the outputted file
print("finished: \(filePath) : \(String(describing: assetExport?.status.rawValue)) ")
}
}
override func viewDidLoad() {
super.viewDidLoad()
print("Hello World")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}