从video文件中删除音频

我正在尝试从手机库中的MOV类型video中删除音轨。 我知道我可以在播放时静音,但我计划上传用户video,将音频输出并减小文件大小是有意义的。

我已经尝试将obj-c代码从这个答案转换为swift,但我要么搞砸了转换,要么就是没有从文件中取出音频。

任何帮助将不胜感激。

你可以试试这个

NSString * initPath1 = VideoLocalPath; AVMutableComposition *composition = [AVMutableComposition composition]; NSString *inputVideoPath = initPath1; AVURLAsset * sourceAsset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:inputVideoPath] options:nil]; AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; BOOL ok = NO; AVAssetTrack * sourceVideoTrack = [[sourceAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; CMTimeRange x = CMTimeRangeMake(kCMTimeZero, [sourceAsset duration]); ok = [compositionVideoTrack insertTimeRange:x ofTrack:sourceVideoTrack atTime:kCMTimeZero error:nil]; if([[NSFileManager defaultManager] fileExistsAtPath:initPath1]) { [[NSFileManager defaultManager] removeItemAtPath:initPath1 error:nil]; } NSURL *url = [[NSURL alloc] initFileURLWithPath: initPath1]; AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetHighestQuality]; exporter.outputURL=url; exporter.outputFileType = @"com.apple.quicktime-movie"; [exporter exportAsynchronouslyWithCompletionHandler:^{ [self savefinalVideoFileToDocuments:exporter.outputURL]; }]; -(void)savefinalVideoFileToDocuments:(NSURL *)url { NSString *storePath = [[self applicationCacheDirectory] stringByAppendingPathComponent:@"Videos"]; NSData * movieData = [NSData dataWithContentsOfURL:url]; [movieData writeToFile:storePath atomically:YES]; } - (NSString *)applicationCacheDirectory { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; return documentsDirectory; } 

在迅速

 var initPath1 = VideoLocalPath var composition = AVMutableComposition.composition() var inputVideoPath = initPath1 var sourceAsset = AVURLAsset(URL: URL(fileURLWithPath: inputVideoPath), options: nil) var compositionVideoTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid) var ok = false var sourceVideoTrack = sourceAsset.tracks(withMediaType: AVMediaTypeVideo)[0] var x = CMTimeRangeMake(kCMTimeZero, sourceAsset.duration) do { ok = try compositionVideoTrack.insertTimeRange(x, of: sourceVideoTrack, atTime: kCMTimeZero) } catch let error { } if FileManager.default.fileExists(atPath: initPath1) { do { try FileManager.default.removeItem(at: initPath1) } catch let error { } } var url = URL(fileURLWithPath: initPath1) var exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) exporter.outputURL = url func savefinalVideoFile(toDocuments url: URL) { var storePath = NSURL(fileURLWithPath: self.applicationCacheDirectory()).appendingPathComponent("Videos")!.absoluteString var movieData = Data(contentsOf: url) movieData.write(toFile: storePath, atomically: true) } func applicationCacheDirectory() -> String { var paths = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true) var documentsDirectory = (paths.count > 0) ? paths[0] : nil return documentsDirectory } 

最热门的答案对我不起作用+我有video轮换问题。 我最后通过添加参数muteSound: Bool修改了我的video压缩方法。

我使用比特率2300000来保持video看起来不错,但是尺寸比原来小3-4倍。

我会保持这个问题的开放性,并将最受欢迎的问题标记为正确。 也许有人可以想出更简单的东西。

 func compressVideo(inputURL: NSURL, outputURL: NSURL, bitRate: Int, muteSound: Bool, onDone: () -> ()) { let videoAsset = AVURLAsset(URL: inputURL, options: nil) let videoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0] let videoSize = videoTrack.naturalSize let videoWriterCompressionSettings = [ AVVideoAverageBitRateKey: bitRate ] let videoWriterSettings:[String : AnyObject] = [ AVVideoCodecKey : AVVideoCodecH264, AVVideoCompressionPropertiesKey : videoWriterCompressionSettings, AVVideoWidthKey : Int(videoSize.width), AVVideoHeightKey : Int(videoSize.height) ] let videoWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: videoWriterSettings) videoWriterInput.expectsMediaDataInRealTime = true videoWriterInput.transform = videoTrack.preferredTransform let videoWriter = try! AVAssetWriter(URL: outputURL, fileType: AVFileTypeQuickTimeMovie) videoWriter.addInput(videoWriterInput) let videoReaderSettings:[String : AnyObject] = [ kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) ] let videoReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: videoReaderSettings) let videoReader = try! AVAssetReader(asset: videoAsset) videoReader.addOutput(videoReaderOutput) let audioWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeAudio, outputSettings: nil) audioWriterInput.expectsMediaDataInRealTime = false videoWriter.addInput(audioWriterInput) let audioTrack = videoAsset.tracksWithMediaType(AVMediaTypeAudio)[0] let audioReaderOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: nil) let audioReader = try! AVAssetReader(asset: videoAsset) if muteSound == false { audioReader.addOutput(audioReaderOutput) } videoWriter.startWriting() videoReader.startReading() videoWriter.startSessionAtSourceTime(kCMTimeZero) let processingQueue = dispatch_queue_create("processingQueue1", nil) videoWriterInput.requestMediaDataWhenReadyOnQueue(processingQueue, usingBlock: {() -> Void in while videoWriterInput.readyForMoreMediaData { let sampleBuffer:CMSampleBuffer? = videoReaderOutput.copyNextSampleBuffer() if videoReader.status == .Reading && sampleBuffer != nil { videoWriterInput.appendSampleBuffer(sampleBuffer!) } else { videoWriterInput.markAsFinished() if videoReader.status == .Completed { if muteSound { // return without sound videoWriter.finishWritingWithCompletionHandler({() -> Void in onDone() }) } else { audioReader.startReading() videoWriter.startSessionAtSourceTime(kCMTimeZero) let processingQueue = dispatch_queue_create("processingQueue2", nil) audioWriterInput.requestMediaDataWhenReadyOnQueue(processingQueue, usingBlock: {() -> Void in while audioWriterInput.readyForMoreMediaData { let sampleBuffer:CMSampleBufferRef? = audioReaderOutput.copyNextSampleBuffer() if audioReader.status == .Reading && sampleBuffer != nil { audioWriterInput.appendSampleBuffer(sampleBuffer!) } else { audioWriterInput.markAsFinished() if audioReader.status == .Completed { videoWriter.finishWritingWithCompletionHandler({() -> Void in onDone() }) } } } }) } } } } }) } 

在Swift 3中,

 func removeAudioFromVideo(_ videoPath: String) { let initPath1: String = videoPath let composition = AVMutableComposition() let inputVideoPath: String = initPath1 let sourceAsset = AVURLAsset(url: URL(fileURLWithPath: inputVideoPath), options: nil) let compositionVideoTrack: AVMutableCompositionTrack? = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid) let sourceVideoTrack: AVAssetTrack? = sourceAsset.tracks(withMediaType: AVMediaTypeVideo)[0] let x: CMTimeRange = CMTimeRangeMake(kCMTimeZero, sourceAsset.duration) _ = try? compositionVideoTrack!.insertTimeRange(x, of: sourceVideoTrack!, at: kCMTimeZero) if FileManager.default.fileExists(atPath: initPath1) { try? FileManager.default.removeItem(atPath: initPath1) } let url = URL(fileURLWithPath: initPath1) let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) exporter?.outputURL = url exporter?.outputFileType = "com.apple.quicktime-movie" exporter?.exportAsynchronously(completionHandler: {() -> Void in self.saveFinalVideoFile(toDocuments: exporter!.outputURL!) }) } func saveFinalVideoFile(toDocuments url: URL) { let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("Videos") let movieData = try? Data(contentsOf: url) try? movieData?.write(to: fileURL, options: .atomic) }