【问题标题】:Extract Audio from Video AVFoundation从视频 AVFoundation 中提取音频
【发布时间】:2015-08-07 13:54:45
【问题描述】:
func extractAudioFromVideo(videoUrl:NSURL, audioPath:String){
    //2
    var asset = AVURLAsset(URL: videoUrl, options: nil)
    asset.loadValuesAsynchronouslyForKeys(NSArray(object: "tracks") as [AnyObject], completionHandler: { () -> Void in
        var audioTrack = asset.tracksWithMediaType(AVMediaTypeAudio)[0] as! AVAssetTrack

        var audioComposition = AVMutableComposition()

        var audioCompositionTrack:AVMutableCompositionTrack!

        audioCompositionTrack = audioComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())
        audioCompositionTrack.insertTimeRange(audioTrack.timeRange, ofTrack: audioTrack, atTime: CMTimeMake(0, 1), error: nil)

        var exportSession = AVAssetExportSession(asset: audioComposition, presetName: AVAssetExportPresetAppleM4A)
        var toFileUrl = NSURL(fileURLWithPath: audioPath)

        exportSession.outputURL = toFileUrl
        exportSession.outputFileType = "com.apple.m4a-audio"

        exportSession.exportAsynchronouslyWithCompletionHandler({ () -> Void in
            if exportSession.status == AVAssetExportSessionStatus.Completed {
                println("Succes")
            }else{
                println("not working")
            }
        })

    })

}

我正在使用上面的代码从视频中获取音频,但它正在打印“不工作”

我的音频路径是:

var outStr = NSBundle.mainBundle().pathForResource("cheeseburger", ofType: "m4a")

请帮我解决这个问题

谢谢

【问题讨论】:

    标签: ios swift avfoundation


    【解决方案1】:

    我已经重写了 Swift 4.0 的答案,因为一些 API 更改破坏了前一个。

    import AVFoundation
    
    extension AVAsset {
        // Provide a URL for where you wish to write
        // the audio file if successful
        func writeAudioTrack(to url: URL,
                             success: @escaping () -> (),
                             failure: @escaping (Error) -> ()) {
            do {
                let asset = try audioAsset()
                asset.write(to: url, success: success, failure: failure)
            } catch {
                failure(error)
            }
        }
    
        private func write(to url: URL,
                           success: @escaping () -> (),
                           failure: @escaping (Error) -> ()) {
            // Create an export session that will output an
            // audio track (M4A file)
            guard let exportSession = AVAssetExportSession(asset: self,
                                                           presetName: AVAssetExportPresetAppleM4A) else {
                                                            // This is just a generic error
                                                            let error = NSError(domain: "domain",
                                                                                code: 0,
                                                                                userInfo: nil)
                                                            failure(error)
    
                                                            return
            }
    
            exportSession.outputFileType = .m4a
            exportSession.outputURL = url
    
            exportSession.exportAsynchronously {
                switch exportSession.status {
                case .completed:
                    success()
                case .unknown, .waiting, .exporting, .failed, .cancelled:
                    let error = NSError(domain: "domain", code: 0, userInfo: nil)
                    failure(error)
                }
            }
        }
    
        private func audioAsset() throws -> AVAsset {
            // Create a new container to hold the audio track
            let composition = AVMutableComposition()
            // Create an array of audio tracks in the given asset
            // Typically, there is only one
            let audioTracks = tracks(withMediaType: .audio)
    
            // Iterate through the audio tracks while
            // Adding them to a new AVAsset
            for track in audioTracks {
                let compositionTrack = composition.addMutableTrack(withMediaType: .audio,
                                                                   preferredTrackID: kCMPersistentTrackID_Invalid)
                do {
                    // Add the current audio track at the beginning of
                    // the asset for the duration of the source AVAsset
                    try compositionTrack?.insertTimeRange(track.timeRange,
                                                          of: track,
                                                          at: track.timeRange.start)
                } catch {
                    throw error
                }
            }
    
            return composition
        }
    }
    

    然后,您调用扩展,并依靠不同的闭包来处理成功和失败。此示例中的错误处理非常原始,因此您需要在实现时对其进行改进。

    asset.writeAudioTrack(to: url, success: {
        print("Success")
    }) { (error) in
        print(error.localizedDescription)
    }
    

    【讨论】:

    • 操作无法完成。 (域错误 0。),但是,它只对某些文件执行此操作,否则它可以工作。
    • 显示:错误 Domain=domain Code=0 "(null)"
    • @sharadchauhan 这是我创建的一般错误,表示创建 exportSession 失败。这可能表明您正在使用的资产有问题。检查以确保它有状态者的音轨。
    • @CodeBender 有。但它也有绿屏。这可能是问题吗?
    【解决方案2】:

    来自我的项目(Swift 4.1

    import AVFoundation
    extension AVAsset {
    
        func writeAudioTrackToURL(_ url: URL, completion: @escaping (Bool, Error?) -> ()) {
            do {
                let audioAsset = try self.audioAsset()
                audioAsset.writeToURL(url, completion: completion)
            } catch (let error as NSError){
                completion(false, error)
            }
        }
    
        func writeToURL(_ url: URL, completion: @escaping (Bool, Error?) -> ()) {
    
            guard let exportSession = AVAssetExportSession(asset: self, presetName: AVAssetExportPresetAppleM4A) else {
                completion(false, nil)
                return
            }
    
            exportSession.outputFileType = .m4a
            exportSession.outputURL      = url
    
            exportSession.exportAsynchronously {
                switch exportSession.status {
                case .completed:
                    completion(true, nil)
                case .unknown, .waiting, .exporting, .failed, .cancelled:
                    completion(false, nil)
                }
            }
        }
    
        func audioAsset() throws -> AVAsset {
    
            let composition = AVMutableComposition()
            let audioTracks = tracks(withMediaType: .audio)
    
            for track in audioTracks {
    
                let compositionTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
                try compositionTrack?.insertTimeRange(track.timeRange, of: track, at: track.timeRange.start)
                compositionTrack?.preferredTransform = track.preferredTransform
            }
            return composition
        }
    }
    

    这样使用

        let url = Bundle.main.url(forResource: "video", withExtension: "m4v")!
        let asset = AVURLAsset(url: url, options: nil)
    
        let pathWhereToSave = "<#path#>"
        asset.writeAudioTrackToURL(URL(fileURLWithPath: pathWhereToSave)) { (success, error) -> () in
            if !success {
                print(error)
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2018-04-03
      • 2010-10-09
      • 2020-06-26
      • 2014-03-18
      • 2015-05-16
      • 2011-01-08
      • 2012-07-10
      • 2011-07-27
      相关资源
      最近更新 更多