141 lines
4.2 KiB
Swift
141 lines
4.2 KiB
Swift
//
|
|
// CreateVideoByBuffer.swift
|
|
// tdvideo
|
|
//
|
|
// Created by mac on 2024/2/22.
|
|
//
|
|
|
|
|
|
import UIKit
|
|
import AVFoundation
|
|
import Photos
|
|
|
|
class CreateVideoByBuffer: NSObject {
|
|
|
|
private var videoWriter: AVAssetWriter?
|
|
private var videoWriterInput: AVAssetWriterInput?
|
|
private var adaptor: AVAssetWriterInputPixelBufferAdaptor?
|
|
private var outputURL: URL?
|
|
private var isWriting: Bool = false
|
|
|
|
init(outputURL: URL) {
|
|
super.init()
|
|
self.outputURL = outputURL
|
|
setupWriter()
|
|
}
|
|
|
|
private func setupWriter() {
|
|
guard let outputURL = outputURL else {
|
|
print("Output URL is nil")
|
|
return
|
|
}
|
|
|
|
let width = 1920 // Example width
|
|
let height = 1080 // Example height
|
|
|
|
// 设置视频的输出设置
|
|
let outputSettings: [String: Any] = [
|
|
AVVideoCodecKey: AVVideoCodecType.h264,
|
|
AVVideoWidthKey: width,
|
|
AVVideoHeightKey: height
|
|
]
|
|
|
|
// 创建视频写入器
|
|
do {
|
|
videoWriter = try AVAssetWriter(outputURL: outputURL, fileType: .mov)
|
|
} catch {
|
|
print("Error creating AVAssetWriter: \(error)")
|
|
return
|
|
}
|
|
|
|
// 创建视频写入器输入
|
|
videoWriterInput = AVAssetWriterInput(mediaType: .video, outputSettings: outputSettings)
|
|
|
|
// 检查创建视频写入器输入是否成功
|
|
guard let videoWriterInput = videoWriterInput else {
|
|
print("Failed to create video writer input")
|
|
return
|
|
}
|
|
|
|
// 将视频写入器输入添加到视频写入器
|
|
guard let videoWriter = videoWriter, videoWriter.canAdd(videoWriterInput) else {
|
|
print("Cannot add video writer input to video writer")
|
|
return
|
|
}
|
|
|
|
videoWriter.add(videoWriterInput)
|
|
|
|
// 创建像素缓冲适配器
|
|
adaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: videoWriterInput, sourcePixelBufferAttributes: nil)
|
|
|
|
// 开始写入视频
|
|
guard videoWriter.startWriting() else {
|
|
print("Failed to start writing")
|
|
return
|
|
}
|
|
videoWriter.startSession(atSourceTime: .zero)
|
|
}
|
|
|
|
func createVideo(from imageBuffer: CVImageBuffer, presentationTime: CMTime) {
|
|
guard isWriting else {
|
|
print("Video writer is not initialized or already writing")
|
|
return
|
|
}
|
|
|
|
// 将每个帧的图像缓冲区写入视频
|
|
let pixelBuffer = imageBuffer
|
|
guard let adaptor = adaptor else {
|
|
print("Failed to get pixel buffer adaptor")
|
|
return
|
|
}
|
|
|
|
guard let videoWriterInput = videoWriterInput else {
|
|
print("Failed to get video writer input")
|
|
return
|
|
}
|
|
|
|
guard adaptor.append(pixelBuffer, withPresentationTime: presentationTime) else {
|
|
print("Failed to append pixel buffer")
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
func videoCreationFinished(error: Error?) {
|
|
|
|
// 设置写入标志位
|
|
isWriting = false
|
|
|
|
// 完成视频写入
|
|
guard let videoWriter = videoWriter, let videoWriterInput = videoWriterInput else {
|
|
print("Video writer or writer input is nil")
|
|
return
|
|
}
|
|
|
|
videoWriterInput.markAsFinished()
|
|
videoWriter.finishWriting { [weak self] in
|
|
guard let self = self else { return }
|
|
if let error = videoWriter.error {
|
|
print("Error finishing AVAssetWriter: \(error)")
|
|
} else {
|
|
print("Video creation finished at \(self.outputURL!)")
|
|
// 保存到相册
|
|
saveVideoToAlbum(url: outputURL!)
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
func saveVideoToAlbum(url: URL) {
|
|
PHPhotoLibrary.shared().performChanges {
|
|
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url)
|
|
} completionHandler: { success, error in
|
|
if success {
|
|
print("Video saved to album")
|
|
} else {
|
|
print("Failed to save video to album: \(error?.localizedDescription ?? "Unknown error")")
|
|
}
|
|
}
|
|
}
|
|
}
|