我正在尝试使用从其他视频中获取的样本缓冲区来创建和保存视频。我使用Swift Playground并启用了以下设置,以便Dispatch正常工作。
PlaygroundPage.current.needsIndefiniteExecution = true
然后声明资产阅读器并用于读取样本缓冲区。样本缓冲区有效(将随机缓冲区转换为UIImage并显示它显示正确的帧)。
// A sample buffer array is populated from a source video.
// Source video is just a three seconds 720p video at 30fps (m4v).
var sampleBuffer: CMSampleBuffer? = assetReaderOutput.copyNextSampleBuffer()
var sourceSampleBufferArray = [CMSampleBuffer]()
while (sampleBuffer != nil) {
sampleBuffer = assetReaderOutput.copyNextSampleBuffer()
if (sampleBuffer != nil) {
sourceSampleBufferArray.append(sampleBuffer!)
}
}
现在我尝试使用AVAssetWriter将示例缓冲区保存为新视频。
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
let videoOutputURL = URL(fileURLWithPath: documentsPath.appendingPathComponent("AssembledVideo.m4v"))
do {
try FileManager.default.removeItem(at: videoOutputURL as URL)
}
catch {}
let assetWriter = try AVAssetWriter(outputURL: videoOutputURL as URL, fileType: AVFileTypeAppleM4V)
let outputSettings: Dictionary<String, AnyObject> = [
AVVideoCodecKey : AVVideoCodecH264 as AnyObject,
AVVideoWidthKey : 1280 as AnyObject,
AVVideoHeightKey : 720 as AnyObject
];
let assetWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: outputSettings)
assetWriter.add(assetWriterInput)
let mediaQueue = DispatchQueue(label: "DispatchQueue")
if assetWriter.startWriting() {
var counter = sourceSampleBufferArray.count
assetWriter.startSession(atSourceTime: kCMTimeZero)
assetWriterInput.requestMediaDataWhenReady(on: mediaQueue) {
while assetWriterInput.isReadyForMoreMediaData {
if counter > 0 {
assetWriterInput.append(sourceSampleBufferArray[counter - 1])
counter = counter - 1
}
else {
assetWriterInput.markAsFinished()
assetWriter.finishWriting(completionHandler: {
print(assetWriter.outputURL)
})
break
}
}
}
}
我没有错误,代码似乎运行没有问题,除了创建的视频是零字节。任何建议或帮助找出视频未正确保存的原因将不胜感激。谢谢:))
答案 0 :(得分:1)
每个帧/样本缓冲区都有自己的表示时间戳。移植到新视频时,这些可能不正确。您可以使用
检查时间戳let timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
如果您只在输出视频中插入一个视频,解决方案就像更改输出视频的时间轴原点一样简单,只需:
let startTime = CMSampleBufferGetPresentationTimeStamp(firstInputSampleBuffer)
assetWriter.startSession(atSourceTime: startTime)
如果您要插入多个不兼容的时间轴的视频,则需要使用> 正确的显示时间戳制作单个样本缓冲区的(浅!)副本,使用
CMSampleBufferCreateCopyWithNewTiming()