2016-01-10 7 views
13

L'obiettivo è catturare video a schermo intero su un dispositivo con Swift. Nel codice qui sotto, l'acquisizione video sembra avvenire a schermo intero (mentre la registrazione dell'anteprima della telecamera utilizza l'intero schermo), ma il rendering del video avviene a una risoluzione diversa. Per un 5S in particolare, sembra che l'acquisizione avvenga a 320x568 ma il rendering avviene a 320x480.Swift: registrazioni video in una sola dimensione ma con dimensioni errate

Come è possibile acquisire e visualizzare video a schermo intero?

Codice per la cattura video:

private func initPBJVision() { 
    // Store PBJVision in var for convenience 
    let vision = PBJVision.sharedInstance() 

    // Configure PBJVision 
    vision.delegate = self 
    vision.cameraMode = PBJCameraMode.Video 
    vision.cameraOrientation = PBJCameraOrientation.Portrait 
    vision.focusMode = PBJFocusMode.ContinuousAutoFocus 
    vision.outputFormat = PBJOutputFormat.Preset 
    vision.cameraDevice = PBJCameraDevice.Back 

    // Let taps start/pause recording 
    let tapHandler = UITapGestureRecognizer(target: self, action: "doTap:") 
    view.addGestureRecognizer(tapHandler) 

    // Log status 
    print("Configured PBJVision") 
} 


private func startCameraPreview() { 
    // Store PBJVision in var for convenience 
    let vision = PBJVision.sharedInstance() 

    // Connect PBJVision camera preview to <videoView> 
    // -- Get preview width 
    let deviceWidth = CGRectGetWidth(view.frame) 
    let deviceHeight = CGRectGetHeight(view.frame) 

    // -- Configure PBJVision's preview layer 
    let previewLayer = vision.previewLayer 
    previewLayer.frame = CGRectMake(0, 0, deviceWidth, deviceHeight) 
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill 
    ... 
} 

Video codice di rendering:

func exportVideo(fileUrl: NSURL) { 
    // Create main composition object 
    let videoAsset = AVURLAsset(URL: fileUrl, options: nil) 
    let mainComposition = AVMutableComposition() 
    let compositionVideoTrack = mainComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) 
    let compositionAudioTrack = mainComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid)) 

    // -- Extract and apply video & audio tracks to composition 
    let sourceVideoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0] 
    let sourceAudioTrack = videoAsset.tracksWithMediaType(AVMediaTypeAudio)[0] 
    do { 
     try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: sourceVideoTrack, atTime: kCMTimeZero) 
    } catch { 
     print("Error with insertTimeRange. Video error: \(error).") 
    } 
    do { 
     try compositionAudioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: sourceAudioTrack, atTime: kCMTimeZero) 
    } catch { 
     print("Error with insertTimeRange. Audio error: \(error).") 
    } 

    // Add text to video 
    // -- Create video composition object 
    let renderSize = compositionVideoTrack.naturalSize 
    let videoComposition = AVMutableVideoComposition() 
    videoComposition.renderSize = renderSize 
    videoComposition.frameDuration = CMTimeMake(Int64(1), Int32(videoFrameRate)) 

    // -- Add instruction to video composition object 
    let instruction = AVMutableVideoCompositionInstruction() 
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration) 
    let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: compositionVideoTrack) 
    instruction.layerInstructions = [videoLayerInstruction] 
    videoComposition.instructions = [instruction] 

    // -- Define video frame 
    let videoFrame = CGRectMake(0, 0, renderSize.width, renderSize.height) 
    print("Video Frame: \(videoFrame)") // <-- Prints frame of 320x480 so render size already wrong here 
    ... 
+0

hai visto il valore 'naturalSize'? che cos'è? E cosa farai dopo? Stai usando 'AVAssetExportSession'? – rkyr

+0

@rkyr sì, we 'renderSize' è uguale a' naturalSize'. Al momento della stampa la dimensione del rendering è già sbagliata (320x480), ecco perché non è stato incluso più codice. Eventuali suggerimenti? – Crashalot

risposta

8

Se ho ragione, sembra che tu abbia frainteso il fatto che la larghezza dello schermo del dispositivo is'n pari a dimensioni di anteprima e cattura della fotocamera.

La proprietà videoGravity del numero previewLayer indica come allungare/adattare l'anteprima all'interno del livello. Non influisce sull'output di cattura.

La dimensione effettiva del frame dell'output dipende dalla proprietà sessionPreset corrente del AVCaptureSession corrente. E come posso capire leggendo GitHub repository di PBJVision lib, il suo singleton ha setter per questo (chiamato captureSessionPreset). Puoi cambiarlo all'interno del tuo metodo initPBJVision.

There è possibile trovare i valori possibili dei preset di sessione.

+0

Grazie a @rkyr ma dai doc della classe, sembra che 'sessionPreset' influenzi il bitrate ma non le dimensioni effettive? Come si cambiano le dimensioni effettive dell'acquisizione e si ottiene che corrisponda all'anteprima? – Crashalot

+0

@Crashalot, cambia la qualità dell'immagine cambiandone la dimensione. L'API non ti ha permesso di impostare il frame di cattura. [Qui] (http://stackoverflow.com/a/14322378/5247504) puoi trovare come qualcuno si occupa di esso. – rkyr

+0

Ciao @rkyr qual è il modo migliore per raggiungerti? Vorrei fare una breve domanda. – Crashalot

3

Prova SDAVAssetExportSession

È possibile specificare il AVVideoWidthKey e AVVideoHeightKey è anche possibile specificare il profilo, AVVideoProfileLevelKey cioè AVVideoProfileLevelH264HighAutoLevel per sostenere qualcosa di 4k, un amico (Michael Lowin) rintracciato che la proprietà giù per aiutarci a migliorare un po ' qualità dell'esportazione.

+1

grazie Lamar, le belle modifiche di stile –

Problemi correlati