2014-12-23 26 views
5

Tôi đang cố gắng hợp nhất hai video tôi nhận được sau khi quay bằng máy ảnh dưới dạng UIImagePickerController. Tôi đã thành công với việc kết hợp các video thành một nhưng tôi có một số vấn đề với định hướng của video.Video không quay bằng AVMutableVideoCompositionLayerInstruction

Như tôi đã hiểu nó với UIImagePickerController là tất cả các video đều được chụp ở chế độ ngang, điều này có nghĩa là các video được ghi ở chế độ dọc được xoay 90 °.

Sau mỗi lần ghi hình tôi thêm các video mới vào một mảng

func imagePickerController(picker: UIImagePickerController!, didFinishPickingMediaWithInfo info:NSDictionary) { 
    let tempImage = info[UIImagePickerControllerMediaURL] as NSURL 
    videos.append(tempImage) 
    let pathString = tempImage.relativePath 
    self.dismissViewControllerAnimated(true, completion: {}) 
} 

Sau đó, khi tôi muốn kết hợp tôi đi qua từng video và tạo một lệnh và thêm các hướng dẫn khác mảng

var composition = AVMutableComposition() 
let trackVideo:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID()) 
let trackAudio:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID()) 
var insertTime = kCMTimeZero 

for i in 0...(videos.count-1){ 
    let moviePathUrl = videos[i] 
    let sourceAsset = AVURLAsset(URL: moviePathUrl, options: nil) 

    let tracks = sourceAsset.tracksWithMediaType(AVMediaTypeVideo) 
    let audios = sourceAsset.tracksWithMediaType(AVMediaTypeAudio) 

    if tracks.count > 0{ 
     var videoDuration = CMTimeRangeMake(kCMTimeZero, sourceAsset.duration); 

     let assetTrack:AVAssetTrack = tracks[0] as AVAssetTrack 
     let assetTrackAudio:AVAssetTrack = audios[0] as AVAssetTrack 

     trackVideo.insertTimeRange(videoDuration, ofTrack: assetTrack, atTime: insertTime, error: nil) 
     trackAudio.insertTimeRange(videoDuration, ofTrack: assetTrackAudio, atTime: insertTime, error: nil) 

     //Rotate 
     var rotater = AVMutableVideoCompositionLayerInstruction(assetTrack: assetTrack) 
     rotater.setTransform(assetTrack.preferredTransform, atTime: insertTime) 
     rotater.setOpacity(0.0, atTime: CMTimeAdd(insertTime, sourceAsset.duration)) 
     instructions.append(rotater) 

     //Resize 
     var resizer = AVMutableVideoCompositionLayerInstruction(assetTrack: assetTrack) 
     resizer.setCropRectangle(CGRectMake(0, 0, 300, 300), atTime: insertTime) 
     instructions.append(resizer) 

     insertTime = CMTimeAdd(insertTime, sourceAsset.duration) 

    } 
} 

Khi tôi đã tạo tất cả các hướng dẫn, tôi thêm chúng vào lệnh chính và tạo phiên xuất.

var instruction = AVMutableVideoCompositionInstruction(); 
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, insertTime); 

instruction.layerInstructions = instructions; 
var mainCompositionInst = AVMutableVideoComposition() 
mainCompositionInst.instructions = NSArray(object: instruction) 

mainCompositionInst.frameDuration = CMTimeMake(1, 60); 
mainCompositionInst.renderSize = CGSizeMake(300, 300); 

var exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) 
exporter.videoComposition = mainCompositionInst; 

Tôi đang thiếu gì?

Trả lời

5

Hãy thử sử dụng trackVideo trong initializer cho lớp Hướng dẫn của bạn để nó sẽ sử dụng 's trackID hơn AVMutableCompositionTrack nguồn tài sản của trackID

Cập nhật:

Bạn chỉ cần một AVMutableVideoCompositionLayerInstruction, vì vậy khai báo nó trước lặp lại với tham số AVMutableCompositionTrack. Sau đó, trên mỗi lần lặp của vòng lặp, hãy thiết lập các thuộc tính cần thiết của lệnh lớp (chuyển đổi, cắt trực tiếp) cho nội dung video hiện tại mà bạn đang làm việc. Bạn đang kiểm soát cách nội dung video trong bản nhạc sáng tác sẽ được hiển thị tại mỗi thời điểm chèn.

Cuối cùng, đặt lớp duy nhấtHướng dẫn trong mảng hướng dẫn và sử dụng điều đó trong bố cục video.

var layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: trackVideo) 
for i in 0...(videos.count-1){ 
    //...your other code here 

    layerInstruction.setTransform(assetTrack.preferredTransform, atTime: insertTime) 
    layerInstruction.setCropRectangle(CGRectMake(0, 0, 300, 300), atTime: insertTime) 
} 

var instruction = AVMutableVideoCompositionInstruction(); 
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, insertTime); 

instruction.layerInstructions = NSArray(object: layerInstruction); 
var mainCompositionInst = AVMutableVideoComposition() 
mainCompositionInst.instructions = NSArray(object: instruction) 
+0

Vẫn còn cùng một vấn đề, không có sự khác biệt –

+0

Thực ra, tôi nghĩ bạn chỉ cần một phiên bản 'rotater'. Chỉ có một bản nhạc thành phần video, vì vậy bạn cần khai báo 'rotater' bên ngoài vòng lặp và đặt biến đổi để áp dụng tại thời điểm bắt đầu của mỗi video mới. Nếu bạn ghép nối video, bạn cũng không cần đặt độ mờ thành 0. Người tiếp theo sẽ chỉ xuất hiện. – jlw

+0

Nếu tôi hiểu bạn đúng, tôi tạo xoay bằng trackVideo ngay trước vòng lặp. Sau đó, bên trong vòng lặp tôi đặt biến đổi giống như tôi đã làm trước đây. Điều này không hoạt động. :/ –

1

Bạn có hai lớp. Bạn cần áp dụng lệnh xoay cho cả hai lớp trong bố cục. Những gì bạn đang làm ở đây là áp dụng lệnh xoay cho chỉ một trong số chúng. Nhận tham chiếu đến cả hai yếu tố trong thành phần video và áp dụng các hướng dẫn riêng biệt cho hai lớp.

+0

Mà không phải là những gì tôi đã làm? Tôi đã thêm nhiều mã của mình vào câu hỏi của mình –

1

Bạn chỉ có thể sử dụng mã đơn giản này, Nó làm việc cho tôi:

var assetVideoTrack = (sourceAsset.tracksWithMediaType(AVMediaTypeVideo)).last as! AVAssetTrack 

    var compositionVideoTrack = (composition.tracksWithMediaType(AVMediaTypeVideo)).last as! AVMutableCompositionTrack 

    if (assetVideoTrack.playable && compositionVideoTrack.playable) { 

     compositionVideoTrack.preferredTransform = assetVideoTrack.preferredTransform 
    } 
Các vấn đề liên quan