Ios 我的swift VideoWriter代码有什么问题?

Ios 我的swift VideoWriter代码有什么问题?,ios,swift,video,avfoundation,Ios,Swift,Video,Avfoundation,我想从一些图像(作为帧)生成一个mpeg视频。 在我写完视频文件后,我试着把它保存到照片上,但是IOS认为它不兼容: let compatible = AVAsset(url: video_url).isCompatibleWithSavedPhotosAlbum print("COMPATIBILITY", compatible) // false 然后我尝试创建一个AVPlayer来播放视频,但视频无法播放。所以视频文件一定是被破坏了 我仔细检查了代码,但没有发现问题。请帮忙

我想从一些图像(作为帧)生成一个mpeg视频。 在我写完视频文件后,我试着把它保存到照片上,但是IOS认为它不兼容:

  let compatible = AVAsset(url: video_url).isCompatibleWithSavedPhotosAlbum
  print("COMPATIBILITY", compatible)  // false 
然后我尝试创建一个
AVPlayer
来播放视频,但视频无法播放。所以视频文件一定是被破坏了

我仔细检查了代码,但没有发现问题。请帮忙

这是我的密码:

class VideoWriter {

var url:URL?
var assetWriter:AVAssetWriter?

init(url:URL) {
    self.url = url
    do {
        try self.assetWriter = AVAssetWriter(url: self.url!, fileType: AVFileTypeMPEG4)
    } catch {
        print("Fail to create assetWriter")
    }
}


func writeFrames(frames:[UIImage], finishedHandler:@escaping ()->Void) {
    let settings:[String:Any] = [
        AVVideoCodecKey: AVVideoCodecH264,
        AVVideoWidthKey: 480, //CANVAS_SIZE * 4 / 3,
        AVVideoHeightKey: 360 //CANVAS_SIZE
    ]

    let assetWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: settings)

    self.assetWriter?.add(assetWriterInput)

    let bufferAttributes:[String: Any] = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32ARGB)]
    let bufferAdapter = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: assetWriterInput, sourcePixelBufferAttributes: bufferAttributes)
    let frameTime = CMTimeMake(1, 30)

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

    // write the frames here

    let mediaInputQueue = DispatchQueue(label: "mediaInputQueue")

    var i = 0
    let frameNumber = frames.count

    assetWriterInput.requestMediaDataWhenReady(on: mediaInputQueue){
        while(true){
            if(i >= frameNumber){
                break
            }
            if (assetWriterInput.isReadyForMoreMediaData){
                let image = frames[i]
                print("writing frame ", i)
                let pixelBuffer = self.newPixelBufferFrom(cgImage: image.cgImage!)

                var time:CMTime
                if i == 0 {
                    time = kCMTimeZero
                } else {
                    let value = i - 1
                    let lastTime = CMTimeMake(Int64(value), frameTime.timescale)
                    time = CMTimeAdd(lastTime, frameTime)
                }

                bufferAdapter.append(pixelBuffer!, withPresentationTime: time)
                i += 1
            }
        }
        assetWriterInput.markAsFinished()
        self.assetWriter?.finishWriting(completionHandler: {
            Thread.sleep(forTimeInterval: 0.5)
            DispatchQueue.main.sync {
                print("Completed?", self.assetWriter?.status == AVAssetWriterStatus.completed)
                finishedHandler()
            }
        })
    }

}

func newPixelBufferFrom(cgImage:CGImage) -> CVPixelBuffer?{
    let options:[String: Any] = [kCVPixelBufferCGImageCompatibilityKey as String: true, kCVPixelBufferCGBitmapContextCompatibilityKey as String: true]
    var pxbuffer:CVPixelBuffer?
    let frameWidth = 480 //CANVAS_SIZE
    let frameHeight = 360 //CANVAS_SIZE

    let status = CVPixelBufferCreate(kCFAllocatorDefault, frameWidth, frameHeight, kCVPixelFormatType_32ARGB, options as CFDictionary?, &pxbuffer)
    // TODO: throw exception in case of error, don't use assert
    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)
    // TODO: throw exception in case of error, don't use assert
    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
}

}

顺便说一句,我没有添加音频输入,这是MPEG文件所必需的吗?

您说您打算创建一个MPEG视频文件。但是你会使用AVVideoCodecH264吗?@ElTomato是的,这就是问题所在。我认为MP4与H.264编码兼容。。。愚蠢的错误。更改为
AVFileTypeQuickTimeMovie
后,一切正常。谢谢如果你愿意补充一个答案,我会接受的。不,没有必要。别担心。我只是阅读这里的主题来训练我的大脑。我也有同样的问题,你们能帮我吗?你们说你们打算创建一个MPEG视频文件。但是你会使用AVVideoCodecH264吗?@ElTomato是的,这就是问题所在。我认为MP4与H.264编码兼容。。。愚蠢的错误。更改为
AVFileTypeQuickTimeMovie
后,一切正常。谢谢如果你愿意补充一个答案,我会接受的。不,没有必要。别担心。我只是阅读这里的主题来训练我的大脑。我也有同样的问题你们能帮我吗??