2016-11-24 55 views
4

我需要导出一个UIImage的数组,并构建一个电影,将一些文本放在图像的前方,如果它也可能是音乐。你可以给我一个代码的手?我只找到Objective-c和旧版本Swift如何将UIImage数组作为Swift 3中的影片导出?

+2

的[从\ [UIImage的\],夫特创建影片]可能的复制(http://stackoverflow.com/questions/30470154/create-movie-from-uiimage-swift) –

+0

THOS是有点广泛的,你已经尝试过什么,是所有的图像相同的大小等? – Scriptable

+0

可能的大小不同,我在swift 3中找不到任何完整的解决方案。 –

回答

1

这是第一个答案我张贴的问题:create movie from [UIImage], Swift

以下是答案的副本:

我认为转换张贴“@Cameron E”斯威夫特3 Objective-C代码,它正在工作。答案的链接:@Cameron E's CEMovieMaker

import Foundation 
import AVFoundation 
import UIKit 

public typealias CXEMovieMakerCompletion = (URL) -> Void 
typealias CXEMovieMakerUIImageExtractor = (AnyObject) -> UIImage? 


public class CXEImagesToVideo: NSObject{ 
var assetWriter:AVAssetWriter! 
var writeInput:AVAssetWriterInput! 
var bufferAdapter:AVAssetWriterInputPixelBufferAdaptor! 
var videoSettings:[String : Any]! 
var frameTime:CMTime! 
var fileURL:URL! 

var completionBlock: CXEMovieMakerCompletion? 
var movieMakerUIImageExtractor:CXEMovieMakerUIImageExtractor? 


public class func videoSettings(codec:String, width:Int, height:Int) -> [String: Any]{ 
    if(Int(width) % 16 != 0){ 
     print("warning: video settings width must be divisible by 16") 
    } 

    let videoSettings:[String: Any] = [AVVideoCodecKey: AVVideoCodecH264, 
         AVVideoWidthKey: width, 
         AVVideoHeightKey: height] 

    return videoSettings 
} 

public init(videoSettings: [String: Any]) { 
    super.init() 

    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) 
    let tempPath = paths[0] + "/exprotvideo.mp4" 
    if(FileManager.default.fileExists(atPath: tempPath)){ 
     guard (try? FileManager.default.removeItem(atPath: tempPath)) != nil else { 
      print("remove path failed") 
      return 
     } 
    } 

    self.fileURL = URL(fileURLWithPath: tempPath) 
    self.assetWriter = try! AVAssetWriter(url: self.fileURL, fileType: AVFileTypeQuickTimeMovie) 

    self.videoSettings = videoSettings 
    self.writeInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: videoSettings) 
    assert(self.assetWriter.canAdd(self.writeInput), "add failed") 

    self.assetWriter.add(self.writeInput) 
    let bufferAttributes:[String: Any] = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32ARGB)] 
    self.bufferAdapter = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: self.writeInput, sourcePixelBufferAttributes: bufferAttributes) 
    self.frameTime = CMTimeMake(1, 1) 
} 

public func createMovieFrom(urls: [URL], withCompletion: @escaping CXEMovieMakerCompletion){ 
    self.createMovieFromSource(images: urls as [AnyObject], extractor:{(inputObject:AnyObject) ->UIImage? in 
     return UIImage(data: try! Data(contentsOf: inputObject as! URL))}, withCompletion: withCompletion) 
} 

public func createMovieFrom(images: [UIImage], withCompletion: @escaping CXEMovieMakerCompletion){ 
    self.createMovieFromSource(images: images, extractor: {(inputObject:AnyObject) -> UIImage? in 
    return inputObject as? UIImage}, withCompletion: withCompletion) 
} 

func createMovieFromSource(images: [AnyObject], extractor: @escaping CXEMovieMakerUIImageExtractor, withCompletion: @escaping CXEMovieMakerCompletion){ 
    self.completionBlock = withCompletion 

    self.assetWriter.startWriting() 
    self.assetWriter.startSession(atSourceTime: kCMTimeZero) 

    let mediaInputQueue = DispatchQueue(label: "mediaInputQueue") 
    var i = 0 
    let frameNumber = images.count 

    self.writeInput.requestMediaDataWhenReady(on: mediaInputQueue){ 
     while(true){ 
      if(i >= frameNumber){ 
       break 
      } 

      if (self.writeInput.isReadyForMoreMediaData){ 
       var sampleBuffer:CVPixelBuffer? 
       autoreleasepool{ 
        let img = extractor(images[i]) 
        if img == nil{ 
         i += 1 
         print("Warning: counld not extract one of the frames") 
         //continue 
        } 
        sampleBuffer = self.newPixelBufferFrom(cgImage: img!.cgImage!) 
       } 
       if (sampleBuffer != nil){ 
        if(i == 0){ 
         self.bufferAdapter.append(sampleBuffer!, withPresentationTime: kCMTimeZero) 
        }else{ 
         let value = i - 1 
         let lastTime = CMTimeMake(Int64(value), self.frameTime.timescale) 
         let presentTime = CMTimeAdd(lastTime, self.frameTime) 
         self.bufferAdapter.append(sampleBuffer!, withPresentationTime: presentTime) 
        } 
        i = i + 1 
       } 
      } 
     } 
     self.writeInput.markAsFinished() 
     self.assetWriter.finishWriting { 
      DispatchQueue.main.sync { 
       self.completionBlock!(self.fileURL) 
      } 
     } 
    } 
} 

func newPixelBufferFrom(cgImage:CGImage) -> CVPixelBuffer?{ 
    let options:[String: Any] = [kCVPixelBufferCGImageCompatibilityKey as String: true, kCVPixelBufferCGBitmapContextCompatibilityKey as String: true] 
    var pxbuffer:CVPixelBuffer? 
    let frameWidth = self.videoSettings[AVVideoWidthKey] as! Int 
    let frameHeight = self.videoSettings[AVVideoHeightKey] as! Int 

    let status = CVPixelBufferCreate(kCFAllocatorDefault, frameWidth, frameHeight, kCVPixelFormatType_32ARGB, options as CFDictionary?, &pxbuffer) 
    assert(status == kCVReturnSuccess && pxbuffer != nil, "newPixelBuffer failed") 

    CVPixelBufferLockBaseAddress(pxbuffer!, CVPixelBufferLockFlags(rawValue: 0)) 
    let pxdata = CVPixelBufferGetBaseAddress(pxbuffer!) 
    let rgbColorSpace = CGColorSpaceCreateDeviceRGB() 
    let context = CGContext(data: pxdata, width: frameWidth, height: frameHeight, bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pxbuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue) 
    assert(context != nil, "context is nil") 

    context!.concatenate(CGAffineTransform.identity) 
    context!.draw(cgImage, in: CGRect(x: 0, y: 0, width: cgImage.width, height: cgImage.height)) 
    CVPixelBufferUnlockBaseAddress(pxbuffer!, CVPixelBufferLockFlags(rawValue: 0)) 
    return pxbuffer 
} 
} 

用法:

 var uiImages = [UIImage]() 

/** add image to uiImages */ 

let settings = CXEImagesToVideo.videoSettings(codec: AVVideoCodecH264, width: (uiImages[0].cgImage?.width)!, height: (uiImages[0].cgImage?.height)!) 
let movieMaker = CXEImagesToVideo(videoSettings: settings) 
movieMaker.createMovieFrom(images: uiImages){ (fileURL:URL) in 
    let video = AVAsset(url: fileURL) 
    let playerItem = AVPlayerItem(asset: video) 
    let player = CXEPlayer() 
    player.setPlayerItem(playerItem: playerItem) 

    self.playerView.player = player 
} 

出口或fileURL播放视频。 要点:ImagesToAssetURL async and sync

相关问题