使用从另一个视频

时间:2017-05-11 18:33:19

标签: swift avfoundation

我正在尝试使用从其他视频中获取的样本缓冲区来创建和保存视频。我使用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
            }
        }
    }
}

我没有错误,代码似乎运行没有问题,除了创建的视频是零字节。任何建议或帮助找出视频未正确保存的原因将不胜感激。谢谢:))

1 个答案:

答案 0 :(得分:1)

每个帧/样本缓冲区都有自己的表示时间戳。移植到新视频时,这些可能不正确。您可以使用

检查时间戳
let timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)

如果您只在输出视频中插入一个视频,解决方案就像更改输出视频的时间轴原点一样简单,只需:

let startTime = CMSampleBufferGetPresentationTimeStamp(firstInputSampleBuffer)
assetWriter.startSession(atSourceTime: startTime)

如果您要插入多个不兼容的时间轴的视频,则需要使用 正确的显示时间戳制作单个样本缓冲区的(浅!)副本,使用

CMSampleBufferCreateCopyWithNewTiming()