2016-11-30 45 views
0

我正在構建一個可以實時獲取視圖的IP攝像頭應用程序,現在我想用Swift記錄MJPEG格式的視頻。使用Swift構建來自UIImage的視頻

let imageData = receivedData , imageData.length > 0, 
     let receivedImage = UIImage(data: imageData as Data) 

這裏我收到每個圖像並將它們保存爲UIImage,問題是如何記錄圖像流?我在Github找到了一個有用的資源,但是我失敗了,鏈接很糟糕:https://gist.github.com/acj/6ae90aa1ebb8cad6b47b

任何一個人都可以給我一些提示,或者你們是否有示例項目?非常感謝,謝謝!

更新:我使用阿姆裏特蒂瓦里的答案代碼,但得到這個錯誤:在啓動會議

if let imageData = receivedData , imageData.length > 0, 
     let receivedImage = UIImage(data: imageData as Data){ 
     let size = CGSize(width: 640, height: 640) 
     writeImagesAsMovie([receivedImage], videoPath: "test.mp4", videoSize: size, videoFPS: 2) 
    } 

我以後pixelBufferPool零: 爲640.0x640.0視頻 錯誤圖像轉換爲視頻創建的資產作家我不確定它是否正確的路徑參數(我想將它保存在Documents目錄中)。請幫助我,謝謝!

回答

0

此問題已經解決。我只是複製並粘貼它。

func writeImagesAsMovie(allImages: [UIImage], videoPath: String, videoSize: CGSize, videoFPS: Int32) { 
    // Create AVAssetWriter to write video 
    guard let assetWriter = createAssetWriter(videoPath, size: videoSize) else { 
     print("Error converting images to video: AVAssetWriter not created") 
     return 
    } 

    // If here, AVAssetWriter exists so create AVAssetWriterInputPixelBufferAdaptor 
    let writerInput = assetWriter.inputs.filter{ $0.mediaType == AVMediaTypeVideo }.first! 
    let sourceBufferAttributes : [String : AnyObject] = [ 
     kCVPixelBufferPixelFormatTypeKey as String : Int(kCVPixelFormatType_32ARGB), 
     kCVPixelBufferWidthKey as String : videoSize.width, 
     kCVPixelBufferHeightKey as String : videoSize.height, 
     ] 
    let pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: writerInput, sourcePixelBufferAttributes: sourceBufferAttributes) 

    // Start writing session 
    assetWriter.startWriting() 
    assetWriter.startSessionAtSourceTime(kCMTimeZero) 
    if (pixelBufferAdaptor.pixelBufferPool == nil) { 
     print("Error converting images to video: pixelBufferPool nil after starting session") 
     return 
    } 

    // -- Create queue for <requestMediaDataWhenReadyOnQueue> 
    let mediaQueue = dispatch_queue_create("mediaInputQueue", nil) 

    // -- Set video parameters 
    let frameDuration = CMTimeMake(1, videoFPS) 
    var frameCount = 0 

    // -- Add images to video 
    let numImages = allImages.count 
    writerInput.requestMediaDataWhenReadyOnQueue(mediaQueue, usingBlock: {() -> Void in 
     // Append unadded images to video but only while input ready 
     while (writerInput.readyForMoreMediaData && frameCount < numImages) { 
      let lastFrameTime = CMTimeMake(Int64(frameCount), videoFPS) 
      let presentationTime = frameCount == 0 ? lastFrameTime : CMTimeAdd(lastFrameTime, frameDuration) 

      if !self.appendPixelBufferForImageAtURL(allImages[frameCount], pixelBufferAdaptor: pixelBufferAdaptor, presentationTime: presentationTime) { 
       print("Error converting images to video: AVAssetWriterInputPixelBufferAdapter failed to append pixel buffer") 
       return 
      } 

      frameCount += 1 
     } 

     // No more images to add? End video. 
     if (frameCount >= numImages) { 
      writerInput.markAsFinished() 
      assetWriter.finishWritingWithCompletionHandler { 
       if (assetWriter.error != nil) { 
        print("Error converting images to video: \(assetWriter.error)") 
       } else { 
        self.saveVideoToLibrary(NSURL(fileURLWithPath: videoPath)) 
        print("Converted images to movie @ \(videoPath)") 
       } 
      } 
     } 
    }) 
} 


func createAssetWriter(path: String, size: CGSize) -> AVAssetWriter? { 
    // Convert <path> to NSURL object 
    let pathURL = NSURL(fileURLWithPath: path) 

    // Return new asset writer or nil 
    do { 
     // Create asset writer 
     let newWriter = try AVAssetWriter(URL: pathURL, fileType: AVFileTypeMPEG4) 

     // Define settings for video input 
     let videoSettings: [String : AnyObject] = [ 
      AVVideoCodecKey : AVVideoCodecH264, 
      AVVideoWidthKey : size.width, 
      AVVideoHeightKey : size.height, 
      ] 

     // Add video input to writer 
     let assetWriterVideoInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: videoSettings) 
     newWriter.addInput(assetWriterVideoInput) 

     // Return writer 
     print("Created asset writer for \(size.width)x\(size.height) video") 
     return newWriter 
    } catch { 
     print("Error creating asset writer: \(error)") 
     return nil 
    } 
} 


func appendPixelBufferForImageAtURL(image: UIImage, pixelBufferAdaptor: AVAssetWriterInputPixelBufferAdaptor, presentationTime: CMTime) -> Bool { 
    var appendSucceeded = false 

    autoreleasepool { 
     if let pixelBufferPool = pixelBufferAdaptor.pixelBufferPool { 
      let pixelBufferPointer = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1) 
      let status: CVReturn = CVPixelBufferPoolCreatePixelBuffer(
       kCFAllocatorDefault, 
       pixelBufferPool, 
       pixelBufferPointer 
      ) 

      if let pixelBuffer = pixelBufferPointer.memory where status == 0 { 
       fillPixelBufferFromImage(image, pixelBuffer: pixelBuffer) 
       appendSucceeded = pixelBufferAdaptor.appendPixelBuffer(pixelBuffer, withPresentationTime: presentationTime) 
       pixelBufferPointer.destroy() 
      } else { 
       NSLog("Error: Failed to allocate pixel buffer from pool") 
      } 

      pixelBufferPointer.dealloc(1) 
     } 
    } 

    return appendSucceeded 
} 


func fillPixelBufferFromImage(image: UIImage, pixelBuffer: CVPixelBufferRef) { 
    CVPixelBufferLockBaseAddress(pixelBuffer, 0) 

    let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer) 
    let rgbColorSpace = CGColorSpaceCreateDeviceRGB() 

    // Create CGBitmapContext 
    let context = CGBitmapContextCreate(
     pixelData, 
     Int(image.size.width), 
     Int(image.size.height), 
     8, 
     CVPixelBufferGetBytesPerRow(pixelBuffer), 
     rgbColorSpace, 
     CGImageAlphaInfo.PremultipliedFirst.rawValue 
    ) 

    // Draw image into context 
    CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage) 

    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0) 
} 


func saveVideoToLibrary(videoURL: NSURL) { 
    PHPhotoLibrary.requestAuthorization { status in 
     // Return if unauthorized 
     guard status == .Authorized else { 
      print("Error saving video: unauthorized access") 
      return 
     } 

     // If here, save video to library 
     PHPhotoLibrary.sharedPhotoLibrary().performChanges({ 
      PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(videoURL) 
     }) { success, error in 
      if !success { 
       print("Error saving video: \(error)") 
      } 
     } 
    } 
} 

如果它不會解決你的問題,那麼我會幫你。

+0

我編輯了我的問題,請幫助我,非常感謝! – EricZhou

+0

你能幫我嗎?非常感謝! – EricZhou

+0

此問題已解決。所以請從http://stackoverflow.com/questions/3741323/how-do-i-export-uiimage-array-as-a-movie幫助 –

相關問題