#author("2023-11-04T19:33:15+09:00","default:shota","shota")
#author("2023-11-04T19:37:07+09:00","default:shota","shota")
[[FrontPage]]

*概要 [#s17f6516]
-iOS13より複数のカメラで同時撮影するAPIが追加された
-ズームレンズよりもメインレンズのほうが低照度環境でもノイズが乗りにくいが,ズームで取りたい場合もある→両方撮影して良い方を選べば良いのでは
-結論: iPhone15ProMaxにおいて複数カメラのビデオ撮影では4Kをサポートしていない.1080pが最大である

*コード [#icd019d8]
-最大撮影フォーマットを調べるためのコード

#highlightjs(swift)
 import AVFoundation
 import UIKit
 import Photos
 
 class ViewController: UIViewController {
    @IBOutlet weak var previewView: UIView!
    
    private var captureSession = AVCaptureMultiCamSession()
    
    private var audioInput: AVCaptureDeviceInput!
    private var audioPort: AVCaptureDeviceInput.Port!
    
    // 広角カメラの設定
    private var wideAngleInput: AVCaptureDeviceInput!
    private var wideAnglePort: AVCaptureDeviceInput.Port!
    private var wideAngleOutput: AVCaptureMovieFileOutput!
    private var wideAngleVideoConnection: AVCaptureConnection!
    
    // 望遠カメラの設定
    private var telephotoInput: AVCaptureDeviceInput!
    private var telephotoPort: AVCaptureDeviceInput.Port!
    private var telephotoOutput: AVCaptureMovieFileOutput!
    private var telephotoVideoConnection: AVCaptureConnection!
    
    // プレビュー
    private var videoPreviewLayer: AVCaptureVideoPreviewLayer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // マルチキャプチャをサポートしているかどうか
        guard AVCaptureMultiCamSession.isMultiCamSupported else {
            fatalError()
        }
        
        setupSession()
    }
 
    // MARK: - セッションの設定
    private func setupSession() {
        captureSession.beginConfiguration()
        
        // マイクの準備
        do {
            let microphone = AVCaptureDevice.default(for: .audio)!
            let input = try AVCaptureDeviceInput(device: microphone)
            guard captureSession.canAddInput(input) else {
                fatalError()
            }
            
            audioInput = input
            captureSession.addInputWithNoConnections(input)
            
            guard let audioPort = input.ports(for: .audio,
                                              sourceDeviceType: microphone.deviceType,
                                              sourceDevicePosition: .back).first else {
                fatalError()
            }
            
            self.audioPort = audioPort
        }
        catch {
            fatalError(error.localizedDescription)
        }
        
        // カメラの利用準備
        do {
            try setupWideCamera()
            try setupTeleCamera()
            
            previewView.layer.addSublayer(videoPreviewLayer)
            videoPreviewLayer.frame = previewView.layer.frame
                        
            captureSession.commitConfiguration()
            captureSession.startRunning()
            
            if captureSession.canSetSessionPreset(.hd4K3840x2160) {
                print("4k利用可能")
            }
            else {
                print("4k利用不可能")
            }
        }
        catch {
            print("error")
        }
    }
    
    // MARK: - 広角カメラの設定
    
    private func setupWideCamera() throws {
        guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera,
                                                   for: .video,
                                                   position: .back) else {
            print("camera not founc")
            throw NSError()
        }
        
        // sessinに追加
        wideAngleInput = try AVCaptureDeviceInput(device: camera)
        guard captureSession.canAddInput(wideAngleInput) else {
            print("can not add camera input")
            throw NSError()
        }
        
        captureSession.addInputWithNoConnections(wideAngleInput)
        
        guard let wideAnglePort = wideAngleInput.ports(
            for: .video, sourceDeviceType: camera.deviceType,
            sourceDevicePosition: camera.position).first else {
            print("can not find wide angle port")
            throw NSError()
        }
        
        self.wideAnglePort = wideAnglePort
        
        // outputをsessionに追加する
        wideAngleOutput = AVCaptureMovieFileOutput()
        guard captureSession.canAddOutput(wideAngleOutput) else {
            print("can not add wide angle output")
            throw NSError()
        }
        
        captureSession.addOutputWithNoConnections(wideAngleOutput)
        
        // inputとoutputを接続する
        wideAngleVideoConnection = AVCaptureConnection(
            inputPorts: [wideAnglePort], output: wideAngleOutput)
        
        wideAngleVideoConnection.videoOrientation = .portrait
        if (wideAngleVideoConnection.isVideoStabilizationSupported) {
            wideAngleVideoConnection.preferredVideoStabilizationMode = .cinematicExtended
        }
        
        guard captureSession.canAddConnection(wideAngleVideoConnection) else {
            print("can not add wide angle video connetion")
            throw NSError()
        }
        
        captureSession.addConnection(wideAngleVideoConnection)
        
        // マイクとoutputを接続する
        let audioConnection = AVCaptureConnection(
            inputPorts: [audioPort], output: wideAngleOutput)
        
        guard captureSession.canAddConnection(audioConnection) else {
            print("can not add audio connection")
            throw NSError()
        }
    }
    
    
    // MARK: - 望遠カメラの設定
    private func setupTeleCamera() throws {
        guard let camera = AVCaptureDevice.default(
            .builtInTelephotoCamera, for: .video, position: .back) else {
            print("not found builtin telephoto camera")
            throw NSError()
        }
        
        telephotoInput = try AVCaptureDeviceInput(device: camera)
        guard captureSession.canAddInput(telephotoInput) else {
            print("can not add telephoto camera")
            throw NSError()
        }
        
        captureSession.addInputWithNoConnections(telephotoInput)
        
        guard let telephotoPort = telephotoInput.ports(
            for: .video,
            sourceDeviceType: camera.deviceType,
            sourceDevicePosition: camera.position).first else {
            print("can not fine telephoto input port")
            throw NSError()
        }
        
        self.telephotoPort = telephotoPort
        
        // outputの設定
        telephotoOutput = AVCaptureMovieFileOutput()
        guard captureSession.canAddOutput(telephotoOutput) else {
            print("can not add telephoto output")
            throw NSError()
        }
        
        captureSession.addOutputWithNoConnections(telephotoOutput)
        
        // inputとoutputを接続する
        telephotoVideoConnection = AVCaptureConnection(
            inputPorts: [telephotoPort], output: telephotoOutput)
        
        telephotoVideoConnection.videoOrientation = .portrait
        if telephotoVideoConnection.isVideoStabilizationSupported {
            telephotoVideoConnection.preferredVideoStabilizationMode = .cinematicExtended
        }
        
        guard captureSession.canAddConnection(telephotoVideoConnection) else {
            print("can not add telephoto video connection")
            throw NSError()
        }
        
        captureSession.addConnection(telephotoVideoConnection)
        
        // マイクとinputとoutputを接続する
        let audioConnection = AVCaptureConnection(
            inputPorts: [audioPort], output: telephotoOutput)
        
        guard captureSession.canAddConnection(audioConnection) else {
            print("can not add audio connection. telephoto")
            throw NSError()
        }
        
        captureSession.addConnection(audioConnection)
        
        // プレビューの設定
        videoPreviewLayer = AVCaptureVideoPreviewLayer()
        videoPreviewLayer.setSessionWithNoConnection(captureSession)
        videoPreviewLayer.videoGravity = .resizeAspect
        videoPreviewLayer.bounds = previewView.bounds
        
        let layerConnection = AVCaptureConnection(
            inputPort: telephotoPort, videoPreviewLayer: videoPreviewLayer)
        layerConnection.videoOrientation = .portrait
        
        guard captureSession.canAddConnection(layerConnection) else {
            print("can not add layer connection")
            throw NSError()
        }
        
        captureSession.addConnection(layerConnection)
    }
 }

*感想 [#i1575abb]
4k撮影をサポートしているのであれば,チューニングされた標準カメラアプリから自作のアプリを利用するメリットはあると思い調査した.
iPadProといったM2チップを搭載している端末であれば4K撮影可能かもしれないがA17Proでは非対応のため,まだまだ標準カメラアプリにお世話になる.

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS