2016-01-10 20 views
13

Mục tiêu là chụp toàn màn hình video trên thiết bị bằng Swift. Trong đoạn mã bên dưới, việc quay video xuất hiện ở chế độ toàn màn hình (trong khi ghi lại xem trước máy ảnh sử dụng toàn màn hình), nhưng việc hiển thị video diễn ra ở độ phân giải khác. Đối với 5S đặc biệt, có vẻ như việc chụp hình xảy ra tại 320x568 nhưng hiển thị diễn ra tại 320x480.Swift: các bản ghi video ở một kích thước nhưng hiển thị ở kích thước sai

Làm cách nào bạn có thể chụp và hiển thị video toàn màn hình?

Mã cho quay 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 đang render:

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

bạn có nhìn vào giá trị 'naturalSize' không? nó là gì? Và bạn đang làm gì tiếp theo? Bạn đang sử dụng 'AVAssetExportSession'? – rkyr

+0

@rkyr vâng, chúng tôi 'renderSize' bằng 'naturalSize'. Tại thời điểm in ra, kích thước hiển thị đã sai (320x480), vì vậy đó là lý do tại sao không có thêm mã nào được bao gồm. Bất kỳ đề xuất? – Crashalot

Trả lời

8

Nếu tôi giúp bạn có được ngay, có vẻ như bạn đã hiểu lầm thực tế là độ rộng màn hình điện thoại is'n bằng kích thước xem trước máy ảnh (và chụp).

Thuộc tính videoGravity của previewLayer cho biết cách kéo dài/vừa với bản xem trước của bạn trong lớp. Nó không ảnh hưởng đến đầu ra chụp.

Kích thước khung hình thực tế phụ thuộc vào sessionPreset thuộc tính hiện tại của bạn AVCaptureSession. Và như tôi có thể hiểu bằng cách đọc kho GitHub của PBJVision lib, singleton của nó đã setter cho điều này (được gọi là captureSessionPreset). Bạn có thể thay đổi nó bên trong phương thức initPBJVision của mình.

There bạn có thể tìm các giá trị có thể có của giá trị đặt trước phiên.

+0

Cảm ơn @ rkyr nhưng từ tài liệu lớp học, có vẻ như 'sessionPreset' ảnh hưởng đến tốc độ bit chứ không phải kích thước thực tế? Làm thế nào để bạn thay đổi kích thước thực tế của việc chụp và làm cho nó phù hợp với bản xem trước? – Crashalot

+0

@Crashalot, nó thay đổi chất lượng hình ảnh bằng cách thay đổi kích thước của nó. API không cho phép bạn đặt khung chụp. [Ở đây] (http://stackoverflow.com/a/14322378/5247504) bạn có thể tìm thấy cách ai đó đối phó với nó. – rkyr

+0

Hi @rkyr cách nào tốt nhất để liên lạc với bạn? Muốn hỏi một câu hỏi nhanh. – Crashalot

3

Hãy thử SDAVAssetExportSession

Bạn có thể chỉ định AVVideoWidthKeyAVVideoHeightKey Bạn cũng có thể xác định cấu hình, AVVideoProfileLevelKey tức AVVideoProfileLevelH264HighAutoLevel để hỗ trợ cái gì đó 4k, một người bạn (Michael Lowin) theo dõi rằng bất động sản xuống để giúp chúng tôi cải thiện một số phẩm chất xuất khẩu.

+1

cảm ơn Lamar, chỉnh sửa kiểu đẹp –

Các vấn đề liên quan