微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

swift – 媒体类型的样本缓冲区必须与接收者的媒体类型(“soun”)匹配

基于这个答案 https://stackoverflow.com/a/16035330/1615183我在Swift中创建了以下用于压缩视频的代码

var videoWriter:AVAssetWriter!
var videoWriterInput:AVAssetWriterInput!
var processingQueue:dispatch_queue_t  = dispatch_queue_create("processingQueue1",nil)
var processingQueue2:dispatch_queue_t = dispatch_queue_create("processingQueue2",nil)
var audioWriterInput:AVAssetWriterInput!

func encode(){

    NSFileManager.defaultManager().removeItemAtURL(self.outputFile,error: nil)

    let videoCleanApertureSettings = [AVVideoCleanApertureHeightKey: 720,AVVideoCleanApertureWidthKey: 1280,AVVideoCleanApertureHorizontalOffsetKey: 2,AVVideoCleanApertureVerticalOffsetKey: 2
    ]
    let codecSettings  = [AVVideoAverageBitRateKey: 1024000,AVVideoCleanApertureKey: videoCleanApertureSettings
    ]

    let videoSettings = [AVVideoCodecKey: AVVideoCodecKey,AVVideoCompressionPropertiesKey: codecSettings,AVVideoHeightKey: 720,AVVideoWidthKey: 1280]


    //setup video writer
    var error:NSError?
    let asset = AVURLAsset(URL: self.inputFile,options: nil)

    let videoTrack:AVAssetTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0] as AVAssetTrack
    let videoSize:CGSize = videoTrack.naturalSize

    videoWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo,outputSettings: videoSettings)
    videoWriterInput.expectsMediaDataInRealTime = false
    videoWriterInput.transform = videoTrack.preferredTransform
    videoWriter = AVAssetWriter(URL: self.outputFile,fileType: AVFileTypeQuickTimeMovie,error: &error)

    if videoWriter.canAddInput(videoWriterInput) {
        videoWriter.addInput(videoWriterInput)
    }else{
        println("cant add video writer input")
        return
    }

    //setup video reader

    let videoReaderSettings = [ kCVPixelBufferPixelFormatTypeKey as String : kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]

    let videoReaderOutput:AVAssetReaderTrackOutput = AVAssetReaderTrackOutput(track: videoTrack,outputSettings: videoReaderSettings) // should it be videoReaderSettings?

    let videoReader:AVAssetReader = AVAssetReader(asset: asset,error: &error)
    if videoReader.canAddOutput(videoReaderOutput) {
        videoReader.addOutput(videoReaderOutput)
    }

    //setup audio writer
    audioWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeAudio,outputSettings: nil)

    audioWriterInput.expectsMediaDataInRealTime = false
    if videoWriter.canAddInput(audioWriterInput){
        videoWriter.addInput(audioWriterInput)
    }

    //setup audio reader
    let audioTrack:AVAssetTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0] as AVAssetTrack
    let audioReaderOutput:AVAssetReaderOutput = AVAssetReaderTrackOutput(track: audioTrack,outputSettings: nil)
    let audioReader:AVAssetReader = AVAssetReader(asset: asset,error: &error)

    if audioReader.canAddOutput(audioReaderOutput) {
        audioReader.addOutput(audioReaderOutput)
    }else {
        println("cant add audio reader")
        return
    }


    videoWriter.startWriting()
    videoReader.startReading()

    videoWriter.startSessionAtSourceTime(kCMTimeZero)




    videoWriterInput.requestMediaDataWhenReadyOnQueue(processingQueue) {
        while self.videoWriterInput.readyForMoreMediaData {
            println("First loop")
            var sampleBuffer = videoReaderOutput.copyNextSampleBuffer()
            if videoReader.status == .Reading && sampleBuffer != nil {
                println("Appending")
                self.videoWriterInput.appendSampleBuffer(sampleBuffer)
            }else {
                self.videoWriterInput.markAsFinished()
                if videoReader.status == .Completed {

                    audioReader.startReading()
                    self.videoWriter.startSessionAtSourceTime(kCMTimeZero)

                    self.audioWriterInput.requestMediaDataWhenReadyOnQueue(self.processingQueue2) {
                        while self.audioWriterInput.readyForMoreMediaData {
                            println("Second loop")
                            var sampleBuffer2:CMSampleBufferRef? = audioReaderOutput.copyNextSampleBuffer()
                            if audioReader.status == .Reading && sampleBuffer2 != nil {
                                self.audioWriterInput.appendSampleBuffer(sampleBuffer2)
                            }else {
                                self.audioWriterInput.markAsFinished()
                                println("Audio finish")
                                self.videoWriter.finishWritingWithCompletionHandler { println("Done") }
                            }
                        }

                    }


                }
                else {
                    println("Video Reader not completed")
                }
                println("Finished")
                break
            }// else vidoSampleBuffer
        }
    }

 }

但是,如果我删除音频部分,我只得到一个文件.如果我在第二次循环运行时第一次按原样运行它没有问题,但在第二次迭代时它崩溃并出现以下错误

*** Terminating app due to uncaught exception 'NSinvalidargumentexception',reason: '*** -[AVAssetWriterInput appendSampleBuffer:] Media type of sample buffer must match receiver's media type ("soun")'

有没有人有同样的问题?

解决方法

将AVMediaTypeVideo更改为音频:

let audioTrack:AVAssetTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0] as AVAssetTrack

应该

let audioTrack:AVAssetTrack = asset.tracksWithMediaType(AVMediaTypeAudio)[0] as AVAssetTrack

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐