2

La manière la plus simple d'enregistrer une vidéo sur iOS consiste à définir un AVCaptureSession.sessionPreset.Comment enregistrer une vidéo sur iOS sans utiliser de préréglage?

Mais cela ne fonctionne pas pour moi puisque je veux contrôler des paramètres comme le binning, la stabilisation (cinématique, standard ou aucun) et ISO.

Je trouve le format que je veux et lui attribuer à activeFormat, mais lorsque je tente de lancer l'enregistrement, je reçois une erreur:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 
'*** -[AVCaptureMovieFileOutput startRecordingToOutputFileURL:recordingDelegate:] No active/enabled connections' 

Voici mon code d'initialisation:

let device = AVCaptureDevice.defaultDevice(
    withDeviceType: .builtInWideAngleCamera, 
    mediaType: AVMediaTypeVideo, 
    position: .back)! 
let session = AVCaptureSession() 
session.addInput(try! AVCaptureDeviceInput(device: device)) 
output = AVCaptureMovieFileOutput() 
session.addOutput(output) 
device.setFormatWithHighestIso() 
session.startRunning() 

setFormatWithHighestIso() est défini comme:

extension AVCaptureDevice { 
    var goodVideoFormats: [AVCaptureDeviceFormat] { 
    return (formats as! [AVCaptureDeviceFormat]) 
     .filter { CMFormatDescriptionGetMediaSubType($0.formatDescription) != 875704422 } // 420f 
     .filter { $0.autoFocusSystem == .phaseDetection } 
    } 

    func setFormatWithHighestIso() { 
    let format = goodVideoFormats 
     .filter { $0.maxISO > 1759 } 
     .filter { $0.height < 1937 } 
     .first! 

    try! lockForConfiguration() 
    defer { unlockForConfiguration() } 
    activeFormat = format 
    NSLog("\(format)") 
    } 
} 

La dernière instruction de consignation produit:

<AVCaptureDeviceFormat: 0x1702027d0 'vide'/'420f' 2592x1936, { 3- 30 fps}, HRSI:4032x3024, fov:58.986, max zoom:189.00 (upscales @1.56), AF System:2, ISO:22.0-1760.0, SS:0.000005-0.333333, supports wide color> 

C'est en effet le format que je veux, si setFormatWithHighestIso() fonctionne comme prévu. Voir la pomme reference.


D'autres choses que j'essayé:

  • En utilisant 420V au lieu de 420F, en changeant la == 875704422 to =!. Au lieu de démarrer l'appareil photo en mode photo, démarrez-le en mode vidéo, puis passez en mode vidéo en supprimant AVCapturePhotoOutput et en ajoutant AVCaptureMovieFileOutput.
  • Vérification que AVCaptureConnection est activé et qu'il l'est.
  • Vérifier que la connexion est active, mais ce n'est pas:

    conn = output.connection soyez (withMediaType: AVMediaTypeVideo)! vérifier (conn.isActive)

J'ai aussi essayé d'utiliser une autre AVCaptureDeviceFormats, et ils travaillent:

extension AVCaptureDevice { 
    func setFormatWithCinematicVS() { 
    let format = goodVideoFormats 
     .filter { $0.isVideoStabilizationModeSupported(.cinematic) } 
     .filter { $0.height == 720 } 
     .first! 

    try! lockForConfiguration() 
    defer { unlockForConfiguration() } 
    activeFormat = format 
    } 

    func setFormatWithStandardVS() { 
    let format = goodVideoFormats 
     .filter { $0.isVideoStabilizationModeSupported(.standard) } 
     .filter { $0.height == 540 } 
     .first! 

    try! lockForConfiguration() 
    defer { unlockForConfiguration() } 
    activeFormat = format 
    } 
} 

Il est seulement le format le plus élevé ISO qui ne fonctionne pas. Quelle est la particularité de ce format?

Dois-je créer manuellement un AVCaptureConnection? Mais il y a déjà une connexion; ce n'est pas actif.

Ceci est sur l'iPhone 7 Plus exécutant iOS 10.3.3. Comment enregistrer une vidéo dans un format spécifique en définissant le format activeFormat sans utiliser de session?

Si, au lieu d'assigner à activeFormat, j'utilise un sessionPreset, il enregistre une vidéo avec succès.


D'autres questions parlent de ce message d'erreur, mais ce n'est pas dupe d'entre eux puisque j'ai besoin spécifiquement pour capturer la vidéo sans utiliser un préréglage.

+0

Je voudrais essayer cela, mais ne dispose pas d'un 7+ - il n'y a pas d'erreur analogue sur d'autres modèles? Pourriez-vous ajouter le message d'erreur? Et peut-être un lien vers un repro runnable? –

+0

J'ai inclus l'erreur dans la question. Je vais essayer de créer un repro exécutable, mais en attendant, quels appareils avez-vous? Je vais vous dire quel format essayer de repro. –

+0

J'ai un 6s - cela fonctionnera-t-il? –

Répondre

0

La solution se sont avérés être la configuration du AVCaptureDevice avant de l'ajouter à une session. Au lieu de:

session.addInput(try! AVCaptureDeviceInput(device: device)) 
output = AVCaptureMovieFileOutput() 
session.addOutput(output) 
device.setFormatWithHighestIso() 

Vous devriez faire:

device.setFormatWithHighestIso() // Do this first! 
session.addInput(try! AVCaptureDeviceInput(device: device)) 
output = AVCaptureMovieFileOutput() 
session.addOutput(output) 

Lorsque l'appareil est ajouté à la session, un AVCaptureConnection est créé et configuré d'une certaine manière. Si vous modifiez la résolution de l'appareil plus tard, la configuration ne correspond plus, la connexion est désactivée et la vidéo n'enregistre pas.