2016-01-10 15 views
13

Celem jest uchwycenie pełnoekranowego wideo na urządzeniu za pomocą Swift. W poniższym kodzie przechwytywanie wideo wydaje się mieć miejsce na pełnym ekranie (podczas nagrywania podglądu z kamery korzysta z pełnego ekranu), ale renderowanie wideo odbywa się w innej rozdzielczości. W przypadku modelu 5S wygląda na to, że przechwytywanie odbywa się pod adresem 320x568, ale renderowanie odbywa się pod adresem 320x480.Swift: nagrania wideo w jednym rozmiarze, ale renderowane w niewłaściwym rozmiarze

Jak można przechwytywać i renderować wideo na pełnym ekranie?

Kod do przechwytywania wideo:

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 
    ... 
} 

Wideo kod renderowania:

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

Czy przyjrzałeś się wartości 'naturalSize'? co to jest? A co robisz dalej? Używasz 'AVAssetExportSession'? – rkyr

+0

@rkyr Tak, 'renderRozmiar' jest równy' naturalSize'. W momencie drukowania rozmiar renderingu jest już nieprawidłowy (320 x 480), dlatego nie zawierał więcej kodu. Jakieś sugestie? – Crashalot

Odpowiedz

8

Gdybym Ci rację, wydaje się, że masz źle fakt szerokości ekranu urządzenia is'n równa podgląd kamery (i przechwytywanie).

Właściwość videoGravity Twojego previewLayer wskazuje, jak rozciągnąć/dopasować podgląd do warstwy. Nie wpływa na wynik wychwytywania.

Rzeczywisty rozmiar klatki wyjściowej zależy od właściwości sessionPreset twojego aktualnego . I jak mogę zrozumieć czytając repozytorium GitHub biblioteki PBJVision, jego singleton ma ustawiacz dla tego (zwany captureSessionPreset). Możesz go zmienić w swojej metodzie initPBJVision.

There można znaleźć możliwe wartości ustawień wstępnych sesji.

+0

Dzięki @rkyr ale z dokumentacji klas, wydaje się, że 'sessionPreset' wpływa na bitrate, ale nie na faktyczne wymiary? Jak zmienić rzeczywiste wymiary przechwytywania i dopasować je do podglądu? – Crashalot

+0

@Crashalot, zmienia jakość obrazu poprzez zmianę jego wymiaru. Interfejs API nie pozwala ustawić ramki przechwytywania. [Tutaj] (http://stackoverflow.com/a/14322378/5247504) można znaleźć, jak ktoś sobie z tym poradzić. – rkyr

+0

Witaj @rkyr, jaki jest najlepszy sposób, aby do Ciebie dotrzeć? Chciałbym zadać szybkie pytanie. – Crashalot

3

Spróbuj SDAVAssetExportSession

Można określić AVVideoWidthKey i AVVideoHeightKey Można również określić profil, AVVideoProfileLevelKey tj AVVideoProfileLevelH264HighAutoLevel wspierania coś 4k, przyjaciel (Michael Löwin) śledzone że nieruchomość w dół, aby pomóc nam udoskonalić niektóre cechy eksportowe.

+1

dzięki Lamar, ładne zmiany w stylu –